//======================================================================= // // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved. // // File: state.cpp // // Creator: PeterWi // // Purpose: State management functions. // //======================================================================= #include "pch.h" #pragma hdrstop // global state object pointer CAUState *gpState; BOOL gfDownloadStarted; //to be used to distinguish connection detection and actually downloading mode #ifdef DBG const TCHAR REG_AUCONNECTWAIT[] = _T("ConnectWait"); const TCHAR REG_SELFUPDATE_URL[] = _T("SelfUpdateURL"); #endif const TCHAR REG_WUSERVER_URL[] = _T("WUServer"); const TCHAR REG_WUSTATUSSERVER_URL[] = _T("WUStatusServer"); const TCHAR REG_IDENT_URL[] = _T("IdentServer"); const TCHAR WU_LIVE_URL[] = _T("http://windowsupdate.microsoft.com/v4"); //AU configurable registry settings const TCHAR REG_AUOPTIONS[] = _T("AUOptions"); //REG_DWORD const TCHAR REG_AUSTATE[] = _T("AUState"); //REG_DWORD const TCHAR REG_AUDETECTIONSTARTTIME[] = _T("DetectionStartTime"); //REG_SZ const TCHAR REG_AUSCHEDINSTALLDAY[] = _T("ScheduledInstallDay"); //REG_DWORD const TCHAR REG_AUSCHEDINSTALLTIME[] = _T("ScheduledInstallTime"); //REG_DWORD const TCHAR REG_AUSCHEDINSTALLDATE[] = _T("ScheduledInstallDate"); //REG_SZ const TCHAR REG_AUNOAUTOUPDATE[] = _T("NoAutoUpdate"); // REG_DWORD 1 means AU be disabled //======================================================================= // CAUState::HrCreateState // // Static function to create the global state object in memory. //======================================================================= /*static*/ HRESULT CAUState::HrCreateState(void) { HRESULT hr; if ( NULL == (gpState = new CAUState()) ) { hr = E_OUTOFMEMORY; goto done; } if (NULL == (gpState->m_hMutex = CreateMutex(NULL, FALSE, NULL))) { DEBUGMSG("CAUState::HrCreateState() fail to CreateMutex with error %d",GetLastError()); hr = E_FAIL; goto done; } hr = gpState->HrInit(TRUE); done: return hr; } CAUState::CAUState() { //only initialize members that destructor cares m_hMutex = NULL; #ifdef DBG m_pszTestSelfUpdateURL = NULL; #endif m_pszTestIdentServerURL = NULL; } void CAUState::m_Reset(void) { m_PolicySettings.Reset(); m_dwState = AUSTATE_OUTOFBOX; #ifdef DBG SafeFreeNULL(m_pszTestSelfUpdateURL); #endif SafeFreeNULL(m_pszTestIdentServerURL); m_fWin2K = FALSE; m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE; m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE; m_dwCltAction = AUCLT_ACTION_NONE; m_fDisconnected = FALSE; } //======================================================================= // CAUState::HrInit // // Initialize state. //======================================================================= HRESULT CAUState::HrInit(BOOL fInit) { HRESULT hr = S_OK; if (!m_lock()) { return HRESULT_FROM_WIN32(GetLastError()); } m_dwCltAction = AUCLT_ACTION_NONE; m_fDisconnected = FALSE; m_PolicySettings.m_fRegAUOptionsSpecified = TRUE; m_Reset(); m_ReadRegistrySettings(fInit); // read policy information. If any domain policy setting is // invalid, we revert to admin policy settings. if ( FAILED(hr = m_ReadPolicy(fInit)) ) // called after getting m_dwState due to dependency { // only case this function fails is when out of memory goto done; } if (!gPingStatus.SetCorpServerUrl(m_PolicySettings.m_pszWUStatusServerURL)) { hr = E_FAIL; goto done; } if ( FAILED(hr = m_ReadTestOverrides())) {//only case this function fails is when out of memory goto done; } if (!m_PolicySettings.m_fRegAUOptionsSpecified) { if (m_dwState >= AUSTATE_DETECT_PENDING) { //invalid option needs user attention via wizard m_dwState = AUSTATE_OUTOFBOX; } } else if (!fOptionEnabled()) { SetState(AUSTATE_DISABLED); } else if (m_dwState < AUSTATE_DETECT_PENDING) { // if domain policy set or auoption already configured, we skip the wizard state. SetState(AUSTATE_DETECT_PENDING); } m_fWin2K = IsWin2K(); gfDownloadStarted = FALSE; done: #ifdef DBG if ( SUCCEEDED(hr) ) { m_DbgDumpState(); } #endif m_unlock(); return hr; } BOOL fURLChanged(LPCTSTR url1, LPCTSTR url2) { if (url1 == NULL && url2 == NULL) { return FALSE; } if ((url1 == NULL && url2 != NULL ) || (url1 != NULL && url2 == NULL)) { return TRUE; } return 0 != StrCmpI(url1, url2); } //read Policy info again and refresh state object (only care about possible admin policy change now) //return S_FALSE if nothing changed //return S_OK if policy changed and state successfully updated // *pActCode will indicate what to do HRESULT CAUState::Refresh(enumAUPOLICYCHANGEACTION OUT *pActCode) { AUPolicySettings newsettings; HRESULT hr; if (!m_lock()) { return HRESULT_FROM_WIN32(GetLastError()); } *pActCode = AUPOLICYCHANGE_NOOP; hr = newsettings.m_ReadIn(); if (FAILED(hr)) { goto done; } if (newsettings == m_PolicySettings) { hr = S_FALSE; goto done; } if (fURLChanged(newsettings.m_pszWUStatusServerURL, m_PolicySettings.m_pszWUStatusServerURL)) { (void) gPingStatus.SetCorpServerUrl(newsettings.m_pszWUStatusServerURL); } if (!newsettings.m_fRegAUOptionsSpecified) { *pActCode = AUPOLICYCHANGE_NOOP; } else if ((fURLChanged(newsettings.m_pszWUServerURL, m_PolicySettings.m_pszWUServerURL) && AUSTATE_DISABLED != m_dwState) || (AUOPTION_AUTOUPDATE_DISABLE == m_PolicySettings.m_dwOption && newsettings.m_dwOption > m_PolicySettings.m_dwOption) || m_dwState < AUSTATE_DETECT_PENDING) { //stop client, cancel download if any, reset state to detect pending. do detect *pActCode = AUPOLICYCHANGE_RESETENGINE; } else if (AUOPTION_AUTOUPDATE_DISABLE == newsettings.m_dwOption && m_PolicySettings.m_dwOption != newsettings.m_dwOption) { //stop client, cancel download if any, set state to be disabled *pActCode = AUPOLICYCHANGE_DISABLE; } else if (AUSTATE_INSTALL_PENDING != m_dwState && (newsettings.m_enPolicyType != m_PolicySettings.m_enPolicyType ||newsettings.m_dwOption != m_PolicySettings.m_dwOption ||newsettings.m_dwSchedInstallDay != m_PolicySettings.m_dwSchedInstallDay ||newsettings.m_dwSchedInstallTime != m_PolicySettings.m_dwSchedInstallTime)) { *pActCode = AUPOLICYCHANGE_RESETCLIENT; } else { *pActCode = AUPOLICYCHANGE_NOOP; } m_PolicySettings.Copy(newsettings); done: #ifdef DBG m_DbgDumpState(); #endif m_unlock(); DEBUGMSG("CAUState::Refresh() return %#lx with action code %d", hr, *pActCode); return hr; } void CAUState::m_ReadRegistrySettings(BOOL fInit) { if ( FAILED(GetRegDWordValue(REG_AUSTATE, &m_dwState, enAU_AdminPolicy)) // ||m_dwState < AUSTATE_MIN //always false || m_dwState > AUSTATE_MAX) { m_dwState = AUSTATE_OUTOFBOX; } TCHAR tszDetectionStartTime[20]; if ( fInit || FAILED(GetRegStringValue(REG_AUDETECTIONSTARTTIME, tszDetectionStartTime, ARRAYSIZE(tszDetectionStartTime), enAU_AdminPolicy)) || FAILED(String2FileTime(tszDetectionStartTime, &m_auftDetectionStartTime.ft)) ) { m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE; } if (!fInit) { DeleteRegValue(REG_AUSCHEDINSTALLDATE); m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE; } else if (AUSTATE_DOWNLOAD_COMPLETE == m_dwState) { TCHAR szSchedInstallDate[20]; if ( FAILED(GetRegStringValue(REG_AUSCHEDINSTALLDATE, szSchedInstallDate, ARRAYSIZE(szSchedInstallDate), enAU_AdminPolicy)) || FAILED(String2FileTime(szSchedInstallDate, &m_auftSchedInstallDate.ft)) ) { m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE; } } return; } //======================================================================= // CAUState::m_ReadPolicy // read in registry settings //======================================================================= HRESULT CAUState::m_ReadPolicy(BOOL fInit) { return m_PolicySettings.m_ReadIn(); } HRESULT AUPolicySettings::m_ReadIn() { HRESULT hr = m_ReadWUServerURL(); if (SUCCEEDED(hr)) { m_enPolicyType = enAU_DomainPolicy; for (int i = 0; i < 2; i++) { if ( FAILED(hr = m_ReadOptionPolicy()) || FAILED(hr = m_ReadScheduledInstallPolicy()) ) { m_enPolicyType = enAU_AdminPolicy; continue; } break; } } DEBUGMSG("ReadPolicy: %d, hr = %#lx", m_enPolicyType, hr); return hr; } //======================================================================= // CAUState::m_ReadOptionPolicy // return S_FALSE if default option is returned //======================================================================= HRESULT AUPolicySettings::m_ReadOptionPolicy(void) { HRESULT hr = E_INVALIDARG; // reading admin policy will always return success if ( enAU_DomainPolicy == m_enPolicyType ) { // check if disabled by the NoAutoUpdate key if ( SUCCEEDED(CAUState::GetRegDWordValue(REG_AUNOAUTOUPDATE, &(m_dwOption), m_enPolicyType)) && (AUOPTION_AUTOUPDATE_DISABLE == m_dwOption) ) { hr = S_OK; } } if ( FAILED(hr) && (FAILED(hr = CAUState::GetRegDWordValue(REG_AUOPTIONS, &(m_dwOption), m_enPolicyType)) || (m_dwOption > AUOPTION_MAX) || ((enAU_AdminPolicy == m_enPolicyType) && (m_dwOption < AUOPTION_ADMIN_MIN)) || ((enAU_DomainPolicy == m_enPolicyType) && (m_dwOption < AUOPTION_DOMAIN_MIN))) ) { if ( enAU_AdminPolicy == m_enPolicyType ) { DEBUGMSG("bad admin option policy, defaulting to AUOPTION_INSTALLONLY_NOTIFY"); m_fRegAUOptionsSpecified = (AUOPTION_UNSPECIFIED != m_dwOption); m_dwOption = AUOPTION_INSTALLONLY_NOTIFY; hr = S_FALSE; } else { DEBUGMSG("invalid domain option policy"); hr = E_INVALIDARG; } } DEBUGMSG("ReadOptionPolicy: type = %d, hr = %#lx", m_enPolicyType, hr); return hr; } //======================================================================= // CAUState::m_ReadScheduledInstallPolicy //======================================================================= HRESULT AUPolicySettings::m_ReadScheduledInstallPolicy() { const DWORD DEFAULT_SCHED_INSTALL_DAY = 0; const DWORD DEFAULT_SCHED_INSTALL_TIME = 3; HRESULT hr = S_OK; if ( AUOPTION_SCHEDULED != m_dwOption ) { m_dwSchedInstallDay = DEFAULT_SCHED_INSTALL_DAY; m_dwSchedInstallTime = DEFAULT_SCHED_INSTALL_TIME; } else { if ( FAILED(CAUState::GetRegDWordValue(REG_AUSCHEDINSTALLDAY, &m_dwSchedInstallDay, m_enPolicyType)) || (m_dwSchedInstallDay > AUSCHEDINSTALLDAY_MAX) ) { DEBUGMSG("invalid SchedInstallDay policy"); if ( enAU_DomainPolicy == m_enPolicyType ) { hr = E_INVALIDARG; goto done; } m_dwSchedInstallDay = DEFAULT_SCHED_INSTALL_DAY; } if ( FAILED(CAUState::GetRegDWordValue(REG_AUSCHEDINSTALLTIME, &m_dwSchedInstallTime, m_enPolicyType)) || (m_dwSchedInstallTime > AUSCHEDINSTALLTIME_MAX) ) { DEBUGMSG("invalid SchedInstallTime policy"); if ( enAU_DomainPolicy == m_enPolicyType ) { hr = E_INVALIDARG; goto done; } m_dwSchedInstallTime = DEFAULT_SCHED_INSTALL_TIME; } } done: return hr; } //======================================================================= // CAUState::m_ReadWUServerURL // only error returned is E_OUTOFMEMORY //======================================================================= HRESULT AUPolicySettings::m_ReadWUServerURL(void) { HRESULT hr = S_OK; LPTSTR *purls[2] = { &m_pszWUServerURL, &m_pszWUStatusServerURL}; LPCTSTR RegStrs[2] = {REG_WUSERVER_URL, REG_WUSTATUSSERVER_URL}; for (int i = 0 ; i < ARRAYSIZE(purls); i++) { DWORD dwBytes = INTERNET_MAX_URL_LENGTH * sizeof((*purls[i])[0]); if ( (NULL == *purls[i]) && (NULL == (*purls[i] = (LPTSTR)malloc(dwBytes))) ) { hr = E_OUTOFMEMORY; goto done; } hr = CAUState::GetRegStringValue(RegStrs[i], *purls[i], dwBytes/sizeof((*purls[i])[0]), enAU_WindowsUpdatePolicy); if ( FAILED(hr) ) { DEBUGMSG("invalid key %S; resetting both corp WU server URLs", RegStrs[i]); goto done; } } done: if (FAILED(hr)) { SafeFreeNULL(m_pszWUServerURL); SafeFreeNULL(m_pszWUStatusServerURL); if (E_OUTOFMEMORY != hr) { hr = S_OK; } } return hr; } HRESULT AUPolicySettings::m_SetInstallSchedule(DWORD dwSchedInstallDay, DWORD dwSchedInstallTime) { HRESULT hr; if (enAU_DomainPolicy == m_enPolicyType) { return E_ACCESSDENIED; //if domain policy in force, option can not be changed } if (/*dwSchedInstallDay < AUSCHEDINSTALLDAY_MIN ||*/ dwSchedInstallDay > AUSCHEDINSTALLDAY_MAX /*|| dwSchedInstallTime < AUSCHEDINSTALLTIME_MIN*/ || dwSchedInstallTime > AUSCHEDINSTALLTIME_MAX) { return E_INVALIDARG; } if (SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLDAY, dwSchedInstallDay)) && SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLTIME, dwSchedInstallTime))) { m_dwSchedInstallDay = dwSchedInstallDay; m_dwSchedInstallTime = dwSchedInstallTime; } else { //roll back CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLDAY, m_dwSchedInstallDay); CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLTIME,m_dwSchedInstallTime); } return hr; } HRESULT AUPolicySettings::m_SetOption(AUOPTION & Option) { HRESULT hr; if ( (Option.dwOption < AUOPTION_ADMIN_MIN) || (Option.dwOption > AUOPTION_MAX) ) { return E_INVALIDARG; } if (enAU_DomainPolicy == m_enPolicyType) { return E_ACCESSDENIED; //if domain policy in force, option can not be changed } if (SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUOPTIONS, Option.dwOption))) { m_dwOption = Option.dwOption; } else { goto done; } if (AUOPTION_SCHEDULED == Option.dwOption) { hr = m_SetInstallSchedule(Option.dwSchedInstallDay, Option.dwSchedInstallTime); } done: return hr; } //======================================================================= // CAUState::m_ReadTestOverrides //======================================================================= HRESULT CAUState::m_ReadTestOverrides(void) { HRESULT hr = S_OK; DWORD dwBytes = 0; #ifdef DBG dwBytes = INTERNET_MAX_URL_LENGTH * sizeof(m_pszTestSelfUpdateURL[0]); if ( (NULL == m_pszTestSelfUpdateURL) && (NULL == (m_pszTestSelfUpdateURL = (LPTSTR)malloc(dwBytes))) ) { hr = E_OUTOFMEMORY; goto done; } if ( FAILED(GetRegStringValue(REG_SELFUPDATE_URL, m_pszTestSelfUpdateURL, dwBytes/sizeof(m_pszTestSelfUpdateURL[0]), enAU_AdminPolicy)) ) { SafeFreeNULL(m_pszTestSelfUpdateURL); } #endif dwBytes = INTERNET_MAX_URL_LENGTH * sizeof(m_pszTestIdentServerURL[0]); if ( (NULL == m_pszTestIdentServerURL) && (NULL == (m_pszTestIdentServerURL = (LPTSTR)malloc(dwBytes))) ) { hr = E_OUTOFMEMORY; goto done; } if ( FAILED(GetRegStringValue(REG_IDENT_URL, m_pszTestIdentServerURL, dwBytes/sizeof(m_pszTestIdentServerURL[0]), enAU_IUControlPolicy)) ) { SafeFreeNULL(m_pszTestIdentServerURL); } done: return hr; } //======================================================================= // CAUState::m_SetScheduledInstallDate // returns // S_OK - there was no need to change the scheduled install date // other - error code //======================================================================= HRESULT CAUState::m_SetScheduledInstallDate(void) { // fixcode need to put new scheduled time in event log HRESULT hr = S_OK; // assume scheduled install date unchanged TCHAR szSchedInstallDate[20]; if (SUCCEEDED(hr = FileTime2String(m_auftSchedInstallDate.ft, szSchedInstallDate, ARRAYSIZE(szSchedInstallDate)))) { DEBUGMSG("New scheduled install date: %S", szSchedInstallDate); hr = SetRegStringValue(REG_AUSCHEDINSTALLDATE, szSchedInstallDate, enAU_AdminPolicy); } else { DEBUGMSG("failed m_SetScheduledInstallDate() == %#lx", hr); } return hr; } AUOPTION CAUState::GetOption(void) { AUOPTION opt; BOOL fLocked = m_lock(); opt.dwOption = m_PolicySettings.m_dwOption; opt.dwSchedInstallDay = m_PolicySettings.m_dwSchedInstallDay; opt.dwSchedInstallTime = m_PolicySettings.m_dwSchedInstallTime; opt.fDomainPolicy = (enAU_DomainPolicy == m_PolicySettings.m_enPolicyType); if (fLocked) m_unlock(); return opt; } //======================================================================= // CAUState::SetOption // option.fDomainPolicy is irrelevant. Not settable //======================================================================= HRESULT CAUState::SetOption(AUOPTION & Option) { HRESULT hr; if (!m_lock()) { return HRESULT_FROM_WIN32(GetLastError()); } hr = m_PolicySettings.m_SetOption(Option); m_unlock(); return hr; } HRESULT CAUState::SetInstallSchedule(DWORD dwSchedInstallDay, DWORD dwSchedInstallTime) { HRESULT hr; if (!m_lock()) { return HRESULT_FROM_WIN32(GetLastError()); } hr = m_PolicySettings.m_SetInstallSchedule(dwSchedInstallDay, dwSchedInstallTime); m_unlock(); return hr; } //======================================================================= // CAUState::SetState // it could also be called to kick state event in both engine and client // even if no state change is involved //======================================================================= void CAUState::SetState(DWORD dwState) { if (!m_lock()) { return ; } if ( m_dwState != dwState ) { m_dwState = dwState; SetRegDWordValue(REG_AUSTATE, dwState); DEBUGMSG("WUAUENG SetState Event, state = %d", dwState); } else { DEBUGMSG("kick state event in client and engine with state %d", dwState); } SetEvent(ghEngineState); ghClientHandles.ClientStateChange(); m_unlock(); } void CAUState::GetInstallSchedule(DWORD *pdwSchedInstallDay, DWORD *pdwSchedInstallTime) { BOOL fLocked = m_lock(); *pdwSchedInstallDay = m_PolicySettings.m_dwSchedInstallDay; *pdwSchedInstallTime = m_PolicySettings.m_dwSchedInstallTime; if (fLocked) m_unlock(); } //======================================================================= // CAUState::fWasSystemRestored // // Determine if system was restored. //======================================================================= BOOL CAUState::fWasSystemRestored(void) { if ( fIsPersonalOrProfessional() && fRegKeyExists(AUREGKEY_HKLM_SYSTEM_WAS_RESTORED) ) { fRegKeyDelete(AUREGKEY_HKLM_SYSTEM_WAS_RESTORED); return TRUE; } return FALSE; } void CAUState::SetDisconnected(BOOL fDisconnected) { if (!m_lock()) { return ; } m_fDisconnected = fDisconnected; m_unlock(); } //======================================================================= // CAUState::GetRegDWordValue //======================================================================= HRESULT CAUState::GetRegDWordValue(LPCTSTR lpszValueName, LPDWORD pdwValue, enumAUPolicyType enPolicyType) { if (lpszValueName == NULL) { return E_INVALIDARG; } return ::GetRegDWordValue(lpszValueName, pdwValue, (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY); } //======================================================================= // CAUState::SetRegDWordValue //======================================================================= HRESULT CAUState::SetRegDWordValue(LPCTSTR lpszValueName, DWORD dwValue, enumAUPolicyType enPolicyType, DWORD options) { if (lpszValueName == NULL) { return E_INVALIDARG; } return ::SetRegDWordValue(lpszValueName, dwValue, options, (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY); } //======================================================================= // CAUState::GetRegStringValue //======================================================================= HRESULT CAUState::GetRegStringValue(LPCTSTR lpszValueName, LPTSTR lpszBuffer, int nCharCount, enumAUPolicyType enPolicyType) { LPCTSTR pszSubKey; if (lpszValueName == NULL || lpszBuffer == NULL) { return E_INVALIDARG; } switch (enPolicyType) { case enAU_DomainPolicy: pszSubKey = AUREGKEY_HKLM_DOMAIN_POLICY; break; case enAU_AdminPolicy: pszSubKey = AUREGKEY_HKLM_ADMIN_POLICY; break; case enAU_WindowsUpdatePolicy: pszSubKey = AUREGKEY_HKLM_WINDOWSUPDATE_POLICY; break; case enAU_IUControlPolicy: pszSubKey = AUREGKEY_HKLM_IUCONTROL_POLICY; break; default: return E_INVALIDARG; } return ::GetRegStringValue(lpszValueName, lpszBuffer, nCharCount, pszSubKey); } //======================================================================= // CAUState::SetRegStringValue //======================================================================= HRESULT CAUState::SetRegStringValue(LPCTSTR lpszValueName, LPCTSTR lpszNewValue, enumAUPolicyType enPolicyType) { HKEY hKey; HRESULT hRet = E_FAIL; DWORD dwResult; if (lpszValueName == NULL || lpszNewValue == NULL) { return E_INVALIDARG; } return ::SetRegStringValue(lpszValueName, lpszNewValue, (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY); } //======================================================================= // Calculate Scheduled Date //======================================================================= HRESULT CAUState::m_CalculateScheduledInstallDate(AUFILETIME & auftSchedInstallDate, DWORD *pdwSleepTime) { if ( (-1 == m_PolicySettings.m_dwSchedInstallDay) || (-1 == m_PolicySettings.m_dwSchedInstallTime) ) { return E_INVALIDARG; } //DEBUGMSG("Schedule day: %d, time: %d", m_dwSchedInstallDay, m_dwSchedInstallTime); AUFILETIME auftNow; SYSTEMTIME stNow; GetLocalTime(&stNow); if ( !SystemTimeToFileTime(&stNow, &auftNow.ft) ) { return HRESULT_FROM_WIN32(GetLastError()); } SYSTEMTIME stScheduled = stNow; stScheduled.wHour = (WORD)m_PolicySettings.m_dwSchedInstallTime; stScheduled.wMinute = stScheduled.wSecond = stScheduled.wMilliseconds = 0; DWORD dwSchedInstallDayOfWeek = (0 == m_PolicySettings.m_dwSchedInstallDay) ? stNow.wDayOfWeek : (m_PolicySettings.m_dwSchedInstallDay - 1); DWORD dwDaysToAdd = (7 + dwSchedInstallDayOfWeek - stNow.wDayOfWeek) % 7; //DEBUGMSG("daystoadd %d", dwDaysToAdd); AUFILETIME auftScheduled; if ( !SystemTimeToFileTime(&stScheduled, &auftScheduled.ft) ) { return HRESULT_FROM_WIN32(GetLastError()); } auftScheduled.ull += (ULONGLONG)dwDaysToAdd * AU_ONE_DAY * NanoSec100PerSec; if ( auftScheduled.ull < auftNow.ull ) { // we missed the time today, go to next scheduled day auftScheduled.ull += (ULONGLONG)((0 == m_PolicySettings.m_dwSchedInstallDay) ? AU_ONE_DAY : AU_ONE_WEEK) * NanoSec100PerSec; } auftSchedInstallDate = auftScheduled; *pdwSleepTime = (DWORD)((auftScheduled.ull - auftNow.ull) / NanoSec100PerSec); return S_OK; } //======================================================================= // CAUState::CalculateScheduledInstallSleepTime //======================================================================= HRESULT CAUState::CalculateScheduledInstallSleepTime(DWORD *pdwSleepTime) { HRESULT hr = S_OK; *pdwSleepTime = 0; if (!m_lock()) { return HRESULT_FROM_WIN32(GetLastError()); } if ( (-1 == m_PolicySettings.m_dwSchedInstallDay) || (-1 == m_PolicySettings.m_dwSchedInstallTime) ) { hr = E_INVALIDARG; goto done; } AUFILETIME auftSchedInstallDate; if (SUCCEEDED(hr = m_CalculateScheduledInstallDate(auftSchedInstallDate, pdwSleepTime))) { if (m_auftSchedInstallDate.ull != auftSchedInstallDate.ull) { //recalculate sleep time if anything changes m_auftSchedInstallDate = auftSchedInstallDate; if (S_OK == (hr = m_SetScheduledInstallDate())) { hr = S_FALSE; } } } AUFILETIME auftNow; SYSTEMTIME stNow; GetLocalTime(&stNow); if ( !SystemTimeToFileTime(&stNow, &auftNow.ft) ) { hr = HRESULT_FROM_WIN32(GetLastError()); goto done; } if (AUFT_INVALID_VALUE != m_auftSchedInstallDate.ull) { if ( auftNow.ull < m_auftSchedInstallDate.ull ) { *pdwSleepTime = (DWORD) ((m_auftSchedInstallDate.ull - auftNow.ull) / NanoSec100PerSec); } else if ( ((auftNow.ull - m_auftSchedInstallDate.ull) / NanoSec100PerSec) <= AU_TEN_MINS ) { // we should have done the scheduled install within the // last 10 minutes. Close enough, do it now. } } done: // DEBUGMSG("CalculateScheduleInstallSleepTime return %d sleeping secs with result %#lx", *pdwSleepTime, hr); m_unlock(); return hr; } //======================================================================= // CAUState::SetDetectionStartTime //======================================================================= void CAUState::SetDetectionStartTime(BOOL fOverwrite) { if (!m_lock()) { return ; } if (fOverwrite || AUFT_INVALID_VALUE == m_auftDetectionStartTime.ull) { AUFILETIME auftNow; SYSTEMTIME stNow; GetLocalTime(&stNow); if (SystemTimeToFileTime(&stNow, &auftNow.ft)) { HRESULT hr; TCHAR tszDetectionStartTime[20]; if (SUCCEEDED(hr = FileTime2String(auftNow.ft, tszDetectionStartTime, ARRAYSIZE(tszDetectionStartTime)))) { m_auftDetectionStartTime = auftNow; DEBUGMSG("New last connection check time: %S", tszDetectionStartTime); SetRegStringValue(REG_AUDETECTIONSTARTTIME, tszDetectionStartTime, enAU_AdminPolicy); } else { DEBUGMSG("failed m_SetScheduledInstallDate() == %#lx", hr); } } } else { DEBUGMSG("CAUState::SetDetectionStartTime() fOverwrite==FALSE, time(%#lx%8lx) != AUFT_INVALID_VALUE.", m_auftDetectionStartTime.ft.dwHighDateTime, m_auftDetectionStartTime.ft.dwLowDateTime); } m_unlock(); } //======================================================================= // CAUState::IsUnableToConnect //======================================================================= BOOL CAUState::IsUnableToConnect(void) { AUFILETIME auftNow; SYSTEMTIME stNow; GetLocalTime(&stNow); if (!SystemTimeToFileTime(&stNow, &auftNow.ft)) { return FALSE; //REVIEW: or return TRUE? } if (!m_lock()) { return FALSE; } BOOL fRet = FALSE; if (AUFT_INVALID_VALUE != m_auftDetectionStartTime.ull && (auftNow.ull - m_auftDetectionStartTime.ull) / NanoSec100PerSec >= dwSecsToWait(AU_TWO_DAYS)) { fRet = TRUE; } m_unlock(); return fRet; } //======================================================================= // CAUState::RemoveDetectionStartTime //======================================================================= void CAUState::RemoveDetectionStartTime(void) { if (!m_lock()) { return ; } DeleteRegValue(REG_AUDETECTIONSTARTTIME); m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE; m_unlock(); } #ifdef DBG //======================================================================= // CAUState::m_DbgDumpState //======================================================================= void CAUState::m_DbgDumpState(void) { DEBUGMSG("======= Initial State Dump ========="); m_PolicySettings.m_DbgDump(); DEBUGMSG("State: %d", m_dwState); TCHAR szSchedInstallDate[20]; if ( 0 == m_auftSchedInstallDate.ull ) { (void)StringCchCopyEx(szSchedInstallDate, ARRAYSIZE(szSchedInstallDate), _T("none"), NULL, NULL, MISTSAFE_STRING_FLAGS); } else { if ( FAILED(FileTime2String(m_auftSchedInstallDate.ft, szSchedInstallDate, ARRAYSIZE(szSchedInstallDate))) ) { (void)StringCchCopyEx(szSchedInstallDate, ARRAYSIZE(szSchedInstallDate), _T("invalid"), NULL, NULL, MISTSAFE_STRING_FLAGS); } } DEBUGMSG("ScheduledInstallDate: %S", szSchedInstallDate); //DEBUGMSG("WUServer Value: %S", gpState->GetWUServerURL()); DEBUGMSG("Ident Server: %S", gpState->GetIdentServerURL()); DEBUGMSG("Self Update Server URL Override: %S", (NULL != gpState->GetSelfUpdateServerURLOverride()) ? gpState->GetSelfUpdateServerURLOverride() : _T("none")); DEBUGMSG("====================================="); } #endif