Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

990 lines
29 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: state.cpp
  6. //
  7. // Creator: PeterWi
  8. //
  9. // Purpose: State management functions.
  10. //
  11. //=======================================================================
  12. #include "pch.h"
  13. #pragma hdrstop
  14. // global state object pointer
  15. CAUState *gpState;
  16. BOOL gfDownloadStarted; //to be used to distinguish connection detection and actually downloading mode
  17. #ifdef DBG
  18. const TCHAR REG_AUCONNECTWAIT[] = _T("ConnectWait");
  19. const TCHAR REG_SELFUPDATE_URL[] = _T("SelfUpdateURL");
  20. #endif
  21. const TCHAR REG_WUSERVER_URL[] = _T("WUServer");
  22. const TCHAR REG_WUSTATUSSERVER_URL[] = _T("WUStatusServer");
  23. const TCHAR REG_IDENT_URL[] = _T("IdentServer");
  24. const TCHAR WU_LIVE_URL[] = _T("http://windowsupdate.microsoft.com/v4");
  25. //AU configurable registry settings
  26. const TCHAR REG_AUOPTIONS[] = _T("AUOptions"); //REG_DWORD
  27. const TCHAR REG_AUSTATE[] = _T("AUState"); //REG_DWORD
  28. const TCHAR REG_AUDETECTIONSTARTTIME[] = _T("DetectionStartTime"); //REG_SZ
  29. const TCHAR REG_AUSCHEDINSTALLDAY[] = _T("ScheduledInstallDay"); //REG_DWORD
  30. const TCHAR REG_AUSCHEDINSTALLTIME[] = _T("ScheduledInstallTime"); //REG_DWORD
  31. const TCHAR REG_AUSCHEDINSTALLDATE[] = _T("ScheduledInstallDate"); //REG_SZ
  32. const TCHAR REG_AUNOAUTOUPDATE[] = _T("NoAutoUpdate"); // REG_DWORD 1 means AU be disabled
  33. //=======================================================================
  34. // CAUState::HrCreateState
  35. //
  36. // Static function to create the global state object in memory.
  37. //=======================================================================
  38. /*static*/ HRESULT CAUState::HrCreateState(void)
  39. {
  40. HRESULT hr;
  41. if ( NULL == (gpState = new CAUState()) )
  42. {
  43. hr = E_OUTOFMEMORY;
  44. goto done;
  45. }
  46. if (NULL == (gpState->m_hMutex = CreateMutex(NULL, FALSE, NULL)))
  47. {
  48. DEBUGMSG("CAUState::HrCreateState() fail to CreateMutex with error %d",GetLastError());
  49. hr = E_FAIL;
  50. goto done;
  51. }
  52. hr = gpState->HrInit(TRUE);
  53. done:
  54. return hr;
  55. }
  56. CAUState::CAUState()
  57. { //only initialize members that destructor cares
  58. m_hMutex = NULL;
  59. #ifdef DBG
  60. m_pszTestSelfUpdateURL = NULL;
  61. #endif
  62. m_pszTestIdentServerURL = NULL;
  63. }
  64. void CAUState::m_Reset(void)
  65. {
  66. m_PolicySettings.Reset();
  67. m_dwState = AUSTATE_OUTOFBOX;
  68. #ifdef DBG
  69. SafeFreeNULL(m_pszTestSelfUpdateURL);
  70. #endif
  71. SafeFreeNULL(m_pszTestIdentServerURL);
  72. m_fWin2K = FALSE;
  73. m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE;
  74. m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE;
  75. m_dwCltAction = AUCLT_ACTION_NONE;
  76. m_fDisconnected = FALSE;
  77. }
  78. //=======================================================================
  79. // CAUState::HrInit
  80. //
  81. // Initialize state.
  82. //=======================================================================
  83. HRESULT CAUState::HrInit(BOOL fInit)
  84. {
  85. HRESULT hr = S_OK;
  86. if (!m_lock())
  87. {
  88. return HRESULT_FROM_WIN32(GetLastError());
  89. }
  90. m_dwCltAction = AUCLT_ACTION_NONE;
  91. m_fDisconnected = FALSE;
  92. m_PolicySettings.m_fRegAUOptionsSpecified = TRUE;
  93. m_Reset();
  94. m_ReadRegistrySettings(fInit);
  95. // read policy information. If any domain policy setting is
  96. // invalid, we revert to admin policy settings.
  97. if ( FAILED(hr = m_ReadPolicy(fInit)) ) // called after getting m_dwState due to dependency
  98. { // only case this function fails is when out of memory
  99. goto done;
  100. }
  101. if (!gPingStatus.SetCorpServerUrl(m_PolicySettings.m_pszWUStatusServerURL))
  102. {
  103. hr = E_FAIL;
  104. goto done;
  105. }
  106. if ( FAILED(hr = m_ReadTestOverrides()))
  107. {//only case this function fails is when out of memory
  108. goto done;
  109. }
  110. if (!m_PolicySettings.m_fRegAUOptionsSpecified)
  111. {
  112. if (m_dwState >= AUSTATE_DETECT_PENDING)
  113. { //invalid option needs user attention via wizard
  114. m_dwState = AUSTATE_OUTOFBOX;
  115. }
  116. }
  117. else if (!fOptionEnabled())
  118. {
  119. SetState(AUSTATE_DISABLED);
  120. }
  121. else if (m_dwState < AUSTATE_DETECT_PENDING)
  122. { // if domain policy set or auoption already configured, we skip the wizard state.
  123. SetState(AUSTATE_DETECT_PENDING);
  124. }
  125. m_fWin2K = IsWin2K();
  126. gfDownloadStarted = FALSE;
  127. done:
  128. #ifdef DBG
  129. if ( SUCCEEDED(hr) )
  130. {
  131. m_DbgDumpState();
  132. }
  133. #endif
  134. m_unlock();
  135. return hr;
  136. }
  137. BOOL fURLChanged(LPCTSTR url1, LPCTSTR url2)
  138. {
  139. if (url1 == NULL && url2 == NULL)
  140. {
  141. return FALSE;
  142. }
  143. if ((url1 == NULL && url2 != NULL )
  144. || (url1 != NULL && url2 == NULL))
  145. {
  146. return TRUE;
  147. }
  148. return 0 != StrCmpI(url1, url2);
  149. }
  150. //read Policy info again and refresh state object (only care about possible admin policy change now)
  151. //return S_FALSE if nothing changed
  152. //return S_OK if policy changed and state successfully updated
  153. // *pActCode will indicate what to do
  154. HRESULT CAUState::Refresh(enumAUPOLICYCHANGEACTION OUT *pActCode)
  155. {
  156. AUPolicySettings newsettings;
  157. HRESULT hr;
  158. if (!m_lock())
  159. {
  160. return HRESULT_FROM_WIN32(GetLastError());
  161. }
  162. *pActCode = AUPOLICYCHANGE_NOOP;
  163. hr = newsettings.m_ReadIn();
  164. if (FAILED(hr))
  165. {
  166. goto done;
  167. }
  168. if (newsettings == m_PolicySettings)
  169. {
  170. hr = S_FALSE;
  171. goto done;
  172. }
  173. if (fURLChanged(newsettings.m_pszWUStatusServerURL, m_PolicySettings.m_pszWUStatusServerURL))
  174. {
  175. (void) gPingStatus.SetCorpServerUrl(newsettings.m_pszWUStatusServerURL);
  176. }
  177. if (!newsettings.m_fRegAUOptionsSpecified)
  178. {
  179. *pActCode = AUPOLICYCHANGE_NOOP;
  180. }
  181. else if ((fURLChanged(newsettings.m_pszWUServerURL, m_PolicySettings.m_pszWUServerURL) && AUSTATE_DISABLED != m_dwState)
  182. || (AUOPTION_AUTOUPDATE_DISABLE == m_PolicySettings.m_dwOption && newsettings.m_dwOption > m_PolicySettings.m_dwOption)
  183. || m_dwState < AUSTATE_DETECT_PENDING)
  184. { //stop client, cancel download if any, reset state to detect pending. do detect
  185. *pActCode = AUPOLICYCHANGE_RESETENGINE;
  186. }
  187. else if (AUOPTION_AUTOUPDATE_DISABLE == newsettings.m_dwOption && m_PolicySettings.m_dwOption != newsettings.m_dwOption)
  188. { //stop client, cancel download if any, set state to be disabled
  189. *pActCode = AUPOLICYCHANGE_DISABLE;
  190. }
  191. else if (AUSTATE_INSTALL_PENDING != m_dwState &&
  192. (newsettings.m_enPolicyType != m_PolicySettings.m_enPolicyType
  193. ||newsettings.m_dwOption != m_PolicySettings.m_dwOption
  194. ||newsettings.m_dwSchedInstallDay != m_PolicySettings.m_dwSchedInstallDay
  195. ||newsettings.m_dwSchedInstallTime != m_PolicySettings.m_dwSchedInstallTime))
  196. {
  197. *pActCode = AUPOLICYCHANGE_RESETCLIENT;
  198. }
  199. else
  200. {
  201. *pActCode = AUPOLICYCHANGE_NOOP;
  202. }
  203. m_PolicySettings.Copy(newsettings);
  204. done:
  205. #ifdef DBG
  206. m_DbgDumpState();
  207. #endif
  208. m_unlock();
  209. DEBUGMSG("CAUState::Refresh() return %#lx with action code %d", hr, *pActCode);
  210. return hr;
  211. }
  212. void CAUState::m_ReadRegistrySettings(BOOL fInit)
  213. {
  214. if ( FAILED(GetRegDWordValue(REG_AUSTATE, &m_dwState, enAU_AdminPolicy))
  215. // ||m_dwState < AUSTATE_MIN //always false
  216. || m_dwState > AUSTATE_MAX)
  217. {
  218. m_dwState = AUSTATE_OUTOFBOX;
  219. }
  220. TCHAR tszDetectionStartTime[20];
  221. if ( fInit ||
  222. FAILED(GetRegStringValue(REG_AUDETECTIONSTARTTIME, tszDetectionStartTime,
  223. ARRAYSIZE(tszDetectionStartTime), enAU_AdminPolicy)) ||
  224. FAILED(String2FileTime(tszDetectionStartTime, &m_auftDetectionStartTime.ft)) )
  225. {
  226. m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE;
  227. }
  228. if (!fInit)
  229. {
  230. DeleteRegValue(REG_AUSCHEDINSTALLDATE);
  231. m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE;
  232. }
  233. else if (AUSTATE_DOWNLOAD_COMPLETE == m_dwState)
  234. {
  235. TCHAR szSchedInstallDate[20];
  236. if ( FAILED(GetRegStringValue(REG_AUSCHEDINSTALLDATE, szSchedInstallDate,
  237. ARRAYSIZE(szSchedInstallDate), enAU_AdminPolicy)) ||
  238. FAILED(String2FileTime(szSchedInstallDate, &m_auftSchedInstallDate.ft)) )
  239. {
  240. m_auftSchedInstallDate.ull = AUFT_INVALID_VALUE;
  241. }
  242. }
  243. return;
  244. }
  245. //=======================================================================
  246. // CAUState::m_ReadPolicy
  247. // read in registry settings
  248. //=======================================================================
  249. HRESULT CAUState::m_ReadPolicy(BOOL fInit)
  250. {
  251. return m_PolicySettings.m_ReadIn();
  252. }
  253. HRESULT AUPolicySettings::m_ReadIn()
  254. {
  255. HRESULT hr = m_ReadWUServerURL();
  256. if (SUCCEEDED(hr))
  257. {
  258. m_enPolicyType = enAU_DomainPolicy;
  259. for (int i = 0; i < 2; i++)
  260. {
  261. if ( FAILED(hr = m_ReadOptionPolicy()) ||
  262. FAILED(hr = m_ReadScheduledInstallPolicy()) )
  263. {
  264. m_enPolicyType = enAU_AdminPolicy;
  265. continue;
  266. }
  267. break;
  268. }
  269. }
  270. DEBUGMSG("ReadPolicy: %d, hr = %#lx", m_enPolicyType, hr);
  271. return hr;
  272. }
  273. //=======================================================================
  274. // CAUState::m_ReadOptionPolicy
  275. // return S_FALSE if default option is returned
  276. //=======================================================================
  277. HRESULT AUPolicySettings::m_ReadOptionPolicy(void)
  278. {
  279. HRESULT hr = E_INVALIDARG;
  280. // reading admin policy will always return success
  281. if ( enAU_DomainPolicy == m_enPolicyType )
  282. {
  283. // check if disabled by the NoAutoUpdate key
  284. if ( SUCCEEDED(CAUState::GetRegDWordValue(REG_AUNOAUTOUPDATE, &(m_dwOption), m_enPolicyType)) &&
  285. (AUOPTION_AUTOUPDATE_DISABLE == m_dwOption) )
  286. {
  287. hr = S_OK;
  288. }
  289. }
  290. if ( FAILED(hr) &&
  291. (FAILED(hr = CAUState::GetRegDWordValue(REG_AUOPTIONS, &(m_dwOption), m_enPolicyType)) ||
  292. (m_dwOption > AUOPTION_MAX) ||
  293. ((enAU_AdminPolicy == m_enPolicyType) && (m_dwOption < AUOPTION_ADMIN_MIN)) ||
  294. ((enAU_DomainPolicy == m_enPolicyType) && (m_dwOption < AUOPTION_DOMAIN_MIN))) )
  295. {
  296. if ( enAU_AdminPolicy == m_enPolicyType )
  297. {
  298. DEBUGMSG("bad admin option policy, defaulting to AUOPTION_INSTALLONLY_NOTIFY");
  299. m_fRegAUOptionsSpecified = (AUOPTION_UNSPECIFIED != m_dwOption);
  300. m_dwOption = AUOPTION_INSTALLONLY_NOTIFY;
  301. hr = S_FALSE;
  302. }
  303. else
  304. {
  305. DEBUGMSG("invalid domain option policy");
  306. hr = E_INVALIDARG;
  307. }
  308. }
  309. DEBUGMSG("ReadOptionPolicy: type = %d, hr = %#lx", m_enPolicyType, hr);
  310. return hr;
  311. }
  312. //=======================================================================
  313. // CAUState::m_ReadScheduledInstallPolicy
  314. //=======================================================================
  315. HRESULT AUPolicySettings::m_ReadScheduledInstallPolicy()
  316. {
  317. const DWORD DEFAULT_SCHED_INSTALL_DAY = 0;
  318. const DWORD DEFAULT_SCHED_INSTALL_TIME = 3;
  319. HRESULT hr = S_OK;
  320. if ( AUOPTION_SCHEDULED != m_dwOption )
  321. {
  322. m_dwSchedInstallDay = DEFAULT_SCHED_INSTALL_DAY;
  323. m_dwSchedInstallTime = DEFAULT_SCHED_INSTALL_TIME;
  324. }
  325. else
  326. {
  327. if ( FAILED(CAUState::GetRegDWordValue(REG_AUSCHEDINSTALLDAY, &m_dwSchedInstallDay, m_enPolicyType)) ||
  328. (m_dwSchedInstallDay > AUSCHEDINSTALLDAY_MAX) )
  329. {
  330. DEBUGMSG("invalid SchedInstallDay policy");
  331. if ( enAU_DomainPolicy == m_enPolicyType )
  332. {
  333. hr = E_INVALIDARG;
  334. goto done;
  335. }
  336. m_dwSchedInstallDay = DEFAULT_SCHED_INSTALL_DAY;
  337. }
  338. if ( FAILED(CAUState::GetRegDWordValue(REG_AUSCHEDINSTALLTIME, &m_dwSchedInstallTime, m_enPolicyType)) ||
  339. (m_dwSchedInstallTime > AUSCHEDINSTALLTIME_MAX) )
  340. {
  341. DEBUGMSG("invalid SchedInstallTime policy");
  342. if ( enAU_DomainPolicy == m_enPolicyType )
  343. {
  344. hr = E_INVALIDARG;
  345. goto done;
  346. }
  347. m_dwSchedInstallTime = DEFAULT_SCHED_INSTALL_TIME;
  348. }
  349. }
  350. done:
  351. return hr;
  352. }
  353. //=======================================================================
  354. // CAUState::m_ReadWUServerURL
  355. // only error returned is E_OUTOFMEMORY
  356. //=======================================================================
  357. HRESULT AUPolicySettings::m_ReadWUServerURL(void)
  358. {
  359. HRESULT hr = S_OK;
  360. LPTSTR *purls[2] = { &m_pszWUServerURL, &m_pszWUStatusServerURL};
  361. LPCTSTR RegStrs[2] = {REG_WUSERVER_URL, REG_WUSTATUSSERVER_URL};
  362. for (int i = 0 ; i < ARRAYSIZE(purls); i++)
  363. {
  364. DWORD dwBytes = INTERNET_MAX_URL_LENGTH * sizeof((*purls[i])[0]);
  365. if ( (NULL == *purls[i]) &&
  366. (NULL == (*purls[i] = (LPTSTR)malloc(dwBytes))) )
  367. {
  368. hr = E_OUTOFMEMORY;
  369. goto done;
  370. }
  371. hr = CAUState::GetRegStringValue(RegStrs[i], *purls[i],
  372. dwBytes/sizeof((*purls[i])[0]), enAU_WindowsUpdatePolicy);
  373. if ( FAILED(hr) )
  374. {
  375. DEBUGMSG("invalid key %S; resetting both corp WU server URLs", RegStrs[i]);
  376. goto done;
  377. }
  378. }
  379. done:
  380. if (FAILED(hr))
  381. {
  382. SafeFreeNULL(m_pszWUServerURL);
  383. SafeFreeNULL(m_pszWUStatusServerURL);
  384. if (E_OUTOFMEMORY != hr)
  385. {
  386. hr = S_OK;
  387. }
  388. }
  389. return hr;
  390. }
  391. HRESULT AUPolicySettings::m_SetInstallSchedule(DWORD dwSchedInstallDay, DWORD dwSchedInstallTime)
  392. {
  393. HRESULT hr;
  394. if (enAU_DomainPolicy == m_enPolicyType)
  395. {
  396. return E_ACCESSDENIED; //if domain policy in force, option can not be changed
  397. }
  398. if (/*dwSchedInstallDay < AUSCHEDINSTALLDAY_MIN ||*/ dwSchedInstallDay > AUSCHEDINSTALLDAY_MAX
  399. /*|| dwSchedInstallTime < AUSCHEDINSTALLTIME_MIN*/ || dwSchedInstallTime > AUSCHEDINSTALLTIME_MAX)
  400. {
  401. return E_INVALIDARG;
  402. }
  403. if (SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLDAY, dwSchedInstallDay))
  404. && SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLTIME, dwSchedInstallTime)))
  405. {
  406. m_dwSchedInstallDay = dwSchedInstallDay;
  407. m_dwSchedInstallTime = dwSchedInstallTime;
  408. }
  409. else
  410. { //roll back
  411. CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLDAY, m_dwSchedInstallDay);
  412. CAUState::SetRegDWordValue(REG_AUSCHEDINSTALLTIME,m_dwSchedInstallTime);
  413. }
  414. return hr;
  415. }
  416. HRESULT AUPolicySettings::m_SetOption(AUOPTION & Option)
  417. {
  418. HRESULT hr;
  419. if ( (Option.dwOption < AUOPTION_ADMIN_MIN) || (Option.dwOption > AUOPTION_MAX) )
  420. {
  421. return E_INVALIDARG;
  422. }
  423. if (enAU_DomainPolicy == m_enPolicyType)
  424. {
  425. return E_ACCESSDENIED; //if domain policy in force, option can not be changed
  426. }
  427. if (SUCCEEDED(hr = CAUState::SetRegDWordValue(REG_AUOPTIONS, Option.dwOption)))
  428. {
  429. m_dwOption = Option.dwOption;
  430. }
  431. else
  432. {
  433. goto done;
  434. }
  435. if (AUOPTION_SCHEDULED == Option.dwOption)
  436. {
  437. hr = m_SetInstallSchedule(Option.dwSchedInstallDay, Option.dwSchedInstallTime);
  438. }
  439. done:
  440. return hr;
  441. }
  442. //=======================================================================
  443. // CAUState::m_ReadTestOverrides
  444. //=======================================================================
  445. HRESULT CAUState::m_ReadTestOverrides(void)
  446. {
  447. HRESULT hr = S_OK;
  448. DWORD dwBytes = 0;
  449. #ifdef DBG
  450. dwBytes = INTERNET_MAX_URL_LENGTH * sizeof(m_pszTestSelfUpdateURL[0]);
  451. if ( (NULL == m_pszTestSelfUpdateURL) &&
  452. (NULL == (m_pszTestSelfUpdateURL = (LPTSTR)malloc(dwBytes))) )
  453. {
  454. hr = E_OUTOFMEMORY;
  455. goto done;
  456. }
  457. if ( FAILED(GetRegStringValue(REG_SELFUPDATE_URL, m_pszTestSelfUpdateURL,
  458. dwBytes/sizeof(m_pszTestSelfUpdateURL[0]), enAU_AdminPolicy)) )
  459. {
  460. SafeFreeNULL(m_pszTestSelfUpdateURL);
  461. }
  462. #endif
  463. dwBytes = INTERNET_MAX_URL_LENGTH * sizeof(m_pszTestIdentServerURL[0]);
  464. if ( (NULL == m_pszTestIdentServerURL) &&
  465. (NULL == (m_pszTestIdentServerURL = (LPTSTR)malloc(dwBytes))) )
  466. {
  467. hr = E_OUTOFMEMORY;
  468. goto done;
  469. }
  470. if ( FAILED(GetRegStringValue(REG_IDENT_URL, m_pszTestIdentServerURL,
  471. dwBytes/sizeof(m_pszTestIdentServerURL[0]), enAU_IUControlPolicy)) )
  472. {
  473. SafeFreeNULL(m_pszTestIdentServerURL);
  474. }
  475. done:
  476. return hr;
  477. }
  478. //=======================================================================
  479. // CAUState::m_SetScheduledInstallDate
  480. // returns
  481. // S_OK - there was no need to change the scheduled install date
  482. // other - error code
  483. //=======================================================================
  484. HRESULT CAUState::m_SetScheduledInstallDate(void)
  485. {
  486. // fixcode need to put new scheduled time in event log
  487. HRESULT hr = S_OK; // assume scheduled install date unchanged
  488. TCHAR szSchedInstallDate[20];
  489. if (SUCCEEDED(hr = FileTime2String(m_auftSchedInstallDate.ft, szSchedInstallDate, ARRAYSIZE(szSchedInstallDate))))
  490. {
  491. DEBUGMSG("New scheduled install date: %S", szSchedInstallDate);
  492. hr = SetRegStringValue(REG_AUSCHEDINSTALLDATE, szSchedInstallDate, enAU_AdminPolicy);
  493. }
  494. else
  495. {
  496. DEBUGMSG("failed m_SetScheduledInstallDate() == %#lx", hr);
  497. }
  498. return hr;
  499. }
  500. AUOPTION CAUState::GetOption(void)
  501. {
  502. AUOPTION opt;
  503. BOOL fLocked = m_lock();
  504. opt.dwOption = m_PolicySettings.m_dwOption;
  505. opt.dwSchedInstallDay = m_PolicySettings.m_dwSchedInstallDay;
  506. opt.dwSchedInstallTime = m_PolicySettings.m_dwSchedInstallTime;
  507. opt.fDomainPolicy = (enAU_DomainPolicy == m_PolicySettings.m_enPolicyType);
  508. if (fLocked)
  509. m_unlock();
  510. return opt;
  511. }
  512. //=======================================================================
  513. // CAUState::SetOption
  514. // option.fDomainPolicy is irrelevant. Not settable
  515. //=======================================================================
  516. HRESULT CAUState::SetOption(AUOPTION & Option)
  517. {
  518. HRESULT hr;
  519. if (!m_lock())
  520. {
  521. return HRESULT_FROM_WIN32(GetLastError());
  522. }
  523. hr = m_PolicySettings.m_SetOption(Option);
  524. m_unlock();
  525. return hr;
  526. }
  527. HRESULT CAUState::SetInstallSchedule(DWORD dwSchedInstallDay, DWORD dwSchedInstallTime)
  528. {
  529. HRESULT hr;
  530. if (!m_lock())
  531. {
  532. return HRESULT_FROM_WIN32(GetLastError());
  533. }
  534. hr = m_PolicySettings.m_SetInstallSchedule(dwSchedInstallDay, dwSchedInstallTime);
  535. m_unlock();
  536. return hr;
  537. }
  538. //=======================================================================
  539. // CAUState::SetState
  540. // it could also be called to kick state event in both engine and client
  541. // even if no state change is involved
  542. //=======================================================================
  543. void CAUState::SetState(DWORD dwState)
  544. {
  545. if (!m_lock())
  546. {
  547. return ;
  548. }
  549. if ( m_dwState != dwState )
  550. {
  551. m_dwState = dwState;
  552. SetRegDWordValue(REG_AUSTATE, dwState);
  553. DEBUGMSG("WUAUENG SetState Event, state = %d", dwState);
  554. }
  555. else
  556. {
  557. DEBUGMSG("kick state event in client and engine with state %d", dwState);
  558. }
  559. SetEvent(ghEngineState);
  560. ghClientHandles.ClientStateChange();
  561. m_unlock();
  562. }
  563. void CAUState::GetInstallSchedule(DWORD *pdwSchedInstallDay, DWORD *pdwSchedInstallTime)
  564. {
  565. BOOL fLocked = m_lock();
  566. *pdwSchedInstallDay = m_PolicySettings.m_dwSchedInstallDay;
  567. *pdwSchedInstallTime = m_PolicySettings.m_dwSchedInstallTime;
  568. if (fLocked)
  569. m_unlock();
  570. }
  571. //=======================================================================
  572. // CAUState::fWasSystemRestored
  573. //
  574. // Determine if system was restored.
  575. //=======================================================================
  576. BOOL CAUState::fWasSystemRestored(void)
  577. {
  578. if ( fIsPersonalOrProfessional() &&
  579. fRegKeyExists(AUREGKEY_HKLM_SYSTEM_WAS_RESTORED) )
  580. {
  581. fRegKeyDelete(AUREGKEY_HKLM_SYSTEM_WAS_RESTORED);
  582. return TRUE;
  583. }
  584. return FALSE;
  585. }
  586. void CAUState::SetDisconnected(BOOL fDisconnected)
  587. {
  588. if (!m_lock())
  589. {
  590. return ;
  591. }
  592. m_fDisconnected = fDisconnected;
  593. m_unlock();
  594. }
  595. //=======================================================================
  596. // CAUState::GetRegDWordValue
  597. //=======================================================================
  598. HRESULT CAUState::GetRegDWordValue(LPCTSTR lpszValueName, LPDWORD pdwValue, enumAUPolicyType enPolicyType)
  599. {
  600. if (lpszValueName == NULL)
  601. {
  602. return E_INVALIDARG;
  603. }
  604. return ::GetRegDWordValue(lpszValueName, pdwValue,
  605. (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY);
  606. }
  607. //=======================================================================
  608. // CAUState::SetRegDWordValue
  609. //=======================================================================
  610. HRESULT CAUState::SetRegDWordValue(LPCTSTR lpszValueName, DWORD dwValue, enumAUPolicyType enPolicyType, DWORD options)
  611. {
  612. if (lpszValueName == NULL)
  613. {
  614. return E_INVALIDARG;
  615. }
  616. return ::SetRegDWordValue(lpszValueName, dwValue, options,
  617. (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY);
  618. }
  619. //=======================================================================
  620. // CAUState::GetRegStringValue
  621. //=======================================================================
  622. HRESULT CAUState::GetRegStringValue(LPCTSTR lpszValueName, LPTSTR lpszBuffer, int nCharCount, enumAUPolicyType enPolicyType)
  623. {
  624. LPCTSTR pszSubKey;
  625. if (lpszValueName == NULL || lpszBuffer == NULL)
  626. {
  627. return E_INVALIDARG;
  628. }
  629. switch (enPolicyType)
  630. {
  631. case enAU_DomainPolicy: pszSubKey = AUREGKEY_HKLM_DOMAIN_POLICY; break;
  632. case enAU_AdminPolicy: pszSubKey = AUREGKEY_HKLM_ADMIN_POLICY; break;
  633. case enAU_WindowsUpdatePolicy: pszSubKey = AUREGKEY_HKLM_WINDOWSUPDATE_POLICY; break;
  634. case enAU_IUControlPolicy: pszSubKey = AUREGKEY_HKLM_IUCONTROL_POLICY; break;
  635. default: return E_INVALIDARG;
  636. }
  637. return ::GetRegStringValue(lpszValueName, lpszBuffer, nCharCount, pszSubKey);
  638. }
  639. //=======================================================================
  640. // CAUState::SetRegStringValue
  641. //=======================================================================
  642. HRESULT CAUState::SetRegStringValue(LPCTSTR lpszValueName, LPCTSTR lpszNewValue, enumAUPolicyType enPolicyType)
  643. {
  644. HKEY hKey;
  645. HRESULT hRet = E_FAIL;
  646. DWORD dwResult;
  647. if (lpszValueName == NULL || lpszNewValue == NULL)
  648. {
  649. return E_INVALIDARG;
  650. }
  651. return ::SetRegStringValue(lpszValueName, lpszNewValue,
  652. (enAU_DomainPolicy == enPolicyType) ? AUREGKEY_HKLM_DOMAIN_POLICY : AUREGKEY_HKLM_ADMIN_POLICY);
  653. }
  654. //=======================================================================
  655. // Calculate Scheduled Date
  656. //=======================================================================
  657. HRESULT CAUState::m_CalculateScheduledInstallDate(AUFILETIME & auftSchedInstallDate,
  658. DWORD *pdwSleepTime)
  659. {
  660. if ( (-1 == m_PolicySettings.m_dwSchedInstallDay) || (-1 == m_PolicySettings.m_dwSchedInstallTime) )
  661. {
  662. return E_INVALIDARG;
  663. }
  664. //DEBUGMSG("Schedule day: %d, time: %d", m_dwSchedInstallDay, m_dwSchedInstallTime);
  665. AUFILETIME auftNow;
  666. SYSTEMTIME stNow;
  667. GetLocalTime(&stNow);
  668. if ( !SystemTimeToFileTime(&stNow, &auftNow.ft) )
  669. {
  670. return HRESULT_FROM_WIN32(GetLastError());
  671. }
  672. SYSTEMTIME stScheduled = stNow;
  673. stScheduled.wHour = (WORD)m_PolicySettings.m_dwSchedInstallTime;
  674. stScheduled.wMinute = stScheduled.wSecond = stScheduled.wMilliseconds = 0;
  675. DWORD dwSchedInstallDayOfWeek = (0 == m_PolicySettings.m_dwSchedInstallDay) ? stNow.wDayOfWeek : (m_PolicySettings.m_dwSchedInstallDay - 1);
  676. DWORD dwDaysToAdd = (7 + dwSchedInstallDayOfWeek - stNow.wDayOfWeek) % 7;
  677. //DEBUGMSG("daystoadd %d", dwDaysToAdd);
  678. AUFILETIME auftScheduled;
  679. if ( !SystemTimeToFileTime(&stScheduled, &auftScheduled.ft) )
  680. {
  681. return HRESULT_FROM_WIN32(GetLastError());
  682. }
  683. auftScheduled.ull += (ULONGLONG)dwDaysToAdd * AU_ONE_DAY * NanoSec100PerSec;
  684. if ( auftScheduled.ull < auftNow.ull )
  685. {
  686. // we missed the time today, go to next scheduled day
  687. auftScheduled.ull += (ULONGLONG)((0 == m_PolicySettings.m_dwSchedInstallDay) ? AU_ONE_DAY : AU_ONE_WEEK) * NanoSec100PerSec;
  688. }
  689. auftSchedInstallDate = auftScheduled;
  690. *pdwSleepTime = (DWORD)((auftScheduled.ull - auftNow.ull) / NanoSec100PerSec);
  691. return S_OK;
  692. }
  693. //=======================================================================
  694. // CAUState::CalculateScheduledInstallSleepTime
  695. //=======================================================================
  696. HRESULT CAUState::CalculateScheduledInstallSleepTime(DWORD *pdwSleepTime)
  697. {
  698. HRESULT hr = S_OK;
  699. *pdwSleepTime = 0;
  700. if (!m_lock())
  701. {
  702. return HRESULT_FROM_WIN32(GetLastError());
  703. }
  704. if ( (-1 == m_PolicySettings.m_dwSchedInstallDay) || (-1 == m_PolicySettings.m_dwSchedInstallTime) )
  705. {
  706. hr = E_INVALIDARG;
  707. goto done;
  708. }
  709. AUFILETIME auftSchedInstallDate;
  710. if (SUCCEEDED(hr = m_CalculateScheduledInstallDate(auftSchedInstallDate, pdwSleepTime)))
  711. {
  712. if (m_auftSchedInstallDate.ull != auftSchedInstallDate.ull)
  713. { //recalculate sleep time if anything changes
  714. m_auftSchedInstallDate = auftSchedInstallDate;
  715. if (S_OK == (hr = m_SetScheduledInstallDate()))
  716. {
  717. hr = S_FALSE;
  718. }
  719. }
  720. }
  721. AUFILETIME auftNow;
  722. SYSTEMTIME stNow;
  723. GetLocalTime(&stNow);
  724. if ( !SystemTimeToFileTime(&stNow, &auftNow.ft) )
  725. {
  726. hr = HRESULT_FROM_WIN32(GetLastError());
  727. goto done;
  728. }
  729. if (AUFT_INVALID_VALUE != m_auftSchedInstallDate.ull)
  730. {
  731. if ( auftNow.ull < m_auftSchedInstallDate.ull )
  732. {
  733. *pdwSleepTime = (DWORD) ((m_auftSchedInstallDate.ull - auftNow.ull) / NanoSec100PerSec);
  734. }
  735. else if ( ((auftNow.ull - m_auftSchedInstallDate.ull) / NanoSec100PerSec) <= AU_TEN_MINS )
  736. {
  737. // we should have done the scheduled install within the
  738. // last 10 minutes. Close enough, do it now.
  739. }
  740. }
  741. done:
  742. // DEBUGMSG("CalculateScheduleInstallSleepTime return %d sleeping secs with result %#lx", *pdwSleepTime, hr);
  743. m_unlock();
  744. return hr;
  745. }
  746. //=======================================================================
  747. // CAUState::SetDetectionStartTime
  748. //=======================================================================
  749. void CAUState::SetDetectionStartTime(BOOL fOverwrite)
  750. {
  751. if (!m_lock())
  752. {
  753. return ;
  754. }
  755. if (fOverwrite || AUFT_INVALID_VALUE == m_auftDetectionStartTime.ull)
  756. {
  757. AUFILETIME auftNow;
  758. SYSTEMTIME stNow;
  759. GetLocalTime(&stNow);
  760. if (SystemTimeToFileTime(&stNow, &auftNow.ft))
  761. {
  762. HRESULT hr;
  763. TCHAR tszDetectionStartTime[20];
  764. if (SUCCEEDED(hr = FileTime2String(auftNow.ft, tszDetectionStartTime, ARRAYSIZE(tszDetectionStartTime))))
  765. {
  766. m_auftDetectionStartTime = auftNow;
  767. DEBUGMSG("New last connection check time: %S", tszDetectionStartTime);
  768. SetRegStringValue(REG_AUDETECTIONSTARTTIME, tszDetectionStartTime, enAU_AdminPolicy);
  769. }
  770. else
  771. {
  772. DEBUGMSG("failed m_SetScheduledInstallDate() == %#lx", hr);
  773. }
  774. }
  775. }
  776. else
  777. {
  778. DEBUGMSG("CAUState::SetDetectionStartTime() fOverwrite==FALSE, time(%#lx%8lx) != AUFT_INVALID_VALUE.", m_auftDetectionStartTime.ft.dwHighDateTime, m_auftDetectionStartTime.ft.dwLowDateTime);
  779. }
  780. m_unlock();
  781. }
  782. //=======================================================================
  783. // CAUState::IsUnableToConnect
  784. //=======================================================================
  785. BOOL CAUState::IsUnableToConnect(void)
  786. {
  787. AUFILETIME auftNow;
  788. SYSTEMTIME stNow;
  789. GetLocalTime(&stNow);
  790. if (!SystemTimeToFileTime(&stNow, &auftNow.ft))
  791. {
  792. return FALSE; //REVIEW: or return TRUE?
  793. }
  794. if (!m_lock())
  795. {
  796. return FALSE;
  797. }
  798. BOOL fRet = FALSE;
  799. if (AUFT_INVALID_VALUE != m_auftDetectionStartTime.ull &&
  800. (auftNow.ull - m_auftDetectionStartTime.ull) / NanoSec100PerSec >= dwSecsToWait(AU_TWO_DAYS))
  801. {
  802. fRet = TRUE;
  803. }
  804. m_unlock();
  805. return fRet;
  806. }
  807. //=======================================================================
  808. // CAUState::RemoveDetectionStartTime
  809. //=======================================================================
  810. void CAUState::RemoveDetectionStartTime(void)
  811. {
  812. if (!m_lock())
  813. {
  814. return ;
  815. }
  816. DeleteRegValue(REG_AUDETECTIONSTARTTIME);
  817. m_auftDetectionStartTime.ull = AUFT_INVALID_VALUE;
  818. m_unlock();
  819. }
  820. #ifdef DBG
  821. //=======================================================================
  822. // CAUState::m_DbgDumpState
  823. //=======================================================================
  824. void CAUState::m_DbgDumpState(void)
  825. {
  826. DEBUGMSG("======= Initial State Dump =========");
  827. m_PolicySettings.m_DbgDump();
  828. DEBUGMSG("State: %d", m_dwState);
  829. TCHAR szSchedInstallDate[20];
  830. if ( 0 == m_auftSchedInstallDate.ull )
  831. {
  832. (void)StringCchCopyEx(szSchedInstallDate, ARRAYSIZE(szSchedInstallDate), _T("none"), NULL, NULL, MISTSAFE_STRING_FLAGS);
  833. }
  834. else
  835. {
  836. if ( FAILED(FileTime2String(m_auftSchedInstallDate.ft, szSchedInstallDate, ARRAYSIZE(szSchedInstallDate))) )
  837. {
  838. (void)StringCchCopyEx(szSchedInstallDate, ARRAYSIZE(szSchedInstallDate), _T("invalid"), NULL, NULL, MISTSAFE_STRING_FLAGS);
  839. }
  840. }
  841. DEBUGMSG("ScheduledInstallDate: %S", szSchedInstallDate);
  842. //DEBUGMSG("WUServer Value: %S", gpState->GetWUServerURL());
  843. DEBUGMSG("Ident Server: %S", gpState->GetIdentServerURL());
  844. DEBUGMSG("Self Update Server URL Override: %S", (NULL != gpState->GetSelfUpdateServerURLOverride()) ? gpState->GetSelfUpdateServerURLOverride() : _T("none"));
  845. DEBUGMSG("=====================================");
  846. }
  847. #endif