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.

1329 lines
41 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #define MAINWINDOW_CURSOR IDC_ARROW
  4. #define RESOURCE_STRING_MAX_LENGTH 100
  5. TCHAR AU_WINDOW_CLASS_NAME[] = _T("Auto Update Client Window");
  6. const TCHAR gtszAUW2KPrivacyUrl[]= _T("..\\help\\wuauhelp.chm::/w2k_autoupdate_privacy.htm");
  7. const TCHAR gtszAUXPPrivacyUrl[]= _T("..\\help\\wuauhelp.chm::/autoupdate_privacy.htm");
  8. const ReminderItem ReminderTimes[TIMEOUT_INX_COUNT] =
  9. {
  10. { 1800, IDS_THIRTY_MINUTES },
  11. { 3600, IDS_ONE_HOUR },
  12. { 7200, IDS_TWO_HOURS },
  13. { 14400, IDS_FOUR_HOURS },
  14. { 86400, IDS_TOMORROW },
  15. { 259200, IDS_THREE_DAYS }
  16. };
  17. const UINT RESOURCESTRINGINDEX[] = {
  18. IDS_NOTE,
  19. IDS_WELCOME_CONTINUE,
  20. IDS_EULA,
  21. IDS_PRIVACY,
  22. IDS_LEARNMORE,
  23. IDS_LEARNMOREAUTO
  24. };
  25. // Global Data Items
  26. CAUInternals* gInternals;
  27. AUClientCatalog *gpClientCatalog ; //= NULL
  28. TCHAR gResStrings[ARRAYSIZE(RESOURCESTRINGINDEX)][RESOURCE_STRING_MAX_LENGTH];
  29. // Global UI Items
  30. CRITICAL_SECTION gcsClient; // guard guard user's tray interaction (showing, not showing) and guard customlb data
  31. HINSTANCE ghInstance;
  32. HFONT ghHeaderFont;
  33. HCURSOR ghCursorHand;
  34. HCURSOR ghCursorNormal; // cursor of main window
  35. HMODULE ghRichEd20;
  36. HANDLE ghEngineState;
  37. HWND ghMainWindow;
  38. HWND ghCurrentDialog;
  39. HWND ghCurrentMainDlg;
  40. AUCLTTopWindows gTopWins;
  41. UINT gNextDialogMsg;
  42. BOOL gbOnlySession; // = FALSE;
  43. BOOL gfShowingInstallWarning; // = FALSE;
  44. HMENU ghPauseMenu;
  45. HMENU ghResumeMenu;
  46. HMENU ghCurrentMenu;
  47. HICON ghAppIcon;
  48. HICON ghAppSmIcon;
  49. HICON ghTrayIcon;
  50. UINT guExitProcess=CDWWUAUCLT_UNSPECIFY;
  51. LPCTSTR gtszAUSchedInstallUrl;
  52. LPCTSTR gtszAUPrivacyUrl;
  53. AU_ENV_VARS gAUEnvVars;
  54. HANDLE g_hClientNotifyEvt = NULL; //the event Engine use to notify client
  55. HANDLE g_hRegisterWait = NULL;
  56. BOOL g_fCoInit = FALSE;
  57. BOOL g_fcsInit = FALSE;
  58. /****
  59. Helper function to simplify window class registration.
  60. *****/
  61. ATOM AURegisterWindowClass(WNDPROC lpWndProc, LPTSTR lpClassName)
  62. {
  63. WNDCLASSEX wcex;
  64. ZeroMemory(&wcex, sizeof(wcex));
  65. wcex.cbSize = sizeof(WNDCLASSEX);
  66. wcex.style = CS_HREDRAW | CS_VREDRAW;
  67. wcex.lpfnWndProc = (WNDPROC)lpWndProc;
  68. // wcex.cbClsExtra = 0;
  69. // wcex.cbWndExtra = 0;
  70. // wcex.lpszMenuName = NULL;
  71. // wcex.hIcon = NULL;
  72. // wcex.hIconSm = NULL;
  73. wcex.hInstance = ghInstance;
  74. wcex.hCursor = LoadCursor(NULL, MAINWINDOW_CURSOR);
  75. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  76. wcex.lpszClassName = lpClassName;
  77. return RegisterClassEx(&wcex);
  78. }
  79. ///////////////////////////////////////////////////////////////////
  80. // map string id to its storage in the gResStrings
  81. ///////////////////////////////////////////////////////////////////
  82. LPTSTR ResStrFromId(UINT uStrId)
  83. {
  84. for (int i = 0; i < ARRAYSIZE(RESOURCESTRINGINDEX); i++)
  85. {
  86. if (RESOURCESTRINGINDEX[i] == uStrId)
  87. {
  88. return gResStrings[i];
  89. }
  90. }
  91. return NULL;
  92. }
  93. ////////////////////////////////////////////////////////
  94. // Set reminder timeout and state and quit
  95. ////////////////////////////////////////////////////////
  96. void QuitNRemind(TIMEOUTINDEX enTimeoutIndex)
  97. {
  98. AUSTATE auState;
  99. if (FAILED(gInternals->m_getServiceState(&auState)))
  100. {
  101. goto done;
  102. }
  103. if (FAILED(gInternals->m_setReminderTimeout(enTimeoutIndex)))
  104. {
  105. goto done;
  106. }
  107. gInternals->m_setReminderState(auState.dwState);
  108. done:
  109. QUITAUClient();
  110. }
  111. ////////////////////////////////////////////////////////////////////////////
  112. //
  113. // Helper Function HrQuerySessionConnectState(int iAdminSession, int *piConState)
  114. // helper function to get the Session Connection State
  115. //
  116. // Input: int iAdminSession Session Admin ID
  117. // Output: int *piConState Conection state
  118. // Return: HRESULT value. If Failed, *piConState is unspecified
  119. ////////////////////////////////////////////////////////////////////////////
  120. HRESULT HrQuerySessionConnectState(int iAdminSession, int *piConState)
  121. {
  122. LPTSTR pBuffer = NULL;
  123. HRESULT hr = NO_ERROR;
  124. DWORD dwBytes;
  125. if (AUIsTSRunning())
  126. {
  127. if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, iAdminSession, WTSConnectState,
  128. &pBuffer, &dwBytes))
  129. {
  130. *piConState = (int) *pBuffer; //Because we are asking for WTSConnectState, pBuffer points to an int
  131. WTSFreeMemory(pBuffer);
  132. hr = NO_ERROR;
  133. }
  134. else
  135. {
  136. DEBUGMSG("WUAUCLT: WTSQuerySessionInformation failed: %lu", GetLastError());
  137. hr = HRESULT_FROM_WIN32(GetLastError());
  138. }
  139. }
  140. else
  141. {
  142. DWORD dwSession = iAdminSession;
  143. if (dwSession == WTS_CURRENT_SESSION)
  144. ProcessIdToSessionId(GetCurrentProcessId(), &dwSession);
  145. // if we're launched & TS is not up, we've gotta be an active session.
  146. if (dwSession == 0)
  147. {
  148. DEBUGMSG("WUAUCLT: TS is not running or not installed. Assuming session 0 is active.");
  149. gbOnlySession = TRUE;
  150. *piConState = WTSActive;
  151. }
  152. else
  153. {
  154. DEBUGMSG("WUAUCLT: TS is not running or not installed, but a non 0 session was asked for (session %d). Failing call.", iAdminSession);
  155. hr = E_FAIL;
  156. }
  157. }
  158. return hr;
  159. }
  160. BOOL FCurrentSessionInActive()
  161. {
  162. BOOL fRet = FALSE;
  163. HRESULT hr;
  164. int iConState;
  165. if (gbOnlySession)
  166. {
  167. DEBUGMSG("FCurrentSessionInActive() Only one session");
  168. goto Done;
  169. }
  170. //Check if the Current Session is Inactive
  171. hr = HrQuerySessionConnectState(WTS_CURRENT_SESSION, &iConState);
  172. if (SUCCEEDED(hr))
  173. {
  174. fRet = (WTSDisconnected == iConState);
  175. }
  176. else
  177. {
  178. if (RPC_S_INVALID_BINDING == GetLastError()) //Terminal Services are disabled, this is session 0
  179. {
  180. DEBUGMSG("FCurrentSessionInActive() TS disabled");
  181. gbOnlySession = TRUE;
  182. }
  183. else
  184. {
  185. DEBUGMSG("FCurrentSessionInActive() HrQuerySessionConnectState failed %#lx =",hr);
  186. }
  187. }
  188. Done:
  189. // DEBUGMSG("FCurrentSessionInActive() return %s", fRet ? "TRUE" : "FALSE");
  190. return fRet;
  191. }
  192. //////////////////////////////////////////////////////////////////////////////
  193. // BuildClientCatalog
  194. //
  195. // Do online detection of the catalog and build up the wuv3is.dll detection state
  196. // inside this process. Validation is done during this process with the catalog file
  197. // previously written by the engine.
  198. //
  199. //////////////////////////////////////////////////////////////////////////////
  200. HRESULT BuildClientCatalog(void)
  201. {
  202. HRESULT hr = S_OK;
  203. DEBUGMSG("BuildClientCatalog() starts");
  204. if ( NULL == gpClientCatalog )
  205. {
  206. gpClientCatalog = new AUClientCatalog();
  207. if ( NULL != gpClientCatalog )
  208. {
  209. if ( FAILED(hr = gpClientCatalog->Init()) )
  210. {
  211. goto done;
  212. }
  213. }
  214. else
  215. {
  216. hr = E_OUTOFMEMORY;
  217. goto done;
  218. }
  219. }
  220. // change to: hr = gpClientCatalog->LoadInstallXML();
  221. done:
  222. DEBUGMSG("BuildClientCatalog() ends");
  223. return hr;
  224. }
  225. void DismissUIIfAny()
  226. {
  227. gTopWins.Add(ghCurrentMainDlg);
  228. gTopWins.Dismiss();
  229. // Don't leave any popup menu around when dismissing dialogs.
  230. if (SendMessage(ghMainWindow, WM_CANCELMODE, 0, 0))
  231. {
  232. DEBUGMSG("WUAUCLT WM_CANCELMODE was not handled");
  233. }
  234. }
  235. void ResetAUClient(void)
  236. {
  237. DismissUIIfAny();
  238. RemoveTrayIcon();
  239. gfShowingInstallWarning = FALSE;
  240. gNextDialogMsg = NULL;
  241. ghCurrentMenu = NULL;
  242. }
  243. void ShowInstallWarning()
  244. { //dismiss current dialog if any
  245. DEBUGMSG("ShowInstallWarning() starts");
  246. gfShowingInstallWarning = TRUE;
  247. gNextDialogMsg = NULL;
  248. ghCurrentMenu = NULL;
  249. CPromptUserDlg PromptUserDlg(IDD_START_INSTALL);
  250. PromptUserDlg.SetInstanceHandle(ghInstance);
  251. INT iRet = PromptUserDlg.DoModal(NULL);
  252. DEBUGMSG("WUAUCLT ShowInstallWarning dlg return code is %d", iRet);
  253. if (IDYES == iRet || AU_IDTIMEOUT == iRet)
  254. {
  255. SetClientExitCode(CDWWUAUCLT_INSTALLNOW);
  256. QUITAUClient();
  257. }
  258. else //if (retVal == IDNO)
  259. {
  260. gNextDialogMsg = AUMSG_SHOW_INSTALL;
  261. }
  262. gfShowingInstallWarning = FALSE;
  263. DEBUGMSG("ShowInstallWarning() ends");
  264. }
  265. void ShowRebootWarning(BOOL fEnableYes, BOOL fEnableNo)
  266. {
  267. DEBUGMSG("ShowRebootWarning() starts");
  268. INT iRet;
  269. CPromptUserDlg PromptUserDlg(IDD_PROMPT_RESTART, fEnableYes, fEnableNo);
  270. PromptUserDlg.SetInstanceHandle(ghInstance);
  271. iRet = PromptUserDlg.DoModal(NULL);
  272. if (IDYES == iRet)
  273. {
  274. SetClientExitCode(CDWWUAUCLT_REBOOTNOW);
  275. }
  276. else if (IDNO == iRet)
  277. {
  278. SetClientExitCode(CDWWUAUCLT_REBOOTLATER);
  279. }
  280. else //if (IDTIMEOUT == iRet)
  281. {
  282. SetClientExitCode(CDWWUAUCLT_REBOOTTIMEOUT);
  283. }
  284. QUITAUClient();
  285. DEBUGMSG("ShowRebootWarning() ends with return code %d", iRet);
  286. DEBUGMSG("ShowRebootWarning() set client exit code to be %d", GetClientExitCode());
  287. }
  288. VOID CALLBACK WaitCallback(PVOID lpParameter, BOOLEAN /*fTimerOrWaitFired*/ )
  289. {
  290. // fTimerOrWaitFired is always false - We can't time out with INFINATE wait
  291. BOOL fRebootWarningMode = (BOOL) PtrToInt(lpParameter);
  292. if (fRebootWarningMode)
  293. {
  294. DEBUGMSG("WUAUCLT got exit signal from engine");
  295. QUITAUClient();
  296. return ;
  297. }
  298. // ClientNotify event was fired
  299. CLIENT_NOTIFY_DATA notifyData;
  300. BOOL fCoInit = SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
  301. if ( !fCoInit )
  302. {
  303. DEBUGMSG("WUAUCLT WaitCallback CoInitialize failed");
  304. goto Done;
  305. }
  306. IUpdates * pUpdates = NULL;
  307. HRESULT hr = CoCreateInstance(__uuidof(Updates),
  308. NULL,
  309. CLSCTX_LOCAL_SERVER,
  310. IID_IUpdates,
  311. (LPVOID*)&pUpdates);
  312. if (FAILED(hr))
  313. {
  314. DEBUGMSG("WaitCallback failed to get Updates object");
  315. goto Done;
  316. }
  317. if (FAILED(hr = pUpdates->GetNotifyData(&notifyData)))
  318. {
  319. DEBUGMSG("WaitCallback fail to get NotifyData %#lx", hr);
  320. goto Done;
  321. }
  322. switch (notifyData.actionCode)
  323. {
  324. case NOTIFY_STOP_CLIENT:
  325. case NOTIFY_RELAUNCH_CLIENT:
  326. if (NOTIFY_RELAUNCH_CLIENT == notifyData.actionCode)
  327. {
  328. DEBUGMSG("WaitCallback() notify client to relaunch");
  329. SetClientExitCode(CDWWUAUCLT_RELAUNCHNOW);
  330. }
  331. else
  332. {
  333. DEBUGMSG("WaitCallback() notify client to stop");
  334. SetClientExitCode(CDWWUAUCLT_OK);
  335. }
  336. if (NULL != ghMutex)
  337. {
  338. WaitForSingleObject(ghMutex, INFINITE);
  339. if (NULL != gpClientCatalog)
  340. {
  341. gpClientCatalog->CancelNQuit();
  342. }
  343. else
  344. {
  345. DEBUGMSG("No need to cancel catalag");
  346. }
  347. ReleaseMutex(ghMutex);
  348. }
  349. QUITAUClient();
  350. break;
  351. case NOTIFY_RESET: //reprocess state and option and show UI accordingly
  352. ResetAUClient();
  353. SetEvent(ghEngineState);
  354. break;
  355. case NOTIFY_ADD_TRAYICON:
  356. DEBUGMSG("WaitCallback() notify client to show tray icon");
  357. ShowTrayIcon();
  358. ghCurrentMenu = ghPauseMenu; //the job is now downloading
  359. break;
  360. case NOTIFY_REMOVE_TRAYICON:
  361. DEBUGMSG("WaitCallback() notify client to remove tray icon");
  362. RemoveTrayIcon();
  363. break;
  364. case NOTIFY_STATE_CHANGE:
  365. DEBUGMSG("WaitCallback() notify client of state change");
  366. SetEvent(ghEngineState);
  367. break;
  368. case NOTIFY_SHOW_INSTALLWARNING:
  369. DEBUGMSG("WaitCallback() notify client to show install warning");
  370. if (!gfShowingInstallWarning)
  371. { //install warning dialog is not up, prevent install warning dialog torn down before it expires when secsinaday low
  372. DismissUIIfAny();
  373. PostMessage(ghMainWindow, AUMSG_SHOW_INSTALLWARNING, 0, 0);
  374. }
  375. break;
  376. }
  377. Done:
  378. SafeRelease(pUpdates);
  379. if (fCoInit)
  380. {
  381. CoUninitialize();
  382. }
  383. }
  384. BOOL ProcessEngineState()
  385. {
  386. AUSTATE AuState;
  387. BOOL fResult = TRUE;
  388. DEBUGMSG("WUAUCLT starts ProcessEngineState()");
  389. ghCurrentMenu = NULL;
  390. if (FAILED(gInternals->m_getServiceState(&AuState)))
  391. {
  392. DEBUGMSG("WUAUCLT : quit because m_getServiceState failed");
  393. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  394. fResult = FALSE;
  395. goto Done;
  396. }
  397. DEBUGMSG("WUAUCLT process Engine state %lu",AuState.dwState);
  398. switch(AuState.dwState)
  399. {
  400. case AUSTATE_NOT_CONFIGURED:
  401. if(gNextDialogMsg != AUMSG_SHOW_WELCOME && ghCurrentMainDlg == NULL )
  402. {
  403. if (ShowTrayIcon())
  404. {
  405. ShowTrayBalloon(IDS_WELCOMETITLE, IDS_WELCOMECAPTION, IDS_WELCOMETITLE);
  406. gNextDialogMsg = AUMSG_SHOW_WELCOME;
  407. }
  408. }
  409. break;
  410. case AUSTATE_DETECT_COMPLETE:
  411. if ( FAILED(gInternals->m_getServiceUpdatesList()) )
  412. {
  413. DEBUGMSG("WUAUCLT : quit because m_getServiceUpdatesList failed");
  414. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  415. fResult = FALSE;
  416. break;
  417. }
  418. {
  419. AUOPTION auopt;
  420. if (SUCCEEDED(gInternals->m_getServiceOption(&auopt)) &&
  421. (AUOPTION_INSTALLONLY_NOTIFY == auopt.dwOption || AUOPTION_SCHEDULED == auopt.dwOption))
  422. {
  423. // user option is auto download, start download
  424. //ShowTrayIcon();
  425. // do download right away without dialogs if user options set to notify for just install
  426. if (FAILED(gInternals->m_startDownload()))
  427. {
  428. QUITAUClient();
  429. }
  430. else
  431. {
  432. // ghCurrentMenu = ghPauseMenu;
  433. }
  434. break;
  435. }
  436. if(gNextDialogMsg != AUMSG_SHOW_DOWNLOAD && ghCurrentMainDlg == NULL)
  437. {
  438. if (ShowTrayIcon())
  439. {
  440. ShowTrayBalloon(IDS_DOWNLOADTITLE, IDS_DOWNLOADCAPTION, IDS_DOWNLOADTITLE);
  441. gNextDialogMsg = AUMSG_SHOW_DOWNLOAD;
  442. }
  443. }
  444. break;
  445. }
  446. case AUSTATE_DOWNLOAD_COMPLETE:
  447. if (AUCLT_ACTION_AUTOINSTALL == AuState.dwCltAction)
  448. { // engine initiated install: auto install
  449. HRESULT hr;
  450. DEBUGMSG("Auto install ...");
  451. if ( S_OK !=(hr = BuildClientCatalog()))
  452. {
  453. DEBUGMSG("WUAUCLT fail to build client catalog with error %#lx, exiting, hr");
  454. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  455. fResult = FALSE;
  456. break;
  457. }
  458. if (FAILED(hr = gInternals->m_startInstall(TRUE)))
  459. {
  460. DEBUGMSG("Fail to post install message with error %#lx", hr);
  461. fResult = FALSE;
  462. break;
  463. }
  464. gpClientCatalog->m_WrkThread.WaitUntilDone();
  465. if (gpClientCatalog->m_fReboot)
  466. {
  467. SetClientExitCode(CDWWUAUCLT_REBOOTNEEDED);
  468. }
  469. else
  470. {
  471. SetClientExitCode(CDWWUAUCLT_OK);
  472. }
  473. QUITAUClient();
  474. break;
  475. }
  476. else
  477. { //show preinstall dialog and let user initiate install
  478. HRESULT hr;
  479. DEBUGMSG("Prompt for manual install");
  480. if ( FAILED(gInternals->m_getServiceUpdatesList()))
  481. {
  482. DEBUGMSG("WUAUCLT : quit because m_getServiceUpdatesList failed");
  483. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  484. fResult = FALSE;
  485. break;
  486. }
  487. if ( S_OK !=(hr = BuildClientCatalog()) )
  488. {
  489. DEBUGMSG("WUAUCLT fail to build client catalog with error %#lx, exiting", hr);
  490. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  491. fResult = FALSE;
  492. }
  493. else if(gNextDialogMsg != AUMSG_SHOW_INSTALL && ghCurrentMainDlg == NULL)
  494. {
  495. if (ShowTrayIcon())
  496. {
  497. ShowTrayBalloon(IDS_INSTALLTITLE, IDS_INSTALLCAPTION, IDS_INSTALLTITLE);
  498. gNextDialogMsg = AUMSG_SHOW_INSTALL;
  499. }
  500. }
  501. break;
  502. }
  503. case AUSTATE_DOWNLOAD_PENDING:
  504. {
  505. UINT nPercentComplete = 0;
  506. DWORD dwStatus;
  507. //if drizzle got transient error, quit client
  508. //fixcode: why quit if transient error?
  509. if (AuState.fDisconnected)
  510. {
  511. DEBUGMSG("WUAUCLT : quit because of lost of connection, fDisconnected = %d",AuState.fDisconnected);
  512. fResult = FALSE;
  513. break;
  514. }
  515. if (FAILED(gInternals->m_getDownloadStatus(&nPercentComplete, &dwStatus)))
  516. {
  517. DEBUGMSG("WUAUCLT : quit because m_getDownloadStatus failed");
  518. fResult = FALSE;
  519. break;
  520. }
  521. if (DWNLDSTATUS_CHECKING_CONNECTION == dwStatus)
  522. {
  523. //hide tray icon
  524. DEBUGMSG("WUAUCLT Waiting for engine to find connection first");
  525. // RemoveTrayIcon();
  526. // ghCurrentMenu = NULL;
  527. }
  528. else if(dwStatus == DWNLDSTATUS_DOWNLOADING)
  529. {
  530. ghCurrentMenu = ghPauseMenu;
  531. DEBUGMSG("WUAUCLT in active downloading state");
  532. ShowTrayIcon();
  533. }
  534. else if(dwStatus == DWNLDSTATUS_PAUSED)
  535. {
  536. ghCurrentMenu = ghResumeMenu;
  537. DEBUGMSG("WUAUCLT in download paused state");
  538. if (fDisableSelection() &&
  539. FAILED(gInternals->m_setDownloadPaused(FALSE)))
  540. {
  541. // QUITAUClient(); //let wuaueng to figure out problem and recover
  542. }
  543. ShowTrayIcon();
  544. }
  545. else //not downloading
  546. {
  547. DEBUGMSG("WUAUCLT WARNING: not downloading while in download pending state");
  548. }
  549. }
  550. break;
  551. case AUSTATE_DETECT_PENDING:
  552. //Quit only if the Install UI has been accepted or there is no InstallUI
  553. if (NULL == ghCurrentMainDlg)
  554. {
  555. QUITAUClient();
  556. }
  557. break;
  558. case AUSTATE_DISABLED:
  559. QUITAUClient();
  560. break;
  561. case AUSTATE_INSTALL_PENDING:
  562. default:
  563. // outofbox and waiting_for_reboot are here. WUAUCLT should not be launched in these states
  564. DEBUGMSG("WUAUCLT AUSTATE = %lu", AuState.dwState);
  565. break;
  566. }
  567. Done:
  568. DEBUGMSG("WUAUCLT exits ProcessEngineState()");
  569. return fResult;
  570. }
  571. BOOL InitUIComponents(HINSTANCE hInstance)
  572. {
  573. INITCOMMONCONTROLSEX icex;
  574. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  575. icex.dwICC = 0; //We dont need to register any control classes
  576. if (!InitCommonControlsEx(&icex)) //needed for theming
  577. {
  578. DEBUGMSG("InitUIComponents :InitCommonControlsEx failed");
  579. return FALSE;
  580. }
  581. //we need to load riched20.dll to register the class
  582. ghRichEd20 = LoadLibraryFromSystemDir(_T("RICHED20.dll"));
  583. if (NULL == ghRichEd20)
  584. {
  585. return FALSE;
  586. }
  587. ghCursorHand = LoadCursor(NULL, IDC_HAND);
  588. ghCursorNormal = LoadCursor(NULL, MAINWINDOW_CURSOR); //change if main window's cursor does
  589. if (NULL == ghCursorHand)
  590. {
  591. DEBUGMSG("WUAUCLT fail to load hand cursor");
  592. ghCursorHand = ghCursorNormal;
  593. }
  594. ghAppIcon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_AUICON), IMAGE_ICON, NULL, NULL, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
  595. ghAppSmIcon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_AUICON), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_CREATEDIBSECTION);
  596. if (IsWin2K())
  597. {
  598. //Win2k
  599. ghTrayIcon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_AUSYSTRAYICON), IMAGE_ICON, 16, 16, 0);
  600. }
  601. else
  602. {
  603. //WindowsXP
  604. ghTrayIcon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_AUICON), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
  605. }
  606. for (int i = 0; i < ARRAYSIZE(RESOURCESTRINGINDEX); i++)
  607. {
  608. LoadString(hInstance, RESOURCESTRINGINDEX[i], ResStrFromId(RESOURCESTRINGINDEX[i]), RESOURCE_STRING_MAX_LENGTH);
  609. }
  610. ghCurrentAccel = LoadAccelerators(ghInstance, MAKEINTRESOURCE(IDA_BASE));
  611. gtszAUSchedInstallUrl = IsWin2K() ? gtszAUW2kSchedInstallUrl : gtszAUXPSchedInstallUrl;
  612. gtszAUPrivacyUrl = IsWin2K() ? gtszAUW2KPrivacyUrl : gtszAUXPPrivacyUrl;
  613. return TRUE;
  614. }
  615. BOOL InitializeAUClientForRebootWarning(HINSTANCE hInstance,
  616. OUT HANDLE *phRegisterWait,
  617. OUT HANDLE *phClientNotifyEvt,
  618. OUT BOOL *pfCoInit)
  619. {
  620. TCHAR buf[100];
  621. SetClientExitCode(CDWWUAUCLT_UNSPECIFY);
  622. *phRegisterWait = NULL;
  623. *pfCoInit = FALSE;
  624. *phClientNotifyEvt = OpenEvent(SYNCHRONIZE, FALSE, gAUEnvVars.m_szClientExitEvtName);
  625. if (NULL == *phClientNotifyEvt)
  626. {
  627. DEBUGMSG("WUAUCLT fail to open client exit event");
  628. return FALSE;
  629. }
  630. INITCOMMONCONTROLSEX icex;
  631. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  632. icex.dwICC = 0; //We dont need to register any control classes
  633. if (!InitCommonControlsEx(&icex)) //needed for theming
  634. {
  635. DEBUGMSG("InitCommonControlsEx failed");
  636. return FALSE;
  637. }
  638. if (!RegisterWaitForSingleObject(phRegisterWait, // wait handle
  639. *phClientNotifyEvt, // handle to object
  640. WaitCallback, // timer callback function
  641. (PVOID)1, // callback function parameter
  642. INFINITE, // time-out interval
  643. WT_EXECUTEONLYONCE // options
  644. ))
  645. {
  646. DEBUGMSG("WUAUCLT RegisterWaitForSingleObject failed %lu",GetLastError());
  647. *phRegisterWait = NULL;
  648. return FALSE;
  649. }
  650. ghInstance = hInstance;
  651. return TRUE;
  652. }
  653. BOOL InitializeAUClient(HINSTANCE hInstance,
  654. OUT HANDLE * phRegisterWait,
  655. OUT HANDLE * phClientNotifyEvt,
  656. OUT BOOL *pfCoInit,
  657. OUT BOOL *pfcsInit)
  658. {
  659. HRESULT hr;
  660. *pfcsInit = FALSE;
  661. *phClientNotifyEvt = NULL;
  662. *phRegisterWait = NULL;
  663. SetClientExitCode(CDWWUAUCLT_UNSPECIFY);
  664. *pfCoInit = SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
  665. if ( !*pfCoInit )
  666. {
  667. DEBUGMSG("WUAUCLT WinMain CoInitialize failed");
  668. return FALSE;
  669. }
  670. if (!InitUIComponents(hInstance))
  671. {
  672. DEBUGMSG("WUAUCLT fail to initialize UI components");
  673. return FALSE;
  674. }
  675. if (NULL == (ghMutex = CreateMutex(NULL, FALSE, NULL)))
  676. {
  677. DEBUGMSG("WUAUCLT fail to create global mutex");
  678. return FALSE;
  679. }
  680. gInternals = NULL;
  681. if ( (NULL == (ghEngineState = CreateEvent(NULL, FALSE, FALSE, NULL))) )
  682. {
  683. DEBUGMSG("WUAUCLT fails to create event");
  684. return FALSE;
  685. }
  686. ghInstance = hInstance;
  687. if (!(*pfcsInit = SafeInitializeCriticalSection(&gcsClient)))
  688. {
  689. DEBUGMSG("WUAUCLT fails to initialize critical section");
  690. return FALSE;
  691. }
  692. #ifndef TESTUI
  693. if (! (gInternals = new CAUInternals()))
  694. {
  695. DEBUGMSG("WUAUCLT fails to create auinternals object");
  696. return FALSE;
  697. }
  698. if (FAILED(hr = gInternals->m_Init()))
  699. {
  700. DEBUGMSG("WUAUCLT failed in CoCreateInstance of service with error %#lx, exiting", hr);
  701. return FALSE;
  702. }
  703. AUEVTHANDLES AuEvtHandles;
  704. ZeroMemory(&AuEvtHandles, sizeof(AuEvtHandles));
  705. if (FAILED(hr = gInternals->m_getEvtHandles(GetCurrentProcessId(), &AuEvtHandles)))
  706. {
  707. DEBUGMSG("WUAUCLT failed in m_getEvtHandles with error %#lx, exiting", hr);
  708. return FALSE;
  709. }
  710. *phClientNotifyEvt = (HANDLE)AuEvtHandles.ulNotifyClient;
  711. if (!RegisterWaitForSingleObject( phRegisterWait, // wait handle
  712. *phClientNotifyEvt, // handle to object
  713. WaitCallback, // timer callback function
  714. 0, // callback function parameter
  715. INFINITE, // time-out interval
  716. WT_EXECUTEDEFAULT // options
  717. ))
  718. {
  719. DEBUGMSG("WUAUCLT RegisterWaitForSingleObject failed %lu",GetLastError());
  720. *phRegisterWait = NULL;
  721. return FALSE;
  722. }
  723. #endif
  724. return TRUE;
  725. }
  726. void UninitializeAUClient(HANDLE hRegisterWait, HANDLE hClientNotifyEvt, BOOL fCoInit, BOOL fcsInit)
  727. {
  728. static BOOL fAlreadyUninit = FALSE;
  729. if (fAlreadyUninit)
  730. {
  731. return;
  732. }
  733. fAlreadyUninit = TRUE;
  734. RemoveTrayIcon();
  735. if (NULL != hRegisterWait)
  736. {
  737. if ( !UnregisterWaitEx(hRegisterWait, INVALID_HANDLE_VALUE) )
  738. {
  739. DEBUGMSG("WUAUCLT: UnregisterWaitEx() failed, dw = %lu", GetLastError());
  740. }
  741. }
  742. if (NULL != ghRichEd20)
  743. {
  744. FreeLibrary(ghRichEd20);
  745. ghRichEd20 = NULL;
  746. }
  747. SafeCloseHandleNULL(hClientNotifyEvt);
  748. if (!gAUEnvVars.m_fRebootWarningMode)
  749. {
  750. //fixcode: is ghMainWindow a valid window here?
  751. KillTimer(ghMainWindow, 1);
  752. if (fcsInit)
  753. {
  754. DeleteCriticalSection(&gcsClient);
  755. }
  756. SafeDeleteNULL(gInternals);
  757. SafeDeleteNULL(gpClientCatalog);
  758. SafeCloseHandleNULL(ghEngineState);
  759. SafeCloseHandleNULL(ghMutex);
  760. }
  761. if ( fCoInit)
  762. {
  763. CoUninitialize();
  764. }
  765. }
  766. int APIENTRY WinMain(HINSTANCE hInstance,
  767. HINSTANCE /*hPrevInstance*/,
  768. LPSTR /*lpCmdLine*/,
  769. int /*nCmdShow*/)
  770. {
  771. HANDLE rhEvents[CNUM_EVENTS];
  772. //Initialize the global pointing to WU Directory. (the directory should already exist)
  773. if(!CreateWUDirectory(TRUE))
  774. {
  775. //If we can not create WU directory, no point in continuing
  776. DEBUGMSG("WUAUCLT Fail to create WU directory");
  777. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  778. goto exit;
  779. }
  780. if (!gAUEnvVars.ReadIn())
  781. {
  782. DEBUGMSG("WUAUCLT fails to read in environment variables");
  783. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  784. goto exit;
  785. }
  786. if (gAUEnvVars.m_fRebootWarningMode)
  787. {
  788. DEBUGMSG("WUAUCLT starts in reboot warning mode");
  789. if (!InitializeAUClientForRebootWarning(hInstance, &g_hRegisterWait, &g_hClientNotifyEvt, &g_fCoInit))
  790. {
  791. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  792. goto exit;
  793. }
  794. }
  795. else
  796. {
  797. DEBUGMSG("WUAUCLT starts in regular mode");
  798. if (!InitializeAUClient(hInstance, &g_hRegisterWait, &g_hClientNotifyEvt, &g_fCoInit, &g_fcsInit))
  799. {
  800. SetClientExitCode(CDWWUAUCLT_FATAL_ERROR);
  801. goto exit;
  802. }
  803. }
  804. DEBUGMSG("WUAUCLT initialization done");
  805. // Create the main window hidden
  806. if (!AURegisterWindowClass(MainWndProc, AU_WINDOW_CLASS_NAME))
  807. {
  808. goto exit;
  809. }
  810. if (!AURegisterWindowClass(CustomLBWndProc, _T("MYLB")))
  811. {
  812. goto exit;
  813. }
  814. if (!CreateWindow(AU_WINDOW_CLASS_NAME, AU_WINDOW_CLASS_NAME, WS_CAPTION,
  815. 0, 0, 0, 0, NULL, NULL, hInstance, NULL))
  816. {
  817. goto exit;
  818. }
  819. ShowWindow(ghMainWindow, SW_HIDE);
  820. #ifdef TESTUI
  821. {
  822. MSG msg;
  823. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  824. {
  825. if (WM_QUIT == msg.message )
  826. {
  827. // Set this event so the service does what every appropriate
  828. // If we don't do this, we might leave the service waiting for this event for
  829. // some cases - for example, when the session in which the client leaves is deactivated or
  830. // when there is a log off
  831. //SetEvent(ghEngineState);
  832. goto exit;
  833. }
  834. TranslateMessage(&msg);
  835. DispatchMessage(&msg);
  836. }
  837. }
  838. #else
  839. {
  840. // Run the main message loop
  841. MSG msg;
  842. if (gAUEnvVars.m_fRebootWarningMode)
  843. {
  844. ShowRebootWarning(gAUEnvVars.m_fEnableYes, gAUEnvVars.m_fEnableNo);
  845. }
  846. else
  847. {
  848. SetTimer(ghMainWindow, 1, dwTimeToWait(ReminderTimes[TIMEOUT_INX_FOUR_HOURS].timeout), NULL); //every 4 hours
  849. DEBUGMSG("WUAUCLT Processing messages and being alert for Engine state change event");
  850. rhEvents[ISTATE_CHANGE] = ghEngineState;
  851. while (1)
  852. {
  853. DWORD dwRet = MsgWaitForMultipleObjectsEx(CNUM_EVENTS, rhEvents, INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
  854. if (WAIT_OBJECT_0 + ISTATE_CHANGE == dwRet) //ghEngineState (ISTATE_CHANGE)
  855. {
  856. DEBUGMSG("WUAUCLT Engine changed state");
  857. if (!ProcessEngineState())
  858. {
  859. QUITAUClient();
  860. }
  861. }
  862. else if (WAIT_OBJECT_0 + IMESSAGE == dwRet) // There is a message to process
  863. {
  864. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  865. {
  866. if (WM_QUIT == msg.message )
  867. {
  868. goto exit;
  869. }
  870. TranslateMessage(&msg);
  871. DispatchMessage(&msg);
  872. }
  873. }
  874. else
  875. {
  876. if (WAIT_ABANDONED_0 == dwRet) //ghEngineState abandoned
  877. {
  878. DEBUGMSG("WUAUCLT quitting because engine state event was abandoned");
  879. }
  880. else if (WAIT_FAILED == dwRet) //MsgWaitForMultipleObjectsEx failed
  881. {
  882. DEBUGMSG("WUAUCLT quitting because MsgWaitForMultipleObjectsEx() failed with last error = %lu", GetLastError());
  883. }
  884. QUITAUClient();
  885. }
  886. }
  887. }
  888. }
  889. #endif
  890. exit:
  891. DEBUGMSG("WUAUCLT Exiting");
  892. //if installation thread is live, wait until it finishes
  893. if (NULL != gpClientCatalog)
  894. {
  895. gpClientCatalog->m_WrkThread.m_Terminate();
  896. }
  897. UninitializeAUClient(g_hRegisterWait, g_hClientNotifyEvt, g_fCoInit, g_fcsInit);
  898. if (CDWWUAUCLT_UNSPECIFY == GetClientExitCode())
  899. {
  900. SetClientExitCode(CDWWUAUCLT_OK);
  901. }
  902. DEBUGMSG("WUAUCLT exit code %d", GetClientExitCode());
  903. ExitProcess(GetClientExitCode());
  904. return 0;
  905. }
  906. LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  907. {
  908. AUSTATE AuState;
  909. switch(message)
  910. {
  911. case WM_CREATE:
  912. {
  913. LOGFONT lFont;
  914. // initialize global ui variables
  915. ghMainWindow = hWnd;
  916. ghCurrentMainDlg = NULL;
  917. gNextDialogMsg = NULL;
  918. ghHeaderFont = NULL;
  919. InitTrayIcon();
  920. HFONT hDefUIFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  921. //create header font
  922. ZeroMemory(&lFont, sizeof(lFont));
  923. lFont.lfWeight = FW_BOLD;
  924. lFont.lfCharSet = DEFAULT_CHARSET;
  925. lFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  926. lFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  927. lFont.lfQuality = DEFAULT_QUALITY;
  928. lFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  929. LoadString(ghInstance, IDS_HEADERFONT, lFont.lfFaceName, ARRAYSIZE(lFont.lfFaceName));
  930. ghHeaderFont = CreateFontIndirect(&lFont);
  931. if(ghHeaderFont == NULL) {
  932. DEBUGMSG("WUAUCLT fail to create Header Font, use default GUI font instead");
  933. ghHeaderFont = hDefUIFont;
  934. }
  935. //create underline font
  936. ZeroMemory(&lFont, sizeof(lFont));
  937. GetObject(hDefUIFont, sizeof(lFont), &lFont);
  938. lFont.lfUnderline = TRUE;
  939. ghHook = SetWindowsHookEx(WH_MSGFILTER, AUTranslatorProc, ghInstance, GetCurrentThreadId());
  940. #ifdef TESTUI
  941. PostMessage(ghMainWindow, AUMSG_SHOW_WELCOME, 0, 0);
  942. #else
  943. #endif
  944. return 0;
  945. }
  946. case AUMSG_SHOW_WELCOME:
  947. DEBUGMSG("WUAUCLT Displaying Welcome");
  948. DialogBox(ghInstance, MAKEINTRESOURCE(IDD_UPDATEFRAME),
  949. NULL, (DLGPROC)WizardFrameProc);
  950. return 0;
  951. case AUMSG_SHOW_DOWNLOAD:
  952. #ifdef TESTUI
  953. {
  954. DEBUGMSG("WUAUCLT Displaying Predownload");
  955. DialogBox(ghInstance, MAKEINTRESOURCE(IDD_DOWNLOAD),
  956. NULL, (DLGPROC)DownloadDlgProc);
  957. return 0;
  958. }
  959. #else
  960. {
  961. DEBUGMSG("WUAUCLT Displaying Predownload");
  962. DialogBox(ghInstance, MAKEINTRESOURCE(IDD_DOWNLOAD),
  963. NULL, (DLGPROC)DownloadDlgProc);
  964. return 0;
  965. }
  966. #endif
  967. case AUMSG_SHOW_INSTALL:
  968. DEBUGMSG("WUAUCLT Displaying Install");
  969. DismissUIIfAny();
  970. DialogBox(ghInstance, MAKEINTRESOURCE(IDD_INSTALLFRAME),
  971. NULL, (DLGPROC)InstallDlgProc);
  972. return 0;
  973. case AUMSG_SHOW_INSTALLWARNING:
  974. DEBUGMSG("WUAUCLT Displaying install warning dialog");
  975. ShowInstallWarning();
  976. return 0;
  977. case WM_CLOSE:
  978. DestroyWindow(ghMainWindow);
  979. return 0;
  980. case WM_ENDSESSION:
  981. DEBUGMSG("WUAUCLT received WM_ENDSESSION (wParam = %#x)", wParam);
  982. if (wParam)
  983. {
  984. //if installation thread is live, wait until it finishes
  985. if (NULL != gpClientCatalog)
  986. {
  987. gpClientCatalog->m_WrkThread.m_Terminate();
  988. }
  989. DismissUIIfAny();
  990. UninitPopupMenus();
  991. if (NULL != ghHeaderFont)
  992. {
  993. DeleteObject(ghHeaderFont);
  994. }
  995. UninitializeAUClient(g_hRegisterWait, g_hClientNotifyEvt, g_fCoInit, g_fcsInit);
  996. // Even we try to set the client exit code here, but there are cases
  997. // based on observation (e.g. logging off during reboot warning) that
  998. // we don't get back to WinMain for clean up after so the exit code gets
  999. // ignored.
  1000. if (CDWWUAUCLT_UNSPECIFY == GetClientExitCode())
  1001. {
  1002. SetClientExitCode(CDWWUAUCLT_ENDSESSION);
  1003. }
  1004. DEBUGMSG("WUAUCLT exit code %d", GetClientExitCode());
  1005. }
  1006. return 0;
  1007. case WM_DESTROY:
  1008. if (NULL != ghHeaderFont)
  1009. {
  1010. DeleteObject(ghHeaderFont);
  1011. }
  1012. if(ghCurrentMainDlg != NULL)
  1013. {
  1014. DestroyWindow(ghCurrentMainDlg);
  1015. }
  1016. UninitPopupMenus();
  1017. PostQuitMessage(0);
  1018. return 0;
  1019. case WM_TIMER:
  1020. #ifdef TESTUI
  1021. return 0;
  1022. #else
  1023. {
  1024. UINT nPercentComplete = 0;
  1025. DWORD dwStatus;
  1026. if (FAILED(gInternals->m_getServiceState(&AuState)))
  1027. {
  1028. DEBUGMSG("WUAUCLT m_getServiceState failed when WM_TIMER or AuState.fDisconnected, quitting");
  1029. QUITAUClient();
  1030. }
  1031. else
  1032. {
  1033. if (AUSTATE_DETECT_COMPLETE != AuState.dwState
  1034. && AUSTATE_DOWNLOAD_PENDING != AuState.dwState
  1035. && AUSTATE_DOWNLOAD_COMPLETE != AuState.dwState
  1036. && AUSTATE_NOT_CONFIGURED != AuState.dwState)
  1037. {
  1038. return 0;
  1039. }
  1040. if (AUSTATE_DOWNLOAD_PENDING != AuState.dwState ||
  1041. SUCCEEDED(gInternals->m_getDownloadStatus(&nPercentComplete, &dwStatus)) && (DWNLDSTATUS_PAUSED == dwStatus))
  1042. {
  1043. UINT cSess;
  1044. if ((SUCCEEDED(gInternals->m_AvailableSessions(&cSess)) && cSess > 1) || FCurrentSessionInActive())
  1045. {
  1046. DEBUGMSG("WUAUCLT : After 4 hours, exit client and relaunch it in next available admin session");
  1047. SetClientExitCode(CDWWUAUCLT_RELAUNCHNOW);
  1048. QUITAUClient();
  1049. }
  1050. }
  1051. }
  1052. return 0;
  1053. }
  1054. #endif
  1055. case AUMSG_TRAYCALLBACK:
  1056. #ifdef TESTUI
  1057. return 0;
  1058. #else
  1059. switch(lParam)
  1060. {
  1061. case WM_LBUTTONDOWN:
  1062. case WM_RBUTTONDOWN:
  1063. case WM_LBUTTONDBLCLK:
  1064. case WM_CONTEXTMENU:
  1065. case NIN_BALLOONUSERCLICK:
  1066. DEBUGMSG("TrayIcon Message got %d", lParam);
  1067. if (ghCurrentMenu != NULL)
  1068. {
  1069. // bug 499697
  1070. // Don't show Pause/Resume menu for download if domain policy specifies schedule install
  1071. if (//SUCCEEDED(gInternals->m_getServiceState(&AuState)) &&
  1072. //AUSTATE_DOWNLOAD_PENDING == AuState.dwState &&
  1073. fDisableSelection())
  1074. {
  1075. break;
  1076. }
  1077. POINT mousePos;
  1078. GetCursorPos(&mousePos);
  1079. SetForegroundWindow(ghMainWindow);
  1080. /*BOOL result =*/ TrackPopupMenu(ghCurrentMenu, 0, mousePos.x, mousePos.y, 0, ghMainWindow, NULL);
  1081. PostMessage(ghMainWindow, WM_NULL, 0, 0);
  1082. }
  1083. else
  1084. {
  1085. EnterCriticalSection(&gcsClient);
  1086. if(gNextDialogMsg != 0)
  1087. {
  1088. PostMessage(hWnd, gNextDialogMsg, 0, 0);
  1089. gNextDialogMsg = 0;
  1090. // we need to make use of the permission to set foregroundwindow ASAP because
  1091. // SetForegroundWindow() will fail if called later
  1092. if (!SetForegroundWindow(ghMainWindow))
  1093. {
  1094. DEBUGMSG("WUAUCLT: Set main window to foreground FAILED");
  1095. }
  1096. }
  1097. else
  1098. {
  1099. SetActiveWindow(ghCurrentMainDlg);
  1100. SetForegroundWindow(ghCurrentMainDlg);
  1101. if(ghCurrentDialog != NULL) SetFocus(ghCurrentDialog);
  1102. }
  1103. LeaveCriticalSection(&gcsClient);
  1104. }
  1105. break;
  1106. case WM_MOUSEMOVE:
  1107. if (FAILED(gInternals->m_getServiceState(&AuState)))
  1108. {
  1109. //fixcode: shall we quit AU here?
  1110. RemoveTrayIcon();
  1111. break;
  1112. }
  1113. if (AUSTATE_DOWNLOAD_PENDING == AuState.dwState)
  1114. {
  1115. ShowProgress();
  1116. }
  1117. break;
  1118. default:
  1119. break;
  1120. }
  1121. return 0;
  1122. #endif
  1123. case WM_COMMAND:
  1124. #ifdef TESTUI
  1125. return 0;
  1126. #else
  1127. // bug 499697
  1128. // Don't process Pause/Resume menu commands
  1129. // if domain policy specifies scheduled install
  1130. // in case the message was generated before
  1131. // current domain policy kicked in.
  1132. if (fDisableSelection())
  1133. {
  1134. return 0;
  1135. }
  1136. switch(LOWORD(wParam))
  1137. {
  1138. case IDC_PAUSE:
  1139. DEBUGMSG("WUAUCLT User pausing download");
  1140. if (FAILED(gInternals->m_setDownloadPaused(TRUE)))
  1141. {
  1142. // QUITAUClient(); //let wuaueng to figure out problem and recover
  1143. }
  1144. else
  1145. {
  1146. ghCurrentMenu = ghResumeMenu;
  1147. DEBUGMSG("current menu = resume");
  1148. }
  1149. break;
  1150. case IDC_RESUME:
  1151. DEBUGMSG("WUAUCLT User resuming download");
  1152. if (FAILED(gInternals->m_setDownloadPaused(FALSE)))
  1153. {
  1154. // QUITAUClient();
  1155. }
  1156. else
  1157. {
  1158. ghCurrentMenu = ghPauseMenu;
  1159. DEBUGMSG("current menu = pause");
  1160. }
  1161. break;
  1162. default:
  1163. break;
  1164. }
  1165. return 0;
  1166. #endif
  1167. default:
  1168. return DefWindowProc(hWnd, message, wParam, lParam);
  1169. }
  1170. return 0;
  1171. }
  1172. //client exit code should only be set once with a meaningful value
  1173. void SetClientExitCode(UINT uExitCode)
  1174. {
  1175. if (guExitProcess != CDWWUAUCLT_UNSPECIFY)
  1176. {
  1177. DEBUGMSG("ERROR: WUAUCLT Client exit code should only be set once");
  1178. }
  1179. else
  1180. {
  1181. guExitProcess = uExitCode;
  1182. }
  1183. }