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.

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