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.

593 lines
19 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: WarningDialog.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // Class to manage dialog presentation for warnings and errors on termination
  7. // of bad applications.
  8. //
  9. // History: 2000-08-31 vtan created
  10. // 2000-11-06 vtan moved from fusapi to fussrv
  11. // --------------------------------------------------------------------------
  12. #ifdef _X86_
  13. #include "StandardHeader.h"
  14. #include "WarningDialog.h"
  15. #include <commctrl.h>
  16. #include <shlwapi.h>
  17. #include <shlwapip.h>
  18. #include "resource.h"
  19. #include "ContextActivation.h"
  20. static const int TEMP_STRING_SIZE = 512;
  21. static const int PROGRESS_TIMER_ID = 48517;
  22. // --------------------------------------------------------------------------
  23. // CWarningDialog::CWarningDialog
  24. //
  25. // Arguments: hInstance = HINSTANCE of the hosting DLL.
  26. // hwndParent = HWND of the parenting window/dialog.
  27. // pszApplication = Path to the application known to be bad.
  28. // pszUser = User of the application known to be bad.
  29. //
  30. // Returns: <none>
  31. //
  32. // Purpose: Constructor for CWarningDialog. This stores the static
  33. // parameters and converts the path to a friendly display name
  34. // using shlwapi!SHGetFileDescriptionW. If the friendly display
  35. // name cannot be obtained the executable name is used.
  36. //
  37. // History: 2000-08-31 vtan created
  38. // --------------------------------------------------------------------------
  39. CWarningDialog::CWarningDialog (HINSTANCE hInstance, HWND hwndParent, const WCHAR *pszApplication, const WCHAR *pszUser) :
  40. _hInstance(hInstance),
  41. _hModuleComctlv6(NULL),
  42. _hwndParent(hwndParent),
  43. _hwnd(NULL),
  44. _fCanShutdownApplication(false),
  45. _uiTimerID(0),
  46. _dwTickStart(0),
  47. _dwTickRefresh(0),
  48. _dwTickMaximum(0),
  49. _pszUser(pszUser)
  50. {
  51. UINT uiDisplayNameCount;
  52. WCHAR szTemp[MAX_PATH];
  53. // Borrow winlogon's manifest. This needs to be changed to a resource
  54. // within the server dll.
  55. static const TCHAR s_szLogonManifest[] = TEXT("WindowsLogon.manifest");
  56. TCHAR szPath[MAX_PATH];
  57. if (GetSystemDirectory(szPath, ARRAYSIZE(szPath)) != 0)
  58. {
  59. if ((lstrlen(szPath) + sizeof('\\') + lstrlen(s_szLogonManifest)) < ARRAYSIZE(szPath))
  60. {
  61. lstrcat(szPath, TEXT("\\"));
  62. lstrcat(szPath, s_szLogonManifest);
  63. CContextActivation::Create(szPath);
  64. }
  65. }
  66. uiDisplayNameCount = ARRAYSIZE(_szApplication);
  67. // If the path is quoted then remove the quotes.
  68. if (pszApplication[0] == L'\"')
  69. {
  70. int i, iStart;
  71. iStart = i = sizeof('\"');
  72. while ((pszApplication[i] != L'\"') && (pszApplication[i] != L'\0'))
  73. {
  74. ++i;
  75. }
  76. lstrcpyW(szTemp, pszApplication + iStart);
  77. szTemp[i - iStart] = L'\0';
  78. }
  79. // Otherwise just copy the path as is.
  80. else
  81. {
  82. lstrcpyW(szTemp, pszApplication);
  83. }
  84. if (SHGetFileDescriptionW(szTemp, NULL, NULL, _szApplication, &uiDisplayNameCount) == FALSE)
  85. {
  86. const WCHAR *pszFileName;
  87. pszFileName = PathFindFileNameW(szTemp);
  88. if (pszFileName == NULL)
  89. {
  90. pszFileName = pszApplication;
  91. }
  92. (WCHAR*)lstrcpynW(_szApplication, pszFileName, ARRAYSIZE(_szApplication));
  93. }
  94. // Bring in comctl32.dll while the manifest is active. This will
  95. // bring in comctlv6.dll which will register its window classes so
  96. // the dialogs can be themed.
  97. if (CContextActivation::HasContext())
  98. {
  99. CContextActivation context;
  100. _hModuleComctlv6 = LoadLibrary(TEXT("comctl32.dll"));
  101. }
  102. }
  103. // --------------------------------------------------------------------------
  104. // CWarningDialog::~CWarningDialog
  105. //
  106. // Arguments: <none>
  107. //
  108. // Returns: <none>
  109. //
  110. // Purpose: Destructor for CWarningDialog. Releases used resources.
  111. //
  112. // History: 2000-08-31 vtan created
  113. // --------------------------------------------------------------------------
  114. CWarningDialog::~CWarningDialog (void)
  115. {
  116. if (_hModuleComctlv6 != NULL)
  117. {
  118. TBOOL(FreeLibrary(_hModuleComctlv6));
  119. _hModuleComctlv6 = NULL;
  120. }
  121. CContextActivation::Destroy();
  122. }
  123. // --------------------------------------------------------------------------
  124. // CWarningDialog::ShowPrompt
  125. //
  126. // Arguments: fCanShutdownApplication = Decides which dialog to show.
  127. //
  128. // Returns: INT_PTR
  129. //
  130. // Purpose: Displays the appropriate warning dialog to the user based
  131. // on their privilege level (fCanShutdownApplication).
  132. //
  133. // History: 2000-08-31 vtan created
  134. // --------------------------------------------------------------------------
  135. INT_PTR CWarningDialog::ShowPrompt (bool fCanShutdownApplication)
  136. {
  137. CContextActivation context;
  138. _fCanShutdownApplication = fCanShutdownApplication;
  139. return(DialogBoxParam(_hInstance,
  140. MAKEINTRESOURCE(fCanShutdownApplication ? IDD_BADAPP_CLOSE : IDD_BADAPP_STOP),
  141. _hwndParent,
  142. PromptDialogProc,
  143. reinterpret_cast<LPARAM>(this)));
  144. }
  145. // --------------------------------------------------------------------------
  146. // CWarningDialog::ShowFailure
  147. //
  148. // Arguments: <none>
  149. //
  150. // Returns: <none>
  151. //
  152. // Purpose: Shows the failure to shut down the application dialog on the
  153. // assumption that the process cannot be terminated.
  154. //
  155. // History: 2000-09-01 vtan created
  156. // --------------------------------------------------------------------------
  157. void CWarningDialog::ShowFailure (void)
  158. {
  159. WCHAR *pszTemp;
  160. pszTemp = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, TEMP_STRING_SIZE * 3 * sizeof(TCHAR)));
  161. if (pszTemp != NULL)
  162. {
  163. WCHAR *pszText, *pszCaption;
  164. pszText = pszTemp + TEMP_STRING_SIZE;
  165. pszCaption = pszText + TEMP_STRING_SIZE;
  166. if ((LoadString(_hInstance,
  167. IDS_TERMINATEPROCESS_FAILURE,
  168. pszTemp,
  169. TEMP_STRING_SIZE) != 0) &&
  170. (LoadString(_hInstance,
  171. IDS_WARNING_CAPTION,
  172. pszCaption,
  173. TEMP_STRING_SIZE) != 0))
  174. {
  175. LPCTSTR pszArray[2];
  176. CContextActivation context;
  177. pszArray[0] = _szApplication;
  178. pszArray[1] = _pszUser;
  179. (DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  180. pszTemp,
  181. 0,
  182. 0,
  183. pszText,
  184. TEMP_STRING_SIZE,
  185. reinterpret_cast<va_list*>(&pszArray));
  186. (int)MessageBox(_hwndParent, pszText, pszCaption, MB_OK | MB_ICONERROR);
  187. }
  188. (HLOCAL)LocalFree(pszTemp);
  189. }
  190. }
  191. // --------------------------------------------------------------------------
  192. // CWarningDialog::ShowProgress
  193. //
  194. // Arguments: dwTickRefresh = Number of ticks for each refresh.
  195. // dwTickMaximum = Number of ticks for the progress dialog.
  196. //
  197. // Returns: <none>
  198. //
  199. // Purpose: Initializes the comctl32 progress control and invokes the
  200. // dialogs for the progress. It's self terminating after the
  201. // maximum number of ticks have been reached.
  202. //
  203. // History: 2000-11-04 vtan created
  204. // --------------------------------------------------------------------------
  205. void CWarningDialog::ShowProgress (DWORD dwTickRefresh, DWORD dwTickMaximum)
  206. {
  207. CContextActivation context;
  208. INITCOMMONCONTROLSEX iccEx;
  209. // Init comctl32 to get the progress control.
  210. iccEx.dwSize = sizeof(iccEx);
  211. iccEx.dwICC = ICC_PROGRESS_CLASS;
  212. if (InitCommonControlsEx(&iccEx) != FALSE)
  213. {
  214. _dwTickRefresh = dwTickRefresh;
  215. _dwTickMaximum = dwTickMaximum;
  216. (INT_PTR)DialogBoxParam(_hInstance,
  217. MAKEINTRESOURCE(IDD_PROGRESS),
  218. _hwndParent,
  219. ProgressDialogProc,
  220. reinterpret_cast<LPARAM>(this));
  221. }
  222. }
  223. // --------------------------------------------------------------------------
  224. // CWarningDialog::CloseDialog
  225. //
  226. // Arguments: <none>
  227. //
  228. // Returns: <none>
  229. //
  230. // Purpose: Ends the current dialog (with IDCANCEL) if being shown. If
  231. // there was a timing mechanism on the dialog then make sure it
  232. // is visible for at least 2 seconds.
  233. //
  234. // History: 2000-11-04 vtan created
  235. // --------------------------------------------------------------------------
  236. void CWarningDialog::CloseDialog (void)
  237. {
  238. if (_hwnd != NULL)
  239. {
  240. if (_dwTickStart != 0)
  241. {
  242. DWORD dwTickElapsed;
  243. dwTickElapsed = GetTickCount() - _dwTickStart;
  244. if (dwTickElapsed < 2000)
  245. {
  246. Sleep(2000 - dwTickElapsed);
  247. }
  248. }
  249. TBOOL(EndDialog(_hwnd, IDCANCEL));
  250. }
  251. }
  252. // --------------------------------------------------------------------------
  253. // CWarningDialog::CenterWindow
  254. //
  255. // Arguments: hwnd = HWND to center.
  256. //
  257. // Returns: <none>
  258. //
  259. // Purpose: Centers the given (assumed top level) window on the primary
  260. // monitor.
  261. //
  262. // History: 2000-08-31 vtan created
  263. // --------------------------------------------------------------------------
  264. void CWarningDialog::CenterWindow (HWND hwnd)
  265. {
  266. RECT rc;
  267. TBOOL(GetWindowRect(hwnd, &rc));
  268. rc.left = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2;
  269. rc.top = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 3;
  270. TBOOL(SetWindowPos(hwnd, HWND_TOP, rc.left, rc.top, 0, 0, SWP_NOSIZE));
  271. TBOOL(SetForegroundWindow(hwnd));
  272. }
  273. // --------------------------------------------------------------------------
  274. // CWarningDialog::Handle_Prompt_WM_INITDIALOG
  275. //
  276. // Arguments: hwnd = HWND of the dialog.
  277. //
  278. // Returns: <none>
  279. //
  280. // Purpose: Initializes the strings in the text fields of the dialog. It
  281. // uses the correct dialog for the access level.
  282. //
  283. // History: 2000-08-31 vtan created
  284. // --------------------------------------------------------------------------
  285. void CWarningDialog::Handle_Prompt_WM_INITDIALOG (HWND hwnd)
  286. {
  287. TCHAR *pszTemp1;
  288. _hwnd = hwnd;
  289. pszTemp1 = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, TEMP_STRING_SIZE * 2 * sizeof(TCHAR)));
  290. if (pszTemp1 != NULL)
  291. {
  292. TCHAR *pszTemp2;
  293. LPCTSTR pszArray[5];
  294. pszTemp2 = pszTemp1 + TEMP_STRING_SIZE;
  295. if (_fCanShutdownApplication)
  296. {
  297. (UINT)GetDlgItemText(hwnd, IDC_BADAPP_CLOSE, pszTemp1, TEMP_STRING_SIZE);
  298. pszArray[0] = pszArray[2] = pszArray[3] = pszArray[4] = _pszUser;
  299. pszArray[1] = _szApplication;
  300. (DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  301. pszTemp1,
  302. 0,
  303. 0,
  304. pszTemp2,
  305. TEMP_STRING_SIZE,
  306. reinterpret_cast<va_list*>(&pszArray));
  307. TBOOL(SetDlgItemText(hwnd, IDC_BADAPP_CLOSE, pszTemp2));
  308. }
  309. else
  310. {
  311. (UINT)GetDlgItemText(hwnd, IDC_BADAPP_STOP, pszTemp1, TEMP_STRING_SIZE);
  312. pszArray[0] = pszArray[2] = _pszUser;
  313. pszArray[1] = _szApplication;
  314. (DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  315. pszTemp1,
  316. 0,
  317. 0,
  318. pszTemp2,
  319. TEMP_STRING_SIZE,
  320. reinterpret_cast<va_list*>(&pszArray));
  321. TBOOL(SetDlgItemText(hwnd, IDC_BADAPP_STOP, pszTemp2));
  322. }
  323. (HLOCAL)LocalFree(pszTemp1);
  324. }
  325. _dwTickStart = 0;
  326. CenterWindow(hwnd);
  327. }
  328. // --------------------------------------------------------------------------
  329. // CWarningDialog::PromptDialogProc
  330. //
  331. // Arguments: See the platform SDK under DlgProc.
  332. //
  333. // Returns: See the platform SDK under DlgProc.
  334. //
  335. // Purpose: Handles messages to the dialog. IDOK and IDCANCEL are treated
  336. // as IDCANCEL when incoming. IDC_BADAPP_CLOSEPROGRAM is treated
  337. // as IDOK back to the caller. You must tab to the button or
  338. // click on it to get the desired effect.
  339. //
  340. // History: 2000-08-31 vtan created
  341. // --------------------------------------------------------------------------
  342. INT_PTR CALLBACK CWarningDialog::PromptDialogProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  343. {
  344. INT_PTR iResult;
  345. CWarningDialog *pThis;
  346. pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
  347. switch (uMsg)
  348. {
  349. case WM_INITDIALOG:
  350. pThis = reinterpret_cast<CWarningDialog*>(lParam);
  351. (LONG_PTR)SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  352. pThis->Handle_Prompt_WM_INITDIALOG(hwnd);
  353. iResult = TRUE;
  354. break;
  355. case WM_DESTROY:
  356. pThis->_hwnd = NULL;
  357. iResult = TRUE;
  358. break;
  359. case WM_COMMAND:
  360. switch (wParam)
  361. {
  362. case IDCANCEL:
  363. case IDOK:
  364. TBOOL(EndDialog(hwnd, IDCANCEL));
  365. break;
  366. case IDC_BADAPP_CLOSEPROGRAM:
  367. TBOOL(EndDialog(hwnd, IDOK));
  368. break;
  369. default:
  370. break;
  371. }
  372. iResult = TRUE;
  373. break;
  374. default:
  375. iResult = FALSE;
  376. break;
  377. }
  378. return(iResult);
  379. }
  380. // --------------------------------------------------------------------------
  381. // CWarningDialog::Handle_Progress_WM_INITDIALOG
  382. //
  383. // Arguments: hwnd = HWND of the dialog.
  384. //
  385. // Returns: <none>
  386. //
  387. // Purpose: Initializes the strings in the text fields of the dialog.
  388. //
  389. // History: 2000-11-04 vtan created
  390. // --------------------------------------------------------------------------
  391. void CWarningDialog::Handle_Progress_WM_INITDIALOG (HWND hwnd)
  392. {
  393. HWND hwndProgress;
  394. TCHAR *pszTemp1;
  395. _hwnd = hwnd;
  396. pszTemp1 = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, 2048 * sizeof(TCHAR)));
  397. if (pszTemp1 != NULL)
  398. {
  399. TCHAR *pszTemp2;
  400. LPCTSTR pszArray[2];
  401. pszTemp2 = pszTemp1 + TEMP_STRING_SIZE;
  402. (UINT)GetDlgItemText(hwnd, IDC_PROGRESS_CLOSE, pszTemp1, TEMP_STRING_SIZE);
  403. pszArray[0] = _szApplication;
  404. pszArray[1] = _pszUser;
  405. (DWORD)FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  406. pszTemp1,
  407. 0,
  408. 0,
  409. pszTemp2,
  410. TEMP_STRING_SIZE,
  411. reinterpret_cast<va_list*>(&pszArray));
  412. TBOOL(SetDlgItemText(hwnd, IDC_PROGRESS_CLOSE, pszTemp2));
  413. (HLOCAL)LocalFree(pszTemp1);
  414. }
  415. CenterWindow(hwnd);
  416. hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS_PROGRESSBAR);
  417. if (hwndProgress != NULL)
  418. {
  419. (LRESULT)SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, _dwTickMaximum));
  420. _uiTimerID = SetTimer(hwnd, PROGRESS_TIMER_ID, _dwTickRefresh, ProgressTimerProc);
  421. _dwTickStart = GetTickCount();
  422. }
  423. }
  424. // --------------------------------------------------------------------------
  425. // CWarningDialog::Handle_Progress_WM_DESTROY
  426. //
  427. // Arguments: hwnd = HWND of the dialog.
  428. //
  429. // Returns: <none>
  430. //
  431. // Purpose: Removes the timer from the associated progress dialog if one
  432. // was created for the dialog.
  433. //
  434. // History: 2000-11-04 vtan created
  435. // --------------------------------------------------------------------------
  436. void CWarningDialog::Handle_Progress_WM_DESTROY (HWND hwnd)
  437. {
  438. if (_uiTimerID != 0)
  439. {
  440. TBOOL(KillTimer(hwnd, _uiTimerID));
  441. _uiTimerID = 0;
  442. }
  443. }
  444. // --------------------------------------------------------------------------
  445. // CWarningDialog::ProgressTimerProc
  446. //
  447. // Arguments: See the platform SDK under TimerProc.
  448. //
  449. // Returns: See the platform SDK under TimerProc.
  450. //
  451. // Purpose: Timer procedure that it called back periodically. This
  452. // function animates the progress bar by setting it's completion
  453. // state to the amount of time that has elapsed. The progress
  454. // bar is based purely on time.
  455. //
  456. // If the time elapsed exceeds the maximum time then end the
  457. // dialog.
  458. //
  459. // History: 2000-11-04 vtan created
  460. // --------------------------------------------------------------------------
  461. void CALLBACK CWarningDialog::ProgressTimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  462. {
  463. UNREFERENCED_PARAMETER(uMsg);
  464. UNREFERENCED_PARAMETER(idEvent);
  465. HWND hwndProgress;
  466. CWarningDialog *pThis;
  467. pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
  468. hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS_PROGRESSBAR);
  469. if (hwndProgress != NULL)
  470. {
  471. (LRESULT)SendMessage(hwndProgress, PBM_SETPOS, dwTime - pThis->_dwTickStart, 0);
  472. if ((dwTime - pThis->_dwTickStart) > pThis->_dwTickMaximum)
  473. {
  474. TBOOL(EndDialog(hwnd, IDCANCEL));
  475. }
  476. }
  477. }
  478. // --------------------------------------------------------------------------
  479. // CWarningDialog::ProgressDialogProc
  480. //
  481. // Arguments: See the platform SDK under DlgProc.
  482. //
  483. // Returns: See the platform SDK under DlgProc.
  484. //
  485. // Purpose: Handles messages for the progress dialog.
  486. //
  487. // History: 2000-11-04 vtan created
  488. // --------------------------------------------------------------------------
  489. INT_PTR CALLBACK CWarningDialog::ProgressDialogProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  490. {
  491. UNREFERENCED_PARAMETER(wParam);
  492. INT_PTR iResult;
  493. CWarningDialog *pThis;
  494. pThis = reinterpret_cast<CWarningDialog*>(GetWindowLongPtr(hwnd, DWLP_USER));
  495. switch (uMsg)
  496. {
  497. case WM_INITDIALOG:
  498. pThis = reinterpret_cast<CWarningDialog*>(lParam);
  499. (LONG_PTR)SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  500. pThis->Handle_Progress_WM_INITDIALOG(hwnd);
  501. iResult = TRUE;
  502. break;
  503. case WM_DESTROY:
  504. pThis->Handle_Progress_WM_DESTROY(hwnd);
  505. pThis->_hwnd = NULL;
  506. iResult = TRUE;
  507. break;
  508. default:
  509. iResult = FALSE;
  510. break;
  511. }
  512. return(iResult);
  513. }
  514. #endif /* _X86_ */