WindowsXP-SP1/enduser/windows.com/wuau/wuaueng/caustate.cpp
2020-09-30 16:53:49 +02:00

991 lines
30 KiB
C++

//=======================================================================
//
// 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