991 lines
29 KiB
C++
991 lines
29 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
|
||
|
|