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.

705 lines
21 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. billbrd.c
  5. Abstract:
  6. Routines for displaying Windows that are static in nature.
  7. Author:
  8. Ted Miller (tedm) 8-Jun-1995
  9. Revision History:
  10. --*/
  11. #include "setupp.h"
  12. #pragma hdrstop
  13. //
  14. // Define structure we pass around to describe a billboard.
  15. //
  16. typedef struct _BILLBOARD_PARAMS {
  17. UINT MessageId;
  18. va_list *arglist;
  19. HWND Owner;
  20. DWORD NotifyThreadId;
  21. } BILLBOARD_PARAMS, *PBILLBOARD_PARAMS;
  22. //
  23. // Custom window messages
  24. //
  25. #define WMX_BILLBOARD_DISPLAYED (WM_USER+243)
  26. #define WMX_BILLBOARD_TERMINATE (WM_USER+244)
  27. #define ID_REBOOT_TIMER 10
  28. //
  29. // Import the entry point used to check whether setup is executing within an
  30. // ASR context.
  31. //
  32. extern BOOL
  33. AsrIsEnabled( VOID );
  34. INT_PTR
  35. BillboardDlgProc(
  36. IN HWND hdlg,
  37. IN UINT msg,
  38. IN WPARAM wParam,
  39. IN LPARAM lParam
  40. )
  41. {
  42. static BOOL Initializing;
  43. HWND Animation = GetDlgItem(hdlg,IDA_SETUPINIT);
  44. static HANDLE hBitmap;
  45. static HCURSOR hCursor;
  46. switch(msg) {
  47. case WM_INITDIALOG:
  48. {
  49. PBILLBOARD_PARAMS BillParams;
  50. PWSTR p;
  51. BOOL b;
  52. BillParams = (PBILLBOARD_PARAMS)lParam;
  53. if(BillParams->MessageId == MSG_INITIALIZING) {
  54. Initializing = TRUE;
  55. b = TRUE;
  56. hCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  57. ShowCursor( TRUE );
  58. Animate_Open(Animation,MAKEINTRESOURCE(IDA_SETUPINIT));
  59. if (ProductType == PRODUCT_WORKSTATION)
  60. {
  61. hBitmap = LoadBitmap (MyModuleHandle, MAKEINTRESOURCE(IDB_INIT_WORKSTATION));
  62. }
  63. else
  64. {
  65. hBitmap = LoadBitmap (MyModuleHandle, MAKEINTRESOURCE(IDB_INIT_SERVER));
  66. }
  67. SendDlgItemMessage(hdlg,IDC_BITMAP,STM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hBitmap);
  68. } else {
  69. Initializing = FALSE;
  70. if(p = RetrieveAndFormatMessageV(SETUPLOG_USE_MESSAGEID,
  71. BillParams->MessageId,BillParams->arglist)) {
  72. b = SetDlgItemText(hdlg,IDT_STATIC_1,p);
  73. MyFree(p);
  74. } else {
  75. b = FALSE;
  76. }
  77. }
  78. if(b) {
  79. //
  80. // Center the billboard relative to the window that owns it.
  81. //
  82. // if we have the BB window, do the positioning on that.
  83. // MainWindowHandle point to that window
  84. //
  85. if (GetBBhwnd())
  86. CenterWindowRelativeToWindow(hdlg, MainWindowHandle, FALSE);
  87. else
  88. pSetupCenterWindowRelativeToParent(hdlg);
  89. //
  90. // Post ourselves a message that we won't get until we've been
  91. // actually displayed on the screen. Then when we process that message,
  92. // we inform the thread that created us that we're up. Note that
  93. // once that notification has been made, the BillParams we're using
  94. // now will go away since they are stored in local vars (see
  95. // DisplayBillboard()).
  96. //
  97. PostMessage(hdlg,WMX_BILLBOARD_DISPLAYED,0,(LPARAM)BillParams->NotifyThreadId);
  98. //
  99. // Tell Windows not to process this message.
  100. //
  101. return(FALSE);
  102. } else {
  103. //
  104. // We won't post the message, but returning -1 will get the
  105. // caller of DialogBox to post it for us.
  106. //
  107. EndDialog(hdlg,-1);
  108. }
  109. }
  110. break;
  111. case WMX_BILLBOARD_DISPLAYED:
  112. if(Initializing) {
  113. Animate_Play(Animation,0,-1,-1);
  114. }
  115. PostThreadMessage(
  116. (DWORD)lParam,
  117. WMX_BILLBOARD_DISPLAYED,
  118. TRUE,
  119. (LPARAM)hdlg
  120. );
  121. break;
  122. case WMX_BILLBOARD_TERMINATE:
  123. if(Initializing) {
  124. SetCursor( hCursor );
  125. ShowCursor( FALSE );
  126. Animate_Stop(Animation);
  127. Animate_Close(Animation);
  128. DeleteObject(hBitmap);
  129. }
  130. EndDialog(hdlg,0);
  131. break;
  132. default:
  133. return(FALSE);
  134. }
  135. return(TRUE);
  136. }
  137. DWORD
  138. BillboardThread(
  139. IN PVOID ThreadParam
  140. )
  141. {
  142. PBILLBOARD_PARAMS BillboardParams;
  143. INT_PTR i;
  144. BillboardParams = ThreadParam;
  145. //
  146. // For the "initializing" case, we use a different dialog.
  147. //
  148. if( AsrIsEnabled() ) {
  149. i = DialogBoxParam(
  150. MyModuleHandle,
  151. (BillboardParams->MessageId == MSG_INITIALIZING) ?
  152. MAKEINTRESOURCE(IDD_SETUPINIT_ASR) :
  153. MAKEINTRESOURCE(IDD_BILLBOARD1),
  154. BillboardParams->Owner,
  155. BillboardDlgProc,
  156. (LPARAM)BillboardParams
  157. );
  158. } else {
  159. i = DialogBoxParam(
  160. MyModuleHandle,
  161. (BillboardParams->MessageId == MSG_INITIALIZING) ?
  162. MAKEINTRESOURCE(IDD_SETUPINIT) :
  163. MAKEINTRESOURCE(IDD_BILLBOARD1),
  164. BillboardParams->Owner,
  165. BillboardDlgProc,
  166. (LPARAM)BillboardParams
  167. );
  168. }
  169. //
  170. // If the dialog box call failed, we have to tell the
  171. // main thread about it here. Otherwise the dialog proc
  172. // tells the main thread.
  173. //
  174. if(i == -1) {
  175. PostThreadMessage(
  176. BillboardParams->NotifyThreadId,
  177. WMX_BILLBOARD_DISPLAYED,
  178. FALSE,
  179. (LPARAM)NULL
  180. );
  181. }
  182. return(0);
  183. }
  184. HWND
  185. DisplayBillboard(
  186. IN HWND Owner,
  187. IN UINT MessageId,
  188. ...
  189. )
  190. {
  191. HANDLE ThreadHandle;
  192. DWORD ThreadId;
  193. BILLBOARD_PARAMS ThreadParams;
  194. va_list arglist;
  195. HWND hwnd;
  196. MSG msg;
  197. hwnd = NULL;
  198. // If we have a billboard, we should not need this. dialog.
  199. if (GetBBhwnd() == NULL)
  200. {
  201. va_start(arglist,MessageId);
  202. //
  203. // The billboard will exist in a separate thread so it will
  204. // always be responsive.
  205. //
  206. ThreadParams.MessageId = MessageId;
  207. ThreadParams.arglist = &arglist;
  208. ThreadParams.Owner = Owner;
  209. ThreadParams.NotifyThreadId = GetCurrentThreadId();
  210. ThreadHandle = CreateThread(
  211. NULL,
  212. 0,
  213. BillboardThread,
  214. &ThreadParams,
  215. 0,
  216. &ThreadId
  217. );
  218. if(ThreadHandle) {
  219. //
  220. // Wait for the billboard to tell us its window handle
  221. // or that it failed to display the billboard dialog.
  222. //
  223. do {
  224. GetMessage(&msg,NULL,0,0);
  225. if(msg.message == WMX_BILLBOARD_DISPLAYED) {
  226. if(msg.wParam) {
  227. hwnd = (HWND)msg.lParam;
  228. Sleep(1500); // let the user see it even on fast machines
  229. }
  230. } else {
  231. DispatchMessage(&msg);
  232. }
  233. } while(msg.message != WMX_BILLBOARD_DISPLAYED);
  234. CloseHandle(ThreadHandle);
  235. }
  236. va_end(arglist);
  237. }
  238. else
  239. {
  240. // Start BB text
  241. StartStopBB(TRUE);
  242. }
  243. return(hwnd);
  244. }
  245. VOID
  246. KillBillboard(
  247. IN HWND BillboardWindowHandle
  248. )
  249. {
  250. if(BillboardWindowHandle && IsWindow(BillboardWindowHandle)) {
  251. PostMessage(BillboardWindowHandle,WMX_BILLBOARD_TERMINATE,0,0);
  252. }
  253. }
  254. INT_PTR
  255. DoneDlgProc(
  256. IN HWND hdlg,
  257. IN UINT msg,
  258. IN WPARAM wParam,
  259. IN LPARAM lParam
  260. )
  261. {
  262. PWSTR p;
  263. static UINT Countdown;
  264. switch(msg) {
  265. case WM_INITDIALOG:
  266. // if we have the BB window, do the positioning on that. MainWindowHandle point to that window
  267. if (GetBBhwnd())
  268. CenterWindowRelativeToWindow(hdlg, MainWindowHandle, FALSE);
  269. else
  270. pSetupCenterWindowRelativeToParent(hdlg);
  271. SendDlgItemMessage(
  272. hdlg,
  273. IDOK,
  274. BM_SETIMAGE,
  275. 0,
  276. (LPARAM)LoadBitmap(MyModuleHandle,MAKEINTRESOURCE(IDB_REBOOT))
  277. );
  278. if(p = RetrieveAndFormatMessage(NULL,(UINT)lParam)) {
  279. SetDlgItemText(hdlg,IDT_STATIC_1,p);
  280. MyFree(p);
  281. }
  282. Countdown = 15 * 10;
  283. SendDlgItemMessage(hdlg,IDC_PROGRESS1,PBM_SETRANGE,0,MAKELONG(0,Countdown));
  284. SendDlgItemMessage(hdlg,IDC_PROGRESS1,PBM_SETSTEP,1,0);
  285. SendDlgItemMessage(hdlg,IDC_PROGRESS1,PBM_SETPOS,0,0);
  286. SetTimer(hdlg,ID_REBOOT_TIMER,100,NULL);
  287. SetFocus(GetDlgItem(hdlg,IDOK));
  288. return(FALSE);
  289. case WM_TIMER:
  290. Countdown--;
  291. if(Countdown) {
  292. SendDlgItemMessage(hdlg,IDC_PROGRESS1,PBM_STEPIT,0,0);
  293. } else {
  294. KillTimer(hdlg,ID_REBOOT_TIMER);
  295. DeleteObject((HGDIOBJ)SendDlgItemMessage(hdlg,IDOK,BM_GETIMAGE,0,0));
  296. EndDialog(hdlg,0);
  297. }
  298. break;
  299. case WM_COMMAND:
  300. if((HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDOK)) {
  301. KillTimer(hdlg,ID_REBOOT_TIMER);
  302. DeleteObject((HGDIOBJ)SendDlgItemMessage(hdlg,IDOK,BM_GETIMAGE,0,0));
  303. EndDialog(hdlg,0);
  304. } else {
  305. return(FALSE);
  306. }
  307. break;
  308. default:
  309. return(FALSE);
  310. }
  311. return(TRUE);
  312. }
  313. typedef BOOL (CALLBACK *STOPBILLBOARD)();
  314. typedef BOOL (CALLBACK *STARTBILLBOARD)();
  315. typedef BOOL (WINAPI* SETTIMEESTIMATE)(LPCTSTR szText);
  316. typedef BOOL (WINAPI* SETPROGRESSTEXT)(LPCTSTR szText);
  317. typedef BOOL (WINAPI* SETINFOTEXT)(LPCTSTR szText);
  318. typedef LRESULT (WINAPI* PROGRESSGAUGEMSG)(UINT msg, WPARAM wparam, LPARAM lparam);
  319. typedef BOOL (WINAPI* SHOWPROGRESSGAUGEWINDOW)(UINT uiShow);
  320. BOOL BB_ShowProgressGaugeWnd(UINT nCmdShow)
  321. {
  322. static SHOWPROGRESSGAUGEWINDOW fpShowGauge = NULL;
  323. BOOL bRet = FALSE;
  324. if (fpShowGauge == NULL)
  325. {
  326. if (hinstBB)
  327. {
  328. fpShowGauge = (SHOWPROGRESSGAUGEWINDOW )GetProcAddress(hinstBB, "ShowProgressGaugeWindow");
  329. }
  330. }
  331. if (fpShowGauge != NULL)
  332. {
  333. bRet = fpShowGauge(nCmdShow);
  334. }
  335. return bRet;
  336. }
  337. LRESULT BB_ProgressGaugeMsg(UINT msg, WPARAM wparam, LPARAM lparam)
  338. {
  339. static PROGRESSGAUGEMSG fpProgressGaugeMsg = NULL;
  340. LRESULT lresult = 0;
  341. if (fpProgressGaugeMsg == NULL)
  342. {
  343. if (hinstBB)
  344. {
  345. fpProgressGaugeMsg = (PROGRESSGAUGEMSG )GetProcAddress(hinstBB, "ProgressGaugeMsg");
  346. }
  347. }
  348. if (fpProgressGaugeMsg != NULL)
  349. {
  350. lresult = fpProgressGaugeMsg(msg, wparam, lparam);
  351. }
  352. return lresult;
  353. }
  354. void BB_SetProgressText(LPCTSTR szText)
  355. {
  356. static SETPROGRESSTEXT fpSetProgressText = NULL;
  357. if (fpSetProgressText == NULL)
  358. {
  359. if (hinstBB)
  360. {
  361. fpSetProgressText = (SETPROGRESSTEXT )GetProcAddress(hinstBB, "SetProgressText");
  362. }
  363. }
  364. if (fpSetProgressText != NULL)
  365. {
  366. fpSetProgressText(szText);
  367. }
  368. }
  369. void BB_SetInfoText(LPTSTR szText)
  370. {
  371. static SETINFOTEXT fpSetInfoText = NULL;
  372. if (fpSetInfoText == NULL)
  373. {
  374. if (hinstBB)
  375. {
  376. fpSetInfoText = (SETINFOTEXT )GetProcAddress(hinstBB, "SetInfoText");
  377. }
  378. }
  379. if (fpSetInfoText != NULL)
  380. {
  381. fpSetInfoText(szText);
  382. }
  383. }
  384. void BB_SetTimeEstimateText(LPTSTR szText)
  385. {
  386. static SETTIMEESTIMATE fpSetTimeEstimate = NULL;
  387. if (fpSetTimeEstimate == NULL)
  388. {
  389. if (hinstBB)
  390. {
  391. fpSetTimeEstimate = (SETTIMEESTIMATE)GetProcAddress(hinstBB, "SetTimeEstimate");
  392. }
  393. }
  394. if (fpSetTimeEstimate != NULL)
  395. {
  396. fpSetTimeEstimate(szText);
  397. }
  398. }
  399. BOOL StartStopBB(BOOL bStart)
  400. {
  401. static STARTBILLBOARD fpStart = NULL;
  402. static STOPBILLBOARD fpStop = NULL;
  403. BOOL bRet = FALSE;
  404. if ((fpStart == NULL) || (fpStop == NULL))
  405. {
  406. if (hinstBB)
  407. {
  408. fpStop = (STARTBILLBOARD )GetProcAddress(hinstBB, "StopBillBoard");
  409. fpStart = (STOPBILLBOARD )GetProcAddress(hinstBB, "StartBillBoard");
  410. }
  411. }
  412. if ((fpStart != NULL) && (fpStop != NULL))
  413. {
  414. if (bStart)
  415. bRet = fpStart();
  416. else
  417. bRet = fpStop();
  418. }
  419. return bRet;
  420. }
  421. LRESULT ProgressGaugeMsgWrapper(UINT msg, WPARAM wparam, LPARAM lparam)
  422. {
  423. static DWORD MsecPerProcessTick;
  424. static DWORD PreviousRemainingTime = 0;
  425. static DWORD RemainungTimeMsecInThisPhase = 0;
  426. static int iCurrentPos = 0;
  427. static int iMaxPosition = 0;
  428. static int iStepSize = 0;
  429. static UINT PreviousPhase = Phase_Unknown;
  430. static BOOL IgnoreSetRange = FALSE;
  431. static BOOL IgnoreSetPos = FALSE;
  432. DWORD dwDeltaTicks = 0;
  433. switch (msg)
  434. {
  435. case WMX_PROGRESSTICKS:
  436. // If we get a WMX_PROGRESSTICKS before a PBM_SETRANGE, ignore the set range
  437. // This should be use if the progress bar only takes up x% of the whole bar.
  438. // In this case the phase sends PBM_SETRANGE and a PBM_SETPOS to setup the
  439. // progress values for it's part of the gauge.
  440. IgnoreSetRange = TRUE;
  441. if (PreviousPhase != CurrentPhase)
  442. {
  443. PreviousPhase = CurrentPhase;
  444. iCurrentPos = 0;
  445. iMaxPosition = (int)wparam;
  446. iStepSize = 10;
  447. MsecPerProcessTick = ((SetupPhase[CurrentPhase].Time*1000)/(iMaxPosition - iCurrentPos) )+ 1;
  448. RemainungTimeMsecInThisPhase = (SetupPhase[CurrentPhase].Time * 1000);
  449. PreviousRemainingTime = RemainungTimeMsecInThisPhase;
  450. }
  451. else
  452. {
  453. // what to do if the same phase send more then one set range.
  454. // don't change the remaining time, only recal the msecperprogresstick
  455. //
  456. iCurrentPos = 0;
  457. iMaxPosition = (int)wparam;
  458. iStepSize = 10;
  459. MsecPerProcessTick = (RemainungTimeMsecInThisPhase /(iMaxPosition - iCurrentPos) )+ 1;
  460. }
  461. break;
  462. case PBM_SETPOS:
  463. {
  464. UINT uiCurrentPos;
  465. if (!IgnoreSetPos)
  466. {
  467. int iDeltaPos = 0;
  468. // Find out where the current position of the gasgauge is.
  469. // The difference is the #ticks we use to reduce the time estimate
  470. uiCurrentPos = (UINT)BB_ProgressGaugeMsg(PBM_GETPOS, 0, 0);
  471. // See if there is a difference in the current position and the one
  472. // we think we are in.
  473. // Only if the new position is greater then the current one
  474. // calc the difference and substract from remaining time.
  475. if ((UINT)wparam > uiCurrentPos)
  476. {
  477. iDeltaPos = (UINT)wparam - uiCurrentPos;
  478. iCurrentPos += iDeltaPos;
  479. // Only substract if more time left
  480. if ((iDeltaPos * MsecPerProcessTick) < RemainungTimeMsecInThisPhase)
  481. {
  482. RemainungTimeMsecInThisPhase -= (iDeltaPos * MsecPerProcessTick);
  483. }
  484. else
  485. {
  486. RemainungTimeMsecInThisPhase = 0;
  487. }
  488. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  489. }
  490. }
  491. IgnoreSetPos = FALSE;
  492. }
  493. break;
  494. case PBM_SETRANGE:
  495. case PBM_SETRANGE32:
  496. // did the phase not send the private message above
  497. if (!IgnoreSetRange)
  498. {
  499. // Are we not in the same phase?
  500. if (PreviousPhase != CurrentPhase)
  501. {
  502. PreviousPhase = CurrentPhase;
  503. // Get the new start and max position
  504. if (msg == PBM_SETRANGE32)
  505. {
  506. iCurrentPos = (int)wparam;
  507. iMaxPosition = (int)lparam;
  508. }
  509. else
  510. {
  511. iCurrentPos = LOWORD(lparam);
  512. iMaxPosition = HIWORD(lparam);
  513. }
  514. iStepSize = 10;
  515. // Calc the msec per tick and msec in this phase
  516. MsecPerProcessTick = ((SetupPhase[CurrentPhase].Time*1000)/(iMaxPosition - iCurrentPos) )+ 1;
  517. RemainungTimeMsecInThisPhase = (SetupPhase[CurrentPhase].Time * 1000);
  518. PreviousRemainingTime = RemainungTimeMsecInThisPhase;
  519. }
  520. else
  521. {
  522. // the same phase send more then one set range.
  523. // 1. don't change the remaining time, only recal the msecperprogresstick
  524. // 2. Ignore the next PBM_SETPOS message.
  525. //
  526. // Get the new start and max position
  527. if (msg == PBM_SETRANGE32)
  528. {
  529. iCurrentPos = (int)wparam;
  530. iMaxPosition = (int)lparam;
  531. }
  532. else
  533. {
  534. iCurrentPos = LOWORD(lparam);
  535. iMaxPosition = HIWORD(lparam);
  536. }
  537. iStepSize = 10;
  538. MsecPerProcessTick = (RemainungTimeMsecInThisPhase /(iMaxPosition - iCurrentPos) )+ 1;
  539. IgnoreSetPos = TRUE;
  540. }
  541. }
  542. else
  543. {
  544. // If we ignored the setrange, also ignore the first set pos.
  545. IgnoreSetPos = TRUE;
  546. }
  547. IgnoreSetRange = FALSE;
  548. break;
  549. case PBM_DELTAPOS:
  550. {
  551. int iDeltaPos = 0;
  552. // wparam has the # of ticks to move the gas gauge
  553. // make sure we don't over shoot the max posistion
  554. if ((iCurrentPos + (int)wparam) > iMaxPosition)
  555. {
  556. iDeltaPos = (iMaxPosition - iCurrentPos);
  557. }
  558. else
  559. {
  560. iDeltaPos = (int)wparam;
  561. }
  562. iCurrentPos += iDeltaPos;
  563. if ((iDeltaPos * MsecPerProcessTick) < RemainungTimeMsecInThisPhase)
  564. {
  565. RemainungTimeMsecInThisPhase -= (iDeltaPos * MsecPerProcessTick);
  566. }
  567. else
  568. {
  569. RemainungTimeMsecInThisPhase = 0;
  570. }
  571. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  572. }
  573. break;
  574. case PBM_STEPIT:
  575. {
  576. int iDeltaPos = 0;
  577. // make sure we don't over shoot the max posistion
  578. if ((iCurrentPos + iStepSize) > iMaxPosition)
  579. {
  580. iDeltaPos = (iMaxPosition - iCurrentPos);
  581. }
  582. else
  583. {
  584. iDeltaPos = iStepSize;
  585. }
  586. iCurrentPos += iDeltaPos;
  587. if ((iDeltaPos * MsecPerProcessTick) < RemainungTimeMsecInThisPhase)
  588. {
  589. RemainungTimeMsecInThisPhase -= (iDeltaPos * MsecPerProcessTick);
  590. }
  591. else
  592. {
  593. RemainungTimeMsecInThisPhase = 0;
  594. }
  595. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  596. }
  597. break;
  598. case PBM_SETSTEP:
  599. iStepSize = (int)wparam;
  600. break;
  601. }
  602. return BB_ProgressGaugeMsg(msg, wparam, lparam);
  603. }
  604. void UpdateTimeString(DWORD RemainungTimeMsecInThisPhase,
  605. DWORD *PreviousRemainingTime)
  606. {
  607. // If the previous displayed time is 1 minute old, update the time remaining.
  608. if ((*PreviousRemainingTime >= 60000) && ((*PreviousRemainingTime - 60000) > RemainungTimeMsecInThisPhase))
  609. {
  610. // Substract one minute.
  611. RemainingTime -= 60;
  612. *PreviousRemainingTime = RemainungTimeMsecInThisPhase;
  613. SetRemainingTime(RemainingTime);
  614. }
  615. }