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.

1498 lines
44 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #define SETNEXTPAGE(x) *((LONG*)lParam) = x
  4. extern HWND BackgroundWnd;
  5. extern HWND BackgroundWnd2;
  6. static HANDLE g_Thread = NULL;
  7. static HANDLE g_Event = NULL;
  8. //
  9. // Prototypes
  10. //
  11. INT_PTR DynSetup_ManualDialog( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam );
  12. HANDLE
  13. pInitializeOnlineSeconds (
  14. VOID
  15. );
  16. DWORD
  17. pGetOnlineRemainingSeconds (
  18. IN HANDLE Handle,
  19. IN DWORD DownloadedBytes,
  20. IN DWORD TotalBytesToDownload,
  21. OUT PDWORD KbPerSec OPTIONAL
  22. );
  23. VOID
  24. pCheckRadioButtons (
  25. IN HWND Hdlg,
  26. IN UINT ButtonToSelect,
  27. ...
  28. )
  29. {
  30. va_list args;
  31. UINT u;
  32. va_start (args, ButtonToSelect);
  33. while (u = va_arg (args, UINT)) {
  34. CheckDlgButton (Hdlg, u, u == ButtonToSelect ? BST_CHECKED : BST_UNCHECKED);
  35. }
  36. va_end (args);
  37. }
  38. BOOL
  39. DynSetupWizPage(
  40. IN HWND hdlg,
  41. IN UINT msg,
  42. IN WPARAM wParam,
  43. IN LPARAM lParam
  44. )
  45. /*++
  46. Routine Description:
  47. Dynamic Setup page 1 (choose to use dynamic updates) or just skip it
  48. if this happens after a restart
  49. Arguments:
  50. Standard window proc arguments.
  51. Returns:
  52. Message-dependent value.
  53. --*/
  54. {
  55. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  56. BOOL fRetVal = FALSE;
  57. switch(msg) {
  58. case WM_INITDIALOG:
  59. pCheckRadioButtons (hdlg, g_DynUpdtStatus->DUStatus == DUS_INITIAL ? IDOK : IDCANCEL, IDOK, IDCANCEL);
  60. SetFocus(GetDlgItem(hdlg,IDOK));
  61. break;
  62. case WM_COMMAND:
  63. if(HIWORD(wParam) == BN_CLICKED) {
  64. if (LOWORD(wParam) == IDOK) {
  65. g_DynUpdtStatus->DUStatus = DUS_INITIAL;
  66. } else if (LOWORD(wParam) == IDCANCEL) {
  67. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  68. }
  69. }
  70. fRetVal = TRUE;
  71. break;
  72. case WMX_ACTIVATEPAGE:
  73. fRetVal = TRUE;
  74. if (wParam) {
  75. //
  76. // don't activate the page in restart mode
  77. //
  78. if (Winnt32Restarted ()) {
  79. if (Winnt32RestartedWithAF ()) {
  80. GetPrivateProfileString(
  81. WINNT_UNATTENDED,
  82. WINNT_U_DYNAMICUPDATESHARE,
  83. TEXT(""),
  84. g_DynUpdtStatus->DynamicUpdatesSource,
  85. ARRAYSIZE(g_DynUpdtStatus->DynamicUpdatesSource),
  86. g_DynUpdtStatus->RestartAnswerFile
  87. );
  88. }
  89. return FALSE;
  90. }
  91. //
  92. // skip this step if already successfully performed
  93. //
  94. if (g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL) {
  95. return FALSE;
  96. }
  97. if (!g_DynUpdtStatus->Disabled && g_DynUpdtStatus->UserSpecifiedUpdates) {
  98. //
  99. // go to the next page to start processing files
  100. //
  101. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  102. } else {
  103. if (g_DynUpdtStatus->Disabled ||
  104. //
  105. // skip if support is not available
  106. //
  107. !DynamicUpdateIsSupported (hdlg)
  108. ) {
  109. //
  110. // skip page(s)
  111. //
  112. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  113. pCheckRadioButtons (hdlg, IDCANCEL, IDOK, IDCANCEL);
  114. // Don't do press button next, This would cause the page to paint.
  115. return( FALSE );
  116. }
  117. //
  118. // in CheckUpgradeOnly mode, ask user if they want to connect to WU
  119. //
  120. if (UpgradeAdvisorMode || !CheckUpgradeOnly || UnattendSwitchSpecified) {
  121. if ((UpgradeAdvisorMode || UnattendedOperation) && !CancelPending) {
  122. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  123. break;
  124. }
  125. }
  126. if (CheckUpgradeOnly) {
  127. //
  128. // disable the Back button in this case
  129. //
  130. PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons & ~PSWIZB_BACK);
  131. }
  132. }
  133. }
  134. Animate_Open(GetDlgItem(hdlg, IDC_ANIMATE), wParam ? MAKEINTRESOURCE(IDA_COMPGLOB) : NULL);
  135. break;
  136. default:
  137. break;
  138. }
  139. return fRetVal;
  140. }
  141. VOID
  142. pUpdateInfoText (
  143. IN UINT InfoId
  144. )
  145. {
  146. #define MAX_TEXT 256
  147. TCHAR text[MAX_TEXT];
  148. if (!LoadString (hInst, InfoId, text, ARRAYSIZE(text))) {
  149. text[0] = 0;
  150. }
  151. BB_SetInfoText (text);
  152. }
  153. VOID
  154. pUpdateProgressText (
  155. IN HWND Hdlg,
  156. IN UINT ProgressId,
  157. IN PCTSTR AppendText, OPTIONAL
  158. IN BOOL InsertNewLine
  159. )
  160. {
  161. #define MAX_TEXT 256
  162. TCHAR text[MAX_TEXT] = TEXT("");
  163. if (Hdlg) {
  164. if (!GetDlgItemText (Hdlg, ProgressId, text, ARRAYSIZE(text))) {
  165. text[0] = 0;
  166. }
  167. } else {
  168. if (!LoadString (hInst, ProgressId, text, ARRAYSIZE(text))) {
  169. text[0] = 0;
  170. }
  171. }
  172. if (AppendText) {
  173. DWORD len = lstrlen (AppendText) + 1;
  174. if (len < ARRAYSIZE(text)) {
  175. if (InsertNewLine) {
  176. if (len + LENGTHOF("\r\n") < ARRAYSIZE(text)) {
  177. len += LENGTHOF("\r\n");
  178. _tcsncat (text, TEXT("\r\n"), ARRAYSIZE(text) - len);
  179. }
  180. }
  181. _tcsncat (text, AppendText, ARRAYSIZE(text) - len);
  182. }
  183. }
  184. BB_SetProgressText (text);
  185. UpdateWindow (GetBBMainHwnd ());
  186. }
  187. VOID
  188. SetDlgItemTextBold (
  189. IN HWND Hdlg,
  190. IN INT DlgItemID,
  191. IN BOOL Bold
  192. )
  193. {
  194. HFONT font;
  195. LOGFONT logFont;
  196. LONG weight;
  197. DWORD id = 0;
  198. font = (HFONT) SendDlgItemMessage (Hdlg, DlgItemID, WM_GETFONT, 0, 0);
  199. if (font && GetObject (font, sizeof(LOGFONT), &logFont)) {
  200. weight = Bold ? FW_BOLD : FW_NORMAL;
  201. if (weight != logFont.lfWeight) {
  202. logFont.lfWeight = weight;
  203. font = CreateFontIndirect (&logFont);
  204. if (font) {
  205. SendDlgItemMessage (Hdlg, DlgItemID, WM_SETFONT, (WPARAM)font, MAKELPARAM(TRUE,0));
  206. }
  207. }
  208. }
  209. }
  210. BOOL
  211. DynSetup2WizPage(
  212. IN HWND hdlg,
  213. IN UINT msg,
  214. IN WPARAM wParam,
  215. IN LPARAM lParam
  216. )
  217. /*++
  218. Routine Description:
  219. Dynamic Setup page 2
  220. Arguments:
  221. Standard window proc arguments.
  222. Returns:
  223. Message-dependent value.
  224. --*/
  225. {
  226. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  227. BOOL fRetVal = FALSE;
  228. PTSTR message;
  229. DWORD onlineRemainingSeconds;
  230. DWORD onlineRemainingMinutes;
  231. DWORD kbps;
  232. TCHAR buf[200];
  233. DWORD estTime, estSize;
  234. HCURSOR hc;
  235. BOOL b;
  236. HANDLE hBitmap, hOld;
  237. DWORD tid;
  238. #ifdef DOWNLOAD_DETAILS
  239. TCHAR buf2[200];
  240. #endif
  241. static BOOL DownloadPageActive = FALSE;
  242. static PTSTR msgToFormat = NULL;
  243. static HANDLE hComp = NULL;
  244. static BOOL CancelDownloadPending = FALSE;
  245. static BOOL ResumeWorkerThread = FALSE;
  246. static DWORD PrevOnlineRemainingMinutes;
  247. static UINT_PTR timer = 0;
  248. #define DOWNLOAD_TIMEOUT_TIMER 5
  249. #define DOWNLOAD_NOTIFY_TIMEOUT 60000
  250. switch(msg) {
  251. case WM_INITDIALOG:
  252. if (GetDlgItemText (hdlg, IDT_DYNSETUP_TIME, buf, ARRAYSIZE(buf))) {
  253. msgToFormat = DupString (buf);
  254. }
  255. SetDlgItemText (hdlg, IDT_DYNSETUP_TIME, TEXT(""));
  256. break;
  257. case WMX_ACTIVATEPAGE:
  258. fRetVal = TRUE;
  259. if (wParam) {
  260. if (g_DynUpdtStatus->DUStatus == DUS_SKIP ||
  261. g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL
  262. ) {
  263. if (g_Thread) {
  264. MYASSERT (g_Event);
  265. g_Thread = NULL;
  266. CloseHandle (g_Event);
  267. g_Event = NULL;
  268. }
  269. if (g_DynUpdtStatus->DUStatus == DUS_SKIP) {
  270. if (!g_DynUpdtStatus->Disabled) {
  271. DynUpdtDebugLog (
  272. Winnt32LogInformation,
  273. TEXT("DynamicUpdate is skipped"),
  274. 0
  275. );
  276. }
  277. }
  278. return FALSE;
  279. }
  280. //
  281. // prepare the UI
  282. //
  283. if (Winnt32Restarted () || g_DynUpdtStatus->UserSpecifiedUpdates) {
  284. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  285. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  286. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  287. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_ARROW), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  288. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  289. } else {
  290. pUpdateInfoText (IDS_ESC_TOCANCEL_DOWNLOAD);
  291. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_ARROW), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  292. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  293. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  294. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  295. }
  296. if (!g_Event) {
  297. g_Event = CreateEvent (NULL, FALSE, FALSE, S_DU_SYNC_EVENT_NAME);
  298. if (!g_Event) {
  299. DynUpdtDebugLog (
  300. Winnt32LogError,
  301. TEXT("CreateEvent(%1) failed"),
  302. 0,
  303. S_DU_SYNC_EVENT_NAME
  304. );
  305. g_DynUpdtStatus->DUStatus = DUS_ERROR;
  306. return FALSE;
  307. }
  308. }
  309. if (!g_Thread) {
  310. g_Thread = CreateThread (NULL, 0, DoDynamicUpdate, (LPVOID)hdlg, 0, &tid);
  311. if (!g_Thread) {
  312. DynUpdtDebugLog (
  313. Winnt32LogError,
  314. TEXT("CreateThread(DoDynamicUpdate) failed"),
  315. 0
  316. );
  317. g_DynUpdtStatus->DUStatus = DUS_ERROR;
  318. CloseHandle (g_Event);
  319. g_Event = NULL;
  320. return FALSE;
  321. }
  322. //
  323. // the handle is no longer needed
  324. //
  325. CloseHandle (g_Thread);
  326. } else {
  327. b = FALSE;
  328. if (g_DynUpdtStatus->DUStatus == DUS_PREPARING_CONNECTIONUNAVAILABLE ||
  329. g_DynUpdtStatus->DUStatus == DUS_PREPARING_INVALIDURL) {
  330. g_DynUpdtStatus->DUStatus = DUS_PREPARING;
  331. b = TRUE;
  332. }
  333. if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING_ERROR) {
  334. g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING;
  335. b = TRUE;
  336. }
  337. if (b) {
  338. //
  339. // page was actually reentered after some previous failure
  340. // resume the working thread
  341. //
  342. MYASSERT (g_Event);
  343. SetEvent (g_Event);
  344. }
  345. }
  346. DownloadPageActive = TRUE;
  347. //
  348. // hide the wizard page
  349. //
  350. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  351. } else {
  352. if (timer) {
  353. KillTimer (hdlg, timer);
  354. timer = 0;
  355. }
  356. DownloadPageActive = FALSE;
  357. }
  358. Animate_Open(GetDlgItem(hdlg, IDC_ANIMATE), wParam ? MAKEINTRESOURCE(IDA_COMPGLOB) : NULL);
  359. break;
  360. case WMX_SETUPUPDATE_PROGRESS_NOTIFY:
  361. //
  362. // reset the timer
  363. //
  364. timer = SetTimer (hdlg, DOWNLOAD_TIMEOUT_TIMER, DOWNLOAD_NOTIFY_TIMEOUT, NULL);
  365. //
  366. // update UI
  367. //
  368. if (!hComp) {
  369. hComp = pInitializeOnlineSeconds ();
  370. PrevOnlineRemainingMinutes = -1;
  371. }
  372. onlineRemainingSeconds = pGetOnlineRemainingSeconds (hComp, (DWORD)lParam, (DWORD)wParam, &kbps);
  373. if (onlineRemainingSeconds) {
  374. onlineRemainingMinutes = onlineRemainingSeconds / 60 + 1;
  375. if (msgToFormat && onlineRemainingMinutes < PrevOnlineRemainingMinutes) {
  376. PrevOnlineRemainingMinutes = onlineRemainingMinutes;
  377. if (_sntprintf (buf, ARRAYSIZE(buf), msgToFormat, onlineRemainingMinutes) < 0) {
  378. buf[ARRAYSIZE(buf) - 1] = 0;
  379. }
  380. #ifdef DOWNLOAD_DETAILS
  381. //
  382. // also display kbps and remaining time in seconds
  383. //
  384. _sntprintf (buf2, TEXT(" (%u sec. at %u kbps)"), onlineRemainingSeconds, kbps);
  385. StringCchCat (buf, ARRAYSIZE(buf), buf2);
  386. #endif
  387. SetDlgItemText (hdlg, IDT_DYNSETUP_TIME, buf);
  388. pUpdateProgressText (hdlg, IDT_DYNSETUP_DOWNLOADING, buf, TRUE);
  389. }
  390. }
  391. break;
  392. case WMX_SETUPUPDATE_RESULT:
  393. if (timer) {
  394. KillTimer (hdlg, timer);
  395. timer = 0;
  396. }
  397. if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING) {
  398. Animate_Stop (GetDlgItem (hdlg, IDC_ANIMATE));
  399. if (g_DynUpdtStatus->Cancelled) {
  400. g_DynUpdtStatus->DUStatus = DUS_CANCELLED;
  401. } else {
  402. if (wParam == DU_STATUS_SUCCESS) {
  403. g_DynUpdtStatus->DUStatus = DUS_PROCESSING;
  404. } else if (wParam == DU_STATUS_FAILED) {
  405. g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING_ERROR;
  406. } else {
  407. g_DynUpdtStatus->DUStatus = DUS_ERROR;
  408. MYASSERT (FALSE);
  409. }
  410. }
  411. if (!CancelDownloadPending) {
  412. //
  413. // let the worker thread continue
  414. //
  415. if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
  416. MYASSERT (g_Event);
  417. SetEvent (g_Event);
  418. } else {
  419. //
  420. // go to the error page
  421. //
  422. if (DownloadPageActive) {
  423. PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
  424. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  425. DownloadPageActive = FALSE;
  426. }
  427. }
  428. } else {
  429. ResumeWorkerThread = TRUE;
  430. }
  431. } else {
  432. MYASSERT (FALSE);
  433. g_DynUpdtStatus->DUStatus = DUS_ERROR;
  434. if (g_Event) {
  435. SetEvent (g_Event);
  436. }
  437. }
  438. break;
  439. case WMX_SETUPUPDATE_PREPARING:
  440. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DIALING, TRUE);
  441. pUpdateProgressText (hdlg, IDT_DYNSETUP_DIALING, NULL, FALSE);
  442. Animate_Play (GetDlgItem (hdlg, IDC_ANIMATE), 0, -1, -1);
  443. break;
  444. case WMX_SETUPUPDATE_DOWNLOADING:
  445. //
  446. // wParam holds the estimated download time
  447. // lParam holds the estimated download size
  448. //
  449. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DIALING, FALSE);
  450. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  451. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  452. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DOWNLOADING, TRUE);
  453. pUpdateProgressText (hdlg, IDT_DYNSETUP_DOWNLOADING, NULL, FALSE);
  454. ShowWindow (GetDlgItem (hdlg, IDT_DYNSETUP_TIME), SW_SHOW);
  455. //
  456. // set a timeout interval, just in case the control "forgets" to send messages
  457. //
  458. timer = SetTimer (hdlg, DOWNLOAD_TIMEOUT_TIMER, DOWNLOAD_NOTIFY_TIMEOUT, NULL);
  459. if (!timer) {
  460. DynUpdtDebugLog (
  461. Winnt32LogWarning,
  462. TEXT("SetTimer failed - unable to automatically abort if the control doesn't respond timely"),
  463. 0
  464. );
  465. }
  466. break;
  467. case WMX_SETUPUPDATE_PROCESSING:
  468. g_DynUpdtStatus->DUStatus = DUS_PROCESSING;
  469. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DOWNLOADING, FALSE);
  470. ShowWindow (GetDlgItem (hdlg, IDT_DYNSETUP_TIME), SW_HIDE);
  471. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  472. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  473. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_PROCESSING, TRUE);
  474. pUpdateProgressText (hdlg, IDT_DYNSETUP_PROCESSING, NULL, FALSE);
  475. pUpdateInfoText (IDS_ESC_TOCANCEL);
  476. break;
  477. case WMX_SETUPUPDATE_THREAD_DONE:
  478. pUpdateProgressText (NULL, 0, NULL, FALSE);
  479. g_Thread = NULL;
  480. if (g_Event) {
  481. CloseHandle (g_Event);
  482. g_Event = NULL;
  483. }
  484. if (g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL) {
  485. if (!g_DynUpdtStatus->Disabled && !g_DynUpdtStatus->RestartWinnt32) {
  486. DynUpdtDebugLog (
  487. Winnt32LogInformation,
  488. TEXT("DynamicUpdate was completed successfully"),
  489. 0
  490. );
  491. }
  492. SetDlgItemTextBold (hdlg, IDT_DYNSETUP_PROCESSING, FALSE);
  493. hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  494. hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  495. UpdateWindow (GetDlgItem (hdlg, IDC_COPY_BMP3));
  496. UpdateWindow (hdlg);
  497. } else if (g_DynUpdtStatus->DUStatus == DUS_ERROR) {
  498. if (UnattendedScriptFile) {
  499. //
  500. // in the unattended case, read the answer to decide if to stop or not
  501. //
  502. GetPrivateProfileString (
  503. WINNT_UNATTENDED,
  504. WINNT_U_DYNAMICUPDATESTOPONERROR,
  505. WINNT_A_NO,
  506. buf,
  507. ARRAYSIZE(buf),
  508. UnattendedScriptFile
  509. );
  510. if (!lstrcmpi (buf, WINNT_A_YES)) {
  511. DynUpdtDebugLog (
  512. Winnt32LogSevereError,
  513. TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
  514. 0
  515. );
  516. g_DynUpdtStatus->RestartWinnt32 = FALSE;
  517. Cancelled = TRUE;
  518. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  519. break;
  520. }
  521. }
  522. } else if (g_DynUpdtStatus->DUStatus == DUS_FATALERROR) {
  523. DynUpdtDebugLog (
  524. Winnt32LogSevereError,
  525. TEXT("Setup encountered a fatal error during DynamicUpdate and stopped"),
  526. 0
  527. );
  528. g_DynUpdtStatus->RestartWinnt32 = FALSE;
  529. Cancelled = TRUE;
  530. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  531. break;
  532. }
  533. //
  534. // continue setup (this may actually restart winnt32)
  535. //
  536. if (DownloadPageActive) {
  537. PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
  538. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  539. DownloadPageActive = FALSE;
  540. }
  541. break;
  542. case WMX_SETUPUPDATE_INIT_RETRY:
  543. //
  544. // go to the retry page
  545. //
  546. if (DownloadPageActive) {
  547. PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
  548. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  549. PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons & ~PSWIZB_NEXT);
  550. DownloadPageActive = FALSE;
  551. }
  552. break;
  553. case WMX_QUERYCANCEL:
  554. //
  555. // on this page, CANCEL means "cancel download", not cancel Setup,
  556. // but only while connecting or downloading
  557. //
  558. if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING && g_DynUpdtStatus->DUStatus != DUS_PREPARING) {
  559. break;
  560. }
  561. fRetVal = TRUE;
  562. if (lParam) {
  563. //
  564. // don't cancel setup
  565. //
  566. *(BOOL*)lParam = FALSE;
  567. }
  568. if (!g_DynUpdtStatus->Cancelled) {
  569. //
  570. // ask user if they really want to cancel DU
  571. //
  572. DWORD rc = IDYES;
  573. CancelDownloadPending = TRUE;
  574. Animate_Stop (GetDlgItem (hdlg, IDC_ANIMATE));
  575. if (!CheckUpgradeOnly) {
  576. rc = MessageBoxFromMessage (
  577. hdlg,
  578. g_DynUpdtStatus->IncompatibleDriversCount ?
  579. MSG_SURE_CANCEL_DOWNLOAD_DRIVERS : MSG_SURE_CANCEL_DOWNLOAD,
  580. FALSE,
  581. AppTitleStringId,
  582. MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL | MB_DEFBUTTON2,
  583. g_DynUpdtStatus->IncompatibleDriversCount
  584. );
  585. }
  586. if (rc == IDYES) {
  587. g_DynUpdtStatus->Cancelled = TRUE;
  588. DynamicUpdateCancel ();
  589. } else {
  590. Animate_Play (GetDlgItem (hdlg, IDC_ANIMATE), 0, -1, -1);
  591. }
  592. if (ResumeWorkerThread) {
  593. ResumeWorkerThread = FALSE;
  594. if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
  595. MYASSERT (g_Event);
  596. SetEvent (g_Event);
  597. }
  598. }
  599. CancelDownloadPending = FALSE;
  600. }
  601. break;
  602. case WM_TIMER:
  603. if (timer && (wParam == timer)) {
  604. if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING) {
  605. //
  606. // oops, the control didn't send any message in a long time now...
  607. // abort download and continue
  608. //
  609. DynUpdtDebugLog (
  610. Winnt32LogError,
  611. TEXT("The timeout for control feedback expired (%1!u! seconds); operation will be aborted"),
  612. 0,
  613. DOWNLOAD_NOTIFY_TIMEOUT / 1000
  614. );
  615. KillTimer (hdlg, timer);
  616. timer = 0;
  617. DynamicUpdateCancel ();
  618. SendMessage (hdlg, WMX_SETUPUPDATE_RESULT, DU_STATUS_FAILED, ERROR_TIMEOUT);
  619. }
  620. }
  621. break;
  622. }
  623. return fRetVal;
  624. }
  625. BOOL
  626. RestartWizPage (
  627. IN HWND hdlg,
  628. IN UINT msg,
  629. IN WPARAM wParam,
  630. IN LPARAM lParam
  631. )
  632. /*++
  633. Routine Description:
  634. Dynamic Setup Restart page
  635. Arguments:
  636. Standard window proc arguments.
  637. Returns:
  638. Message-dependent value.
  639. --*/
  640. {
  641. #define REBOOT_TIMEOUT_SECONDS 5
  642. #define ID_REBOOT_TIMER 1
  643. #define TICKS_PER_SECOND 10
  644. static UINT Countdown;
  645. PCTSTR RestartText;
  646. BOOL fRetVal = FALSE;
  647. switch(msg) {
  648. case WM_TIMER:
  649. if (--Countdown) {
  650. SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_STEPIT, 0, 0);
  651. } else {
  652. PropSheet_PressButton (GetParent (hdlg), PSBTN_FINISH);
  653. }
  654. fRetVal = TRUE;
  655. break;
  656. case WMX_ACTIVATEPAGE:
  657. if (wParam) {
  658. pUpdateInfoText (IDS_ESC_TOCANCEL);
  659. if (Winnt32Restarted () ||
  660. g_DynUpdtStatus->DUStatus != DUS_SUCCESSFUL ||
  661. !g_DynUpdtStatus->RestartWinnt32
  662. ) {
  663. return FALSE;
  664. }
  665. //
  666. // Setup needs to restart with option /Restart:<path to restart file>
  667. //
  668. if (!DynamicUpdatePrepareRestart ()) {
  669. DynUpdtDebugLog (
  670. Winnt32LogError,
  671. TEXT("DynamicUpdatePrepareRestart failed"),
  672. 0
  673. );
  674. g_DynUpdtStatus->DUStatus = DUS_ERROR;
  675. return FALSE;
  676. }
  677. pUpdateProgressText (NULL, IDS_RESTART_SETUP, NULL, FALSE);
  678. pUpdateInfoText (0);
  679. EnableWindow (GetDlgItem(GetParent(hdlg), IDCANCEL), FALSE);
  680. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_FINISH);
  681. RestartText = GetStringResource (MSG_RESTART);
  682. if (RestartText) {
  683. PropSheet_SetFinishText (GetParent (hdlg), RestartText);
  684. FreeStringResource (RestartText);
  685. }
  686. Countdown = REBOOT_TIMEOUT_SECONDS * TICKS_PER_SECOND;
  687. SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELONG(0,Countdown));
  688. SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETSTEP, 1, 0);
  689. SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETPOS, 0, 0);
  690. SetTimer (hdlg, ID_REBOOT_TIMER, 1000 / TICKS_PER_SECOND, NULL);
  691. }
  692. //
  693. // Accept activation/deactivation.
  694. //
  695. fRetVal = TRUE;
  696. break;
  697. case WMX_FINISHBUTTON:
  698. //
  699. // Clean up the timer.
  700. //
  701. KillTimer (hdlg, ID_REBOOT_TIMER);
  702. //
  703. // Let upgrade code do its cleanup.
  704. //
  705. if (UpgradeSupport.CleanupRoutine) {
  706. UpgradeSupport.CleanupRoutine ();
  707. }
  708. fRetVal = TRUE;
  709. break;
  710. }
  711. return fRetVal;
  712. }
  713. BOOL
  714. DynSetup3WizPage(
  715. IN HWND hdlg,
  716. IN UINT msg,
  717. IN WPARAM wParam,
  718. IN LPARAM lParam
  719. )
  720. /*++
  721. Routine Description:
  722. Dynamic Setup page 3 (retrying connection establish)
  723. Arguments:
  724. Standard window proc arguments.
  725. Returns:
  726. Message-dependent value.
  727. --*/
  728. {
  729. TCHAR buffer[100];
  730. BOOL cancel;
  731. static INT iSelected = IDR_DYNSETUP_MANUAL;
  732. static BOOL bFirstTime = TRUE;
  733. BOOL fRetVal = FALSE;
  734. switch(msg) {
  735. case WM_INITDIALOG:
  736. //
  737. // Set radio buttons.
  738. //
  739. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_MANUAL, IDR_DYNSETUP_SKIP);
  740. //
  741. // Set focus to radio buttons
  742. //
  743. SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_MANUAL));
  744. break;
  745. case WM_COMMAND:
  746. if(HIWORD(wParam) == BN_CLICKED) {
  747. switch (LOWORD (wParam)) {
  748. case IDR_DYNSETUP_MANUAL:
  749. case IDR_DYNSETUP_SKIP:
  750. iSelected = LOWORD (wParam);
  751. fRetVal = TRUE;
  752. break;
  753. }
  754. }
  755. break;
  756. case WMX_ACTIVATEPAGE:
  757. if (wParam) {
  758. if (g_DynUpdtStatus->DUStatus != DUS_PREPARING_CONNECTIONUNAVAILABLE) {
  759. return FALSE;
  760. }
  761. if (UnattendSwitchSpecified) {
  762. //
  763. // skip DU by default
  764. //
  765. iSelected = IDR_DYNSETUP_SKIP;
  766. //
  767. // now read the answer, if provided
  768. //
  769. if (UnattendedScriptFile) {
  770. GetPrivateProfileString (
  771. WINNT_UNATTENDED,
  772. WINNT_U_DYNAMICUPDATESTOPONERROR,
  773. WINNT_A_NO,
  774. buffer,
  775. ARRAYSIZE(buffer),
  776. UnattendedScriptFile
  777. );
  778. if (!lstrcmpi (buffer, WINNT_A_YES)) {
  779. DynUpdtDebugLog (
  780. Winnt32LogSevereError,
  781. TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
  782. 0
  783. );
  784. g_DynUpdtStatus->RestartWinnt32 = FALSE;
  785. Cancelled = TRUE;
  786. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  787. break;
  788. }
  789. }
  790. UNATTENDED(PSBTN_NEXT);
  791. } else {
  792. iSelected = bFirstTime ? IDR_DYNSETUP_MANUAL : IDR_DYNSETUP_SKIP;
  793. bFirstTime = FALSE;
  794. }
  795. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_MANUAL, IDR_DYNSETUP_SKIP);
  796. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  797. } else {
  798. if (Cancelled) {
  799. g_DynUpdtStatus->Cancelled = TRUE;
  800. }
  801. //
  802. // let the worker thread continue
  803. //
  804. MYASSERT (g_Thread && g_Event);
  805. SetEvent (g_Event);
  806. }
  807. fRetVal = TRUE;
  808. break;
  809. case WMX_BACKBUTTON:
  810. MYASSERT (FALSE);
  811. case WMX_NEXTBUTTON:
  812. switch (iSelected) {
  813. case IDR_DYNSETUP_MANUAL:
  814. // do magical stuff to hide everything
  815. ShowWindow(BackgroundWnd2, SW_MINIMIZE);
  816. if (DialogBox(hInst, MAKEINTRESOURCE(IDD_DYNAMICSETUP_MANUAL), hdlg, DynSetup_ManualDialog)) {
  817. DynUpdtDebugLog (
  818. Winnt32LogInformation,
  819. TEXT("Manual connect page: user connected manually"),
  820. 0
  821. );
  822. g_DynUpdtStatus->DUStatus = DUS_PREPARING;
  823. } else {
  824. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  825. }
  826. SETNEXTPAGE(IDD_DYNAMICSETUP2);
  827. // do magical stuff to unhide everything
  828. ShowWindow(BackgroundWnd2, SW_SHOWMAXIMIZED);
  829. break;
  830. case IDR_DYNSETUP_SKIP:
  831. DynUpdtDebugLog (
  832. Winnt32LogInformation,
  833. TEXT("Manual connect page: operation was skipped"),
  834. 0
  835. );
  836. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  837. break;
  838. }
  839. fRetVal = TRUE;
  840. break;
  841. }
  842. return fRetVal;
  843. }
  844. BOOL
  845. DynSetup4WizPage(
  846. IN HWND hdlg,
  847. IN UINT msg,
  848. IN WPARAM wParam,
  849. IN LPARAM lParam
  850. )
  851. /*++
  852. Routine Description:
  853. Dynamic Setup page 4 (web site inaccessible)
  854. Arguments:
  855. Standard window proc arguments.
  856. Returns:
  857. Message-dependent value.
  858. --*/
  859. {
  860. TCHAR buffer[100];
  861. BOOL cancel;
  862. static INT iSelected = IDR_DYNSETUP_RETRY;
  863. static BOOL bFirstTime = TRUE;
  864. BOOL fRetVal = FALSE;
  865. switch(msg) {
  866. case WM_INITDIALOG:
  867. //
  868. // Set radio buttons.
  869. //
  870. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
  871. //
  872. // Set focus to radio buttons
  873. //
  874. SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_RETRY));
  875. break;
  876. case WM_COMMAND:
  877. if(HIWORD(wParam) == BN_CLICKED) {
  878. switch (LOWORD (wParam)) {
  879. case IDR_DYNSETUP_RETRY:
  880. case IDR_DYNSETUP_SKIP:
  881. iSelected = LOWORD (wParam);
  882. fRetVal = TRUE;
  883. break;
  884. }
  885. }
  886. break;
  887. case WMX_ACTIVATEPAGE:
  888. if (wParam) {
  889. if (g_DynUpdtStatus->DUStatus != DUS_PREPARING_INVALIDURL) {
  890. return FALSE;
  891. }
  892. if (UnattendSwitchSpecified) {
  893. //
  894. // skip DU by default
  895. //
  896. iSelected = IDR_DYNSETUP_SKIP;
  897. //
  898. // now read the answer, if provided
  899. //
  900. if (UnattendedScriptFile) {
  901. GetPrivateProfileString (
  902. WINNT_UNATTENDED,
  903. WINNT_U_DYNAMICUPDATESTOPONERROR,
  904. WINNT_A_NO,
  905. buffer,
  906. ARRAYSIZE(buffer),
  907. UnattendedScriptFile
  908. );
  909. if (!lstrcmpi (buffer, WINNT_A_YES)) {
  910. DynUpdtDebugLog (
  911. Winnt32LogSevereError,
  912. TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
  913. 0
  914. );
  915. g_DynUpdtStatus->RestartWinnt32 = FALSE;
  916. Cancelled = TRUE;
  917. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  918. break;
  919. }
  920. }
  921. UNATTENDED(PSBTN_NEXT);
  922. } else {
  923. iSelected = bFirstTime ? IDR_DYNSETUP_RETRY : IDR_DYNSETUP_SKIP;
  924. bFirstTime = FALSE;
  925. }
  926. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
  927. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  928. } else {
  929. if (Cancelled) {
  930. g_DynUpdtStatus->Cancelled = TRUE;
  931. }
  932. //
  933. // let the worker thread continue
  934. //
  935. MYASSERT (g_Thread && g_Event);
  936. SetEvent (g_Event);
  937. }
  938. fRetVal = TRUE;
  939. break;
  940. case WMX_BACKBUTTON:
  941. MYASSERT (FALSE);
  942. case WMX_NEXTBUTTON:
  943. switch (iSelected) {
  944. case IDR_DYNSETUP_RETRY:
  945. DynUpdtDebugLog (
  946. Winnt32LogInformation,
  947. TEXT("Retry connection page: user chose to retry"),
  948. 0
  949. );
  950. g_DynUpdtStatus->DUStatus = DUS_PREPARING;
  951. SETNEXTPAGE(IDD_DYNAMICSETUP2);
  952. break;
  953. case IDR_DYNSETUP_SKIP:
  954. DynUpdtDebugLog (
  955. Winnt32LogInformation,
  956. TEXT("Retry connection page: operation was skipped"),
  957. 0
  958. );
  959. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  960. break;
  961. }
  962. fRetVal = TRUE;
  963. break;
  964. }
  965. return fRetVal;
  966. }
  967. BOOL
  968. DynSetup5WizPage(
  969. IN HWND hdlg,
  970. IN UINT msg,
  971. IN WPARAM wParam,
  972. IN LPARAM lParam
  973. )
  974. /*++
  975. Routine Description:
  976. Dynamic Setup page 5 (error while downloading)
  977. Arguments:
  978. Standard window proc arguments.
  979. Returns:
  980. Message-dependent value.
  981. --*/
  982. {
  983. TCHAR buffer[100];
  984. BOOL cancel;
  985. static INT iSelected = IDR_DYNSETUP_RETRY;
  986. static BOOL bFirstTime = TRUE;
  987. BOOL fRetVal = FALSE;
  988. switch(msg) {
  989. case WM_INITDIALOG:
  990. //
  991. // Set radio buttons.
  992. //
  993. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
  994. //
  995. // Set focus to radio buttons
  996. //
  997. SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_RETRY));
  998. break;
  999. case WM_COMMAND:
  1000. if(HIWORD(wParam) == BN_CLICKED) {
  1001. switch (LOWORD (wParam)) {
  1002. case IDR_DYNSETUP_RETRY:
  1003. case IDR_DYNSETUP_SKIP:
  1004. iSelected = LOWORD (wParam);
  1005. fRetVal = TRUE;
  1006. break;
  1007. }
  1008. }
  1009. break;
  1010. case WMX_ACTIVATEPAGE:
  1011. if (wParam) {
  1012. if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
  1013. SendMessage (hdlg, WMX_DYNAMIC_UPDATE_COMPLETE, 0, 0);
  1014. return FALSE;
  1015. }
  1016. if (UnattendSwitchSpecified) {
  1017. //
  1018. // skip DU by default
  1019. //
  1020. iSelected = IDR_DYNSETUP_SKIP;
  1021. //
  1022. // now read the answer, if provided
  1023. //
  1024. if (UnattendedScriptFile) {
  1025. //
  1026. // Read answer
  1027. //
  1028. GetPrivateProfileString (
  1029. WINNT_UNATTENDED,
  1030. WINNT_U_DYNAMICUPDATESTOPONERROR,
  1031. WINNT_A_NO,
  1032. buffer,
  1033. ARRAYSIZE(buffer),
  1034. UnattendedScriptFile
  1035. );
  1036. if (!lstrcmpi (buffer, WINNT_A_YES)) {
  1037. DynUpdtDebugLog (
  1038. Winnt32LogSevereError,
  1039. TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
  1040. 0
  1041. );
  1042. g_DynUpdtStatus->RestartWinnt32 = FALSE;
  1043. Cancelled = TRUE;
  1044. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  1045. break;
  1046. }
  1047. }
  1048. UNATTENDED(PSBTN_NEXT);
  1049. } else {
  1050. iSelected = bFirstTime ? IDR_DYNSETUP_RETRY : IDR_DYNSETUP_SKIP;
  1051. bFirstTime = FALSE;
  1052. }
  1053. pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
  1054. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  1055. } else {
  1056. if (Cancelled) {
  1057. g_DynUpdtStatus->Cancelled = TRUE;
  1058. }
  1059. //
  1060. // let the worker thread continue
  1061. //
  1062. MYASSERT (g_Thread && g_Event);
  1063. SetEvent (g_Event);
  1064. }
  1065. SendMessage (hdlg, WMX_DYNAMIC_UPDATE_COMPLETE, 0, 0);
  1066. fRetVal = TRUE;
  1067. break;
  1068. case WMX_DYNAMIC_UPDATE_COMPLETE:
  1069. #if defined(_X86_)
  1070. //
  1071. // Send upgrade report option to module. DU is
  1072. // now out of the picture.
  1073. //
  1074. switch (g_UpgradeReportMode) {
  1075. case IDC_CRITICAL_ISSUES:
  1076. AppendUpgradeOption (TEXT("ShowReport=Auto"));
  1077. break;
  1078. case IDC_ALL_ISSUES:
  1079. AppendUpgradeOption (TEXT("ShowReport=Yes"));
  1080. break;
  1081. case IDC_NO_REPORT:
  1082. AppendUpgradeOption (TEXT("ShowReport=No"));
  1083. break;
  1084. }
  1085. #endif
  1086. break;
  1087. case WMX_BACKBUTTON:
  1088. MYASSERT (FALSE);
  1089. case WMX_NEXTBUTTON:
  1090. switch (iSelected) {
  1091. case IDR_DYNSETUP_RETRY:
  1092. DynUpdtDebugLog (
  1093. Winnt32LogInformation,
  1094. TEXT("Retry download page: user chose to retry"),
  1095. 0
  1096. );
  1097. g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING;
  1098. SETNEXTPAGE(IDD_DYNAMICSETUP2);
  1099. break;
  1100. case IDR_DYNSETUP_SKIP:
  1101. DynUpdtDebugLog (
  1102. Winnt32LogInformation,
  1103. TEXT("Retry download page: operation was skipped"),
  1104. 0
  1105. );
  1106. g_DynUpdtStatus->DUStatus = DUS_SKIP;
  1107. break;
  1108. }
  1109. fRetVal = TRUE;
  1110. break;
  1111. }
  1112. return fRetVal;
  1113. }
  1114. INT_PTR
  1115. DynSetup_ManualDialog(
  1116. IN HWND hdlg,
  1117. IN UINT msg,
  1118. IN WPARAM wParam,
  1119. IN LPARAM lParam
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Dynamic Setup manual dialog
  1124. Arguments:
  1125. Standard window proc arguments.
  1126. Returns:
  1127. Message-dependent value.
  1128. --*/
  1129. {
  1130. BOOL fRetVal = FALSE;
  1131. switch(msg)
  1132. {
  1133. case WM_INITDIALOG:
  1134. fRetVal = TRUE;
  1135. break;
  1136. case WM_COMMAND:
  1137. if(HIWORD(wParam) == BN_CLICKED) {
  1138. if (LOWORD (wParam) == IDOK)
  1139. {
  1140. EndDialog(hdlg, 1);
  1141. fRetVal = TRUE;
  1142. }
  1143. else
  1144. {
  1145. EndDialog(hdlg, 0);
  1146. fRetVal = TRUE;
  1147. }
  1148. }
  1149. }
  1150. return fRetVal;
  1151. }
  1152. //
  1153. // Time estimate stuff
  1154. //
  1155. #define MAX_INDEX 100
  1156. typedef struct {
  1157. DWORD D;
  1158. DWORD T;
  1159. ULONGLONG DT;
  1160. ULONGLONG TT;
  1161. } STDDEV_ELEM, *PSTDDEV_ELEM;
  1162. typedef struct {
  1163. STDDEV_ELEM Array[MAX_INDEX];
  1164. STDDEV_ELEM Sums;
  1165. UINT Index;
  1166. UINT Count;
  1167. DWORD T0;
  1168. } STDDEV_COMPUTATION, *PSTDDEV_COMPUTATION;
  1169. HANDLE
  1170. pInitializeOnlineSeconds (
  1171. VOID
  1172. )
  1173. {
  1174. PSTDDEV_COMPUTATION p = MALLOC (sizeof (STDDEV_COMPUTATION));
  1175. if (p) {
  1176. ZeroMemory (p, sizeof (STDDEV_COMPUTATION));
  1177. #ifdef DOWNLOAD_DETAILS
  1178. //
  1179. // table header
  1180. //
  1181. DynUpdtDebugLog (
  1182. Winnt32LogDetailedInformation,
  1183. TEXT("Count| MiliSec| Bytes| Baud|EstRemSec|\r\n")
  1184. TEXT("-----|---------|---------|---------|---------|"),
  1185. 0
  1186. );
  1187. #endif
  1188. }
  1189. return (HANDLE)p;
  1190. }
  1191. DWORD
  1192. pGetOnlineRemainingSeconds (
  1193. IN HANDLE Handle,
  1194. IN DWORD DownloadedBytes,
  1195. IN DWORD TotalBytesToDownload,
  1196. OUT PDWORD KbPerSec OPTIONAL
  1197. )
  1198. {
  1199. PSTDDEV_COMPUTATION p = (PSTDDEV_COMPUTATION)Handle;
  1200. PSTDDEV_ELEM e;
  1201. DWORD r = 0;
  1202. DWORD remTimeSec;
  1203. ULONGLONG div;
  1204. if (!p) {
  1205. return 0;
  1206. }
  1207. if (p->Index >= ARRAYSIZE(p->Array)) {
  1208. return 0;
  1209. }
  1210. e = &p->Array[p->Index];
  1211. if (p->Count == 0) {
  1212. //
  1213. // add the first pair
  1214. //
  1215. e->D = DownloadedBytes; // bytes
  1216. e->T = 0; // miliseconds
  1217. e->DT = 0;
  1218. e->TT = 0;
  1219. p->Sums.D = DownloadedBytes;
  1220. p->Count++;
  1221. p->Index++;
  1222. //
  1223. // initialize timer
  1224. //
  1225. p->T0 = GetTickCount ();
  1226. //
  1227. // no time estimate at this point (not enough data)
  1228. //
  1229. return 0;
  1230. }
  1231. //
  1232. // compute sum of prev pairs
  1233. //
  1234. p->Sums.D -= e->D;
  1235. p->Sums.T -= e->T;
  1236. p->Sums.DT -= e->DT;
  1237. p->Sums.TT -= e->TT;
  1238. //
  1239. // compute new values
  1240. //
  1241. e->D = DownloadedBytes; // bytes
  1242. e->T = GetTickCount () - p->T0; // miliseconds
  1243. e->DT = (ULONGLONG)e->D * (ULONGLONG)e->T;
  1244. e->TT = (ULONGLONG)e->T * (ULONGLONG)e->T;
  1245. //
  1246. // compute new sums
  1247. //
  1248. p->Sums.D += e->D;
  1249. p->Sums.T += e->T;
  1250. p->Sums.DT += e->DT;
  1251. p->Sums.TT += e->TT;
  1252. //
  1253. // adjust count and index
  1254. //
  1255. if (p->Count < ARRAYSIZE(p->Array)) {
  1256. p->Count++;
  1257. }
  1258. p->Index++;
  1259. if (p->Index == ARRAYSIZE(p->Array)) {
  1260. p->Index = 0;
  1261. }
  1262. //
  1263. // compute new download rate, in bytes/milisec
  1264. //
  1265. div = p->Sums.TT * (ULONGLONG)p->Count - (ULONGLONG)p->Sums.T * (ULONGLONG)p->Sums.T;
  1266. if (div) {
  1267. r = (DWORD)
  1268. ((p->Sums.DT * (ULONGLONG)p->Count - (ULONGLONG)p->Sums.D * (ULONGLONG)p->Sums.T) *
  1269. 1000 / div / 1024);
  1270. }
  1271. //
  1272. // now estimate remaining time based on the difference and this rate
  1273. // assume there's always something more to download (never 0)
  1274. //
  1275. remTimeSec = 1;
  1276. if (r) {
  1277. remTimeSec += (TotalBytesToDownload - DownloadedBytes) / r / 1000;
  1278. }
  1279. #ifdef DOWNLOAD_DETAILS
  1280. //
  1281. // log this for debug purposes
  1282. //
  1283. DynUpdtDebugLog (
  1284. Winnt32LogDetailedInformation,
  1285. TEXT("%1!5u!%2!10u!%3!10u!%4!10u!%5!10u!"),
  1286. 0,
  1287. p->Count,
  1288. e->T,
  1289. e->D,
  1290. r * 8,
  1291. remTimeSec
  1292. );
  1293. #endif
  1294. if (KbPerSec) {
  1295. *KbPerSec = r;
  1296. }
  1297. return remTimeSec;
  1298. }