Leaked source code of windows server 2003
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.

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