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.

443 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: progress.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // progress.cpp : implementation file
  11. //
  12. #include <pch.cpp>
  13. #pragma hdrstop
  14. #include "clibres.h"
  15. #include "progress.h"
  16. // defines
  17. #ifdef _DEBUG
  18. //#define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. enum MYDIALOGBEHAVIORENUM
  23. {
  24. enumPERCENTCOMPLETEBEHAVIOR = 0,
  25. enumPROGRESSBARWITHTIMEOUT,
  26. };
  27. typedef struct _PROGRESSPROC_LPARAM
  28. {
  29. HINSTANCE hInstance;
  30. HWND hwndParent;
  31. UINT iRscJobDescription;
  32. MYDIALOGBEHAVIORENUM enumWhichBehavior;
  33. DWORD dwTickerUpperRange;
  34. DBBACKUPPROGRESS* pdbp;
  35. } PROGRESSPROC_LPARAM, *PPROGRESSPROC_LPARAM;
  36. static BOOL s_fDisableProgressDialogs = 0;
  37. static BOOL s_fIKnow = 0;
  38. BOOL FICanShowDialogs()
  39. {
  40. if (s_fIKnow != TRUE)
  41. {
  42. s_fIKnow = TRUE;
  43. DWORD dwVal;
  44. if (S_OK == myGetCertRegDWValue(
  45. NULL,
  46. NULL,
  47. NULL,
  48. L"DisableProgress",
  49. &dwVal))
  50. {
  51. s_fDisableProgressDialogs = (dwVal != 0);
  52. }
  53. }
  54. return ! s_fDisableProgressDialogs;
  55. }
  56. ////////////////////////////////////////////////////////////////////////////////
  57. // show a progress dialog
  58. int g_iTimeoutTicks = 0;
  59. BOOL g_fUseTimer;
  60. INT_PTR CALLBACK dlgProcProgress(
  61. HWND hwndDlg,
  62. UINT uMsg,
  63. WPARAM, // wParam
  64. LPARAM lParam)
  65. {
  66. PPROGRESSPROC_LPARAM pLParam = NULL;
  67. switch(uMsg)
  68. {
  69. case WM_INITDIALOG:
  70. {
  71. HWND hwndProgressBar;
  72. pLParam = (PPROGRESSPROC_LPARAM)lParam;
  73. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)pLParam);
  74. hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
  75. {
  76. RECT rcParent, rcDlg, rcScreenArea;
  77. GetWindowRect(pLParam->hwndParent, &rcParent);
  78. GetWindowRect(hwndDlg, &rcDlg);
  79. SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcScreenArea, NULL);
  80. // calc centers
  81. int xLeft = (rcParent.left + rcParent.right) / 2 - (rcDlg.right - rcDlg.left) / 2;
  82. int yTop = (rcParent.top + rcParent.bottom) / 2 - (rcDlg.bottom - rcDlg.top) / 2;
  83. // careful: if the dialog is outside the screen, move it inside
  84. if (xLeft < rcScreenArea.left)
  85. xLeft = rcScreenArea.left;
  86. else if (xLeft + (rcDlg.right - rcDlg.left) > rcScreenArea.right)
  87. xLeft = rcScreenArea.right - (rcDlg.right - rcDlg.left);
  88. if (yTop < rcScreenArea.top)
  89. yTop = rcScreenArea.top;
  90. else if (yTop + (rcDlg.bottom - rcDlg.top) > rcScreenArea.bottom)
  91. yTop = rcScreenArea.bottom - (rcDlg.bottom - rcDlg.top);
  92. // map screen coordinates to child coordinates
  93. SetWindowPos(hwndDlg, HWND_TOPMOST, xLeft, yTop, -1, -1,
  94. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  95. }
  96. {
  97. DWORD dwStyle;
  98. dwStyle = GetWindowLong(hwndProgressBar, GWL_STYLE);
  99. SetWindowLong(hwndProgressBar, GWL_STYLE, (dwStyle | PBS_SMOOTH));
  100. }
  101. // Set the range and increment of the progress bar.
  102. if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
  103. {
  104. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, pLParam->dwTickerUpperRange));
  105. SendMessage(hwndProgressBar, PBM_SETSTEP, (WPARAM) 1, 0);
  106. }
  107. else
  108. {
  109. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
  110. }
  111. SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)0, 0);
  112. // set job description if specified
  113. if (pLParam->iRscJobDescription != 0)
  114. {
  115. WCHAR szJobDesc[MAX_PATH];
  116. if (0 != LoadString(
  117. pLParam->hInstance,
  118. pLParam->iRscJobDescription,
  119. szJobDesc,
  120. MAX_PATH))
  121. SetDlgItemText(hwndDlg, IDC_JOB_DESCRIPTION, szJobDesc);
  122. }
  123. return 1;
  124. }
  125. case WM_DESTROY:
  126. {
  127. pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  128. if (NULL == pLParam)
  129. break;
  130. SetForegroundWindow(pLParam->hwndParent);
  131. LocalFree(pLParam);
  132. pLParam = NULL;
  133. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, NULL);
  134. }
  135. case PBM_STEPIT:
  136. {
  137. pLParam = (PPROGRESSPROC_LPARAM)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  138. if (NULL == pLParam)
  139. break;
  140. HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
  141. if (pLParam->enumWhichBehavior == enumPROGRESSBARWITHTIMEOUT)
  142. SendMessage(hwndProgressBar, PBM_STEPIT, 0, 0);
  143. else
  144. {
  145. DWORD wProgress = pLParam->pdbp->dwDBPercentComplete +
  146. pLParam->pdbp->dwLogPercentComplete +
  147. pLParam->pdbp->dwTruncateLogPercentComplete ;
  148. DWORD wTop = (DWORD)SendMessage(hwndProgressBar,
  149. PBM_GETRANGE,
  150. FALSE,
  151. NULL);
  152. if (wProgress == wTop)
  153. {
  154. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, S_FALSE); // we're done!
  155. return TRUE;
  156. }
  157. else
  158. SendMessage(hwndProgressBar, PBM_SETPOS, wProgress, 0); // keep incrementing
  159. }
  160. break;
  161. }
  162. case PBM_SETPOS:
  163. {
  164. HWND hwndProgressBar = GetDlgItem(hwndDlg, IDD_PROGRESS_BAR);
  165. LRESULT wTop = SendMessage(hwndProgressBar, PBM_GETRANGE, FALSE, NULL);
  166. // if we're not yet at the top make it so
  167. if (wTop != SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0))
  168. {
  169. SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)wTop, 0);
  170. Sleep(400);
  171. }
  172. }
  173. default:
  174. break;
  175. }
  176. return 0;
  177. }
  178. #define PROGRESS_TICKS_PER_SEC 3
  179. DWORD WINAPI StartTimerThread( LPVOID lpParameter )
  180. {
  181. if (FICanShowDialogs())
  182. {
  183. PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
  184. HWND hwndProgressDlg = CreateDialogParam(
  185. psParam->hInstance,
  186. MAKEINTRESOURCE(IDD_PROGRESS_BOX),
  187. NULL,
  188. dlgProcProgress,
  189. (LPARAM)lpParameter);
  190. if (NULL == hwndProgressDlg)
  191. return 0;
  192. ShowWindow(hwndProgressDlg, SW_SHOW);
  193. UpdateWindow(hwndProgressDlg);
  194. // if not timer based, go forever
  195. // if timer based, go while timersec is +
  196. while ((!g_fUseTimer) ||
  197. (g_iTimeoutTicks-- > 0))
  198. {
  199. SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0);
  200. UpdateWindow(hwndProgressDlg);
  201. Sleep(1000/PROGRESS_TICKS_PER_SEC);
  202. }
  203. // send "fill the indicator"
  204. SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
  205. DestroyWindow(hwndProgressDlg);
  206. }
  207. return 0;
  208. }
  209. // callable APIs: Start/End ProgressDlg
  210. BOOL FProgressDlgRunning()
  211. {
  212. return (!g_fUseTimer || (g_iTimeoutTicks > 0));
  213. }
  214. HANDLE
  215. StartProgressDlg(
  216. HINSTANCE hInstance,
  217. HWND hwndParent,
  218. DWORD dwTickerSeconds,
  219. DWORD dwTimeoutSeconds,
  220. UINT iRscJobDescription)
  221. {
  222. HANDLE hProgressThread = NULL;
  223. DWORD dwThread;
  224. PPROGRESSPROC_LPARAM psParam = NULL;
  225. INITCOMMONCONTROLSEX sCommCtrl;
  226. sCommCtrl.dwSize = sizeof(sCommCtrl);
  227. sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
  228. if (!InitCommonControlsEx(&sCommCtrl))
  229. goto Ret;
  230. g_fUseTimer = dwTimeoutSeconds != 0;
  231. g_iTimeoutTicks = (dwTimeoutSeconds * PROGRESS_TICKS_PER_SEC);
  232. // dialog frees this
  233. psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
  234. if (psParam == NULL)
  235. goto Ret;
  236. psParam->hInstance = hInstance;
  237. psParam->hwndParent = hwndParent;
  238. psParam->enumWhichBehavior = enumPROGRESSBARWITHTIMEOUT;
  239. psParam->dwTickerUpperRange = dwTickerSeconds * PROGRESS_TICKS_PER_SEC;
  240. psParam->iRscJobDescription = iRscJobDescription;
  241. psParam->pdbp = NULL;
  242. hProgressThread =
  243. CreateThread(
  244. NULL,
  245. 0,
  246. StartTimerThread,
  247. (void*)psParam,
  248. 0,
  249. &dwThread);
  250. Ret:
  251. if (NULL == hProgressThread)
  252. LocalFree(psParam);
  253. return hProgressThread;
  254. }
  255. void EndProgressDlg(HANDLE hProgressThread)
  256. {
  257. // end countdown immediately
  258. g_iTimeoutTicks = 0;
  259. if (!g_fUseTimer)
  260. {
  261. // make the controlling thread suddenly aware of the timer
  262. g_fUseTimer = TRUE;
  263. }
  264. // don't return until we're certain the progress dlg is gone
  265. for (;;)
  266. {
  267. DWORD dwExitCode;
  268. // break on error
  269. if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
  270. break;
  271. // continue until goes away
  272. if (STILL_ACTIVE != dwExitCode)
  273. break;
  274. Sleep(100);
  275. }
  276. CloseHandle(hProgressThread);
  277. }
  278. ///////////////////////////////////////////////////////
  279. // %age complete progress indicator
  280. DWORD WINAPI StartPercentCompleteThread( LPVOID lpParameter )
  281. {
  282. if (FICanShowDialogs())
  283. {
  284. PPROGRESSPROC_LPARAM psParam = (PPROGRESSPROC_LPARAM)lpParameter;
  285. HWND hwndProgressDlg = CreateDialogParam(
  286. psParam->hInstance,
  287. MAKEINTRESOURCE(IDD_PROGRESS_BOX),
  288. NULL,
  289. dlgProcProgress,
  290. (LPARAM)lpParameter);
  291. if (NULL == hwndProgressDlg) {GetLastError(); return 0;}
  292. ShowWindow(hwndProgressDlg, SW_SHOW);
  293. Sleep(0);
  294. for (;;)
  295. {
  296. if (ERROR_SUCCESS != SendMessage(hwndProgressDlg, PBM_STEPIT, 0, 0))
  297. break;
  298. UpdateWindow(hwndProgressDlg);
  299. Sleep(0);
  300. Sleep(1000/PROGRESS_TICKS_PER_SEC);
  301. }
  302. // send "fill the indicator"
  303. SendMessage(hwndProgressDlg, PBM_SETPOS, 0, 0);
  304. DestroyWindow(hwndProgressDlg);
  305. }
  306. return 0;
  307. }
  308. HANDLE
  309. StartPercentCompleteDlg(
  310. HINSTANCE hInstance,
  311. HWND hwndParent,
  312. UINT iRscJobDescription,
  313. DBBACKUPPROGRESS *pdbp)
  314. {
  315. HANDLE hProgressThread = NULL;
  316. DWORD dwThread;
  317. PPROGRESSPROC_LPARAM psParam = NULL;
  318. g_fUseTimer = FALSE;
  319. g_iTimeoutTicks = 0; // no timeout
  320. INITCOMMONCONTROLSEX sCommCtrl;
  321. sCommCtrl.dwSize = sizeof(sCommCtrl);
  322. sCommCtrl.dwICC = ICC_PROGRESS_CLASS;
  323. if (!InitCommonControlsEx(&sCommCtrl))
  324. goto Ret;
  325. // dialog frees this
  326. psParam = (PPROGRESSPROC_LPARAM)LocalAlloc(LMEM_FIXED, sizeof(PROGRESSPROC_LPARAM));
  327. if (psParam == NULL)
  328. goto Ret;
  329. psParam->hInstance = hInstance;
  330. psParam->hwndParent = hwndParent;
  331. psParam->enumWhichBehavior = enumPERCENTCOMPLETEBEHAVIOR;
  332. psParam->dwTickerUpperRange = 300;
  333. psParam->iRscJobDescription = iRscJobDescription;
  334. psParam->pdbp = pdbp;
  335. hProgressThread =
  336. CreateThread(
  337. NULL,
  338. 0,
  339. StartPercentCompleteThread,
  340. (void*)psParam,
  341. 0,
  342. &dwThread);
  343. Ret:
  344. if (NULL == hProgressThread)
  345. LocalFree(psParam);
  346. return hProgressThread;
  347. }
  348. void EndPercentCompleteDlg(HANDLE hProgressThread)
  349. {
  350. // don't return until we're certain the progress dlg is gone
  351. for (;;)
  352. {
  353. DWORD dwExitCode;
  354. // break on error
  355. if (!GetExitCodeThread(hProgressThread, &dwExitCode) )
  356. break;
  357. // continue until goes away
  358. if (STILL_ACTIVE != dwExitCode)
  359. break;
  360. Sleep(100);
  361. }
  362. CloseHandle(hProgressThread);
  363. }