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.

492 lines
15 KiB

  1. /*************************************************************************
  2. Private shell shutdown dialog implementation
  3. The shell needs a shutdown dialog implementation independent of MSGINA's
  4. implementation to ensure it will function on NT4 and Win9x machines.
  5. This version of shutdown should only be called if the LoadLib and
  6. GetProcAddress for the MSGINA version fail.
  7. This code should be kept in some type of sync with the code in
  8. win/gina/msgina/shtdndlg.c
  9. -dsheldon 10/27/98
  10. *************************************************************************/
  11. #include "shellprv.h"
  12. #include <windowsx.h>
  13. #include <help.h>
  14. #define MAX_SHTDN_OPTIONS 7
  15. #define MAX_CCH_NAME 64
  16. #define MAX_CCH_DESC 256
  17. typedef struct _SHUTDOWNOPTION
  18. {
  19. DWORD dwOption;
  20. TCHAR szName[MAX_CCH_NAME + 1];
  21. TCHAR szDesc[MAX_CCH_DESC + 1];
  22. } SHUTDOWNOPTION, *PSHUTDOWNOPTION;
  23. typedef struct _SHUTDOWNDLGDATA
  24. {
  25. SHUTDOWNOPTION rgShutdownOptions[MAX_SHTDN_OPTIONS];
  26. int cShutdownOptions;
  27. DWORD dwFlags;
  28. DWORD dwItemSelect;
  29. BOOL fEndDialogOnActivate;
  30. } SHUTDOWNDLGDATA, *PSHUTDOWNDLGDATA;
  31. // Internal function prototypes
  32. void SetShutdownOptionDescription(HWND hwndCombo, HWND hwndStatic);
  33. BOOL LoadShutdownOptionStrings(int idStringName, int idStringDesc,
  34. PSHUTDOWNOPTION pOption);
  35. BOOL BuildShutdownOptionArray(DWORD dwItems, LPCTSTR szUsername,
  36. PSHUTDOWNDLGDATA pdata);
  37. BOOL Shutdown_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
  38. DWORD GetOptionSelection(HWND hwndCombo);
  39. void SetShutdownOptionDescription(HWND hwndCombo, HWND hwndStatic);
  40. BOOL Shutdown_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
  41. BOOL_PTR CALLBACK Shutdown_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  42. LPARAM lParam);
  43. // Copied function implementations and constants
  44. // A function copied from gina that shutdown dialog needs.
  45. /*-----------------------------------------------------------------------------
  46. / MoveControls
  47. / ------------
  48. / Load the image and add the control to the dialog.
  49. /
  50. / In:
  51. / hWnd = window to move controls in
  52. / aID, cID = array of control ids to be moved
  53. / dx, dy = deltas to apply to controls
  54. /
  55. / Out:
  56. / -
  57. /----------------------------------------------------------------------------*/
  58. VOID MoveControls(HWND hWnd, UINT* aID, INT cID, INT dx, INT dy, BOOL fSizeWnd)
  59. {
  60. RECT rc;
  61. while ( --cID >= 0 )
  62. {
  63. HWND hWndCtrl = GetDlgItem(hWnd, aID[cID]);
  64. if ( hWndCtrl )
  65. {
  66. GetWindowRect(hWndCtrl, &rc);
  67. MapWindowPoints(NULL, hWnd, (LPPOINT)&rc, 2);
  68. OffsetRect(&rc, dx, dy);
  69. SetWindowPos(hWndCtrl, NULL, rc.left, rc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
  70. }
  71. }
  72. if ( fSizeWnd )
  73. {
  74. GetWindowRect(hWnd, &rc);
  75. MapWindowPoints(NULL, GetParent(hWnd), (LPPOINT)&rc, 2);
  76. SetWindowPos(hWnd, NULL,
  77. 0, 0, (rc.right-rc.left)+dx, (rc.bottom-rc.top)+dy,
  78. SWP_NOZORDER|SWP_NOMOVE);
  79. }
  80. }
  81. /****************************************************
  82. Option flags (dwFlags)
  83. ----------------------
  84. ****************************************************/
  85. #define SHTDN_NOHELP 0x000000001
  86. #define SHTDN_NOPALETTECHANGE 0x000000002
  87. // Shutdown reg value name
  88. #define SHUTDOWN_SETTING TEXT("Shutdown Setting")
  89. // Da code
  90. // -------
  91. BOOL LoadShutdownOptionStrings(int idStringName, int idStringDesc,
  92. PSHUTDOWNOPTION pOption)
  93. {
  94. BOOL fSuccess = (LoadString(HINST_THISDLL, idStringName, pOption->szName,
  95. ARRAYSIZE(pOption->szName)) != 0);
  96. fSuccess &= (LoadString(HINST_THISDLL, idStringDesc, pOption->szDesc,
  97. ARRAYSIZE(pOption->szDesc)) != 0);
  98. return fSuccess;
  99. }
  100. BOOL BuildShutdownOptionArray(DWORD dwItems, LPCTSTR szUsername,
  101. PSHUTDOWNDLGDATA pdata)
  102. {
  103. BOOL fSuccess = TRUE;
  104. pdata->cShutdownOptions = 0;
  105. if (dwItems & SHTDN_LOGOFF)
  106. {
  107. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_LOGOFF;
  108. // Note that logoff is a special case: format using a user name ala
  109. // "log off <username>".
  110. fSuccess &= LoadShutdownOptionStrings(IDS_LOGOFF_NAME,
  111. IDS_LOGOFF_DESC,
  112. &(pdata->rgShutdownOptions[pdata->cShutdownOptions]));
  113. if (fSuccess)
  114. {
  115. TCHAR szTemp[ARRAYSIZE(pdata->rgShutdownOptions[pdata->cShutdownOptions].szName)];
  116. if (szUsername != NULL)
  117. {
  118. wnsprintf(szTemp, ARRAYSIZE(szTemp),
  119. pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  120. szUsername);
  121. }
  122. else
  123. {
  124. wnsprintf(szTemp, ARRAYSIZE(szTemp),
  125. pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  126. TEXT(""));
  127. }
  128. // Now we have the real logoff title in szTemp; copy is back
  129. lstrcpy(pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  130. szTemp);
  131. // Success!
  132. pdata->cShutdownOptions ++;
  133. }
  134. }
  135. if (dwItems & SHTDN_SHUTDOWN)
  136. {
  137. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SHUTDOWN;
  138. fSuccess &= LoadShutdownOptionStrings(IDS_SHUTDOWN_NAME,
  139. IDS_SHUTDOWN_DESC,
  140. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  141. }
  142. if (dwItems & SHTDN_RESTART)
  143. {
  144. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_RESTART;
  145. fSuccess &= LoadShutdownOptionStrings(IDS_RESTART_NAME,
  146. IDS_RESTART_DESC,
  147. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  148. }
  149. if (dwItems & SHTDN_RESTART_DOS)
  150. {
  151. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_RESTART_DOS;
  152. fSuccess &= LoadShutdownOptionStrings(IDS_RESTARTDOS_NAME,
  153. IDS_RESTARTDOS_DESC,
  154. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  155. }
  156. if (dwItems & SHTDN_SLEEP)
  157. {
  158. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SLEEP;
  159. fSuccess &= LoadShutdownOptionStrings(IDS_SLEEP_NAME,
  160. IDS_SLEEP_DESC,
  161. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  162. }
  163. if (dwItems & SHTDN_SLEEP2)
  164. {
  165. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SLEEP2;
  166. fSuccess &= LoadShutdownOptionStrings(IDS_SLEEP2_NAME,
  167. IDS_SLEEP2_DESC,
  168. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  169. }
  170. if (dwItems & SHTDN_HIBERNATE)
  171. {
  172. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_HIBERNATE;
  173. fSuccess &= LoadShutdownOptionStrings(IDS_HIBERNATE_NAME,
  174. IDS_HIBERNATE_DESC,
  175. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  176. }
  177. return fSuccess;
  178. }
  179. BOOL Shutdown_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  180. {
  181. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA) lParam;
  182. HWND hwndCombo;
  183. int iOption;
  184. int iComboItem;
  185. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) lParam);
  186. // Hide the help button and move over OK and Cancel if applicable
  187. if (pdata->dwFlags & SHTDN_NOHELP)
  188. {
  189. static UINT rgidNoHelp[] = {IDOK, IDCANCEL};
  190. RECT rc1, rc2;
  191. int dx;
  192. HWND hwndHelp = GetDlgItem(hwnd, IDHELP);
  193. EnableWindow(hwndHelp, FALSE);
  194. ShowWindow(hwndHelp, SW_HIDE);
  195. GetWindowRect(hwndHelp, &rc1);
  196. GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc2);
  197. dx = rc1.left - rc2.left;
  198. MoveControls(hwnd, rgidNoHelp, ARRAYSIZE(rgidNoHelp), dx, 0, FALSE);
  199. }
  200. // Add the items specified to the combo box
  201. hwndCombo = GetDlgItem(hwnd, IDC_EXITOPTIONS_COMBO);
  202. for (iOption = 0; iOption < pdata->cShutdownOptions; iOption ++)
  203. {
  204. // Add the option
  205. iComboItem = ComboBox_AddString(hwndCombo,
  206. pdata->rgShutdownOptions[iOption].szName);
  207. if (iComboItem != (int) CB_ERR)
  208. {
  209. // Store a pointer to the option
  210. ComboBox_SetItemData(hwndCombo, iComboItem,
  211. &(pdata->rgShutdownOptions[iOption]));
  212. // See if we should select this option
  213. if (pdata->rgShutdownOptions[iOption].dwOption == pdata->dwItemSelect)
  214. {
  215. ComboBox_SetCurSel(hwndCombo, iComboItem);
  216. }
  217. }
  218. }
  219. // If we don't have a selection in the combo, do a default selection
  220. if (ComboBox_GetCurSel(hwndCombo) == CB_ERR)
  221. {
  222. ComboBox_SetCurSel(hwndCombo, 0);
  223. }
  224. SetShutdownOptionDescription(hwndCombo,
  225. GetDlgItem(hwnd, IDC_EXITOPTIONS_DESCRIPTION));
  226. // If we get an activate message, dismiss the dialog, since we just lost
  227. // focus
  228. pdata->fEndDialogOnActivate = TRUE;
  229. return TRUE;
  230. }
  231. DWORD GetOptionSelection(HWND hwndCombo)
  232. {
  233. DWORD dwResult;
  234. PSHUTDOWNOPTION pOption;
  235. int iItem = ComboBox_GetCurSel(hwndCombo);
  236. if (iItem != (int) CB_ERR)
  237. {
  238. pOption = (PSHUTDOWNOPTION) ComboBox_GetItemData(hwndCombo, iItem);
  239. dwResult = pOption->dwOption;
  240. }
  241. else
  242. {
  243. dwResult = SHTDN_NONE;
  244. }
  245. return dwResult;
  246. }
  247. void SetShutdownOptionDescription(HWND hwndCombo, HWND hwndStatic)
  248. {
  249. int iItem;
  250. PSHUTDOWNOPTION pOption;
  251. iItem = ComboBox_GetCurSel(hwndCombo);
  252. if (iItem != CB_ERR)
  253. {
  254. pOption = (PSHUTDOWNOPTION) ComboBox_GetItemData(hwndCombo, iItem);
  255. SetWindowText(hwndStatic, pOption->szDesc);
  256. }
  257. }
  258. BOOL Shutdown_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  259. {
  260. BOOL fHandled = FALSE;
  261. DWORD dwDlgResult;
  262. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA)
  263. GetWindowLongPtr(hwnd, GWLP_USERDATA);
  264. switch (id)
  265. {
  266. case IDOK:
  267. dwDlgResult = GetOptionSelection(GetDlgItem(hwnd, IDC_EXITOPTIONS_COMBO));
  268. if (dwDlgResult != SHTDN_NONE)
  269. {
  270. pdata->fEndDialogOnActivate = FALSE;
  271. fHandled = TRUE;
  272. EndDialog(hwnd, (int) dwDlgResult);
  273. }
  274. break;
  275. case IDCANCEL:
  276. pdata->fEndDialogOnActivate = FALSE;
  277. EndDialog(hwnd, (int) SHTDN_NONE);
  278. fHandled = TRUE;
  279. break;
  280. case IDC_EXITOPTIONS_COMBO:
  281. if (codeNotify == CBN_SELCHANGE)
  282. {
  283. SetShutdownOptionDescription(hwndCtl,
  284. GetDlgItem(hwnd, IDC_EXITOPTIONS_DESCRIPTION));
  285. fHandled = TRUE;
  286. }
  287. break;
  288. case IDHELP:
  289. WinHelp(hwnd, TEXT("windows.hlp>proc4"), HELP_CONTEXT, (DWORD) IDH_TRAY_SHUTDOWN_HELP);
  290. break;
  291. }
  292. return fHandled;
  293. }
  294. BOOL_PTR CALLBACK Shutdown_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  295. LPARAM lParam)
  296. {
  297. switch (uMsg)
  298. {
  299. HANDLE_MSG(hwnd, WM_INITDIALOG, Shutdown_OnInitDialog);
  300. HANDLE_MSG(hwnd, WM_COMMAND, Shutdown_OnCommand);
  301. case WM_INITMENUPOPUP:
  302. {
  303. EnableMenuItem((HMENU)wParam, SC_MOVE, MF_BYCOMMAND|MF_GRAYED);
  304. }
  305. break;
  306. case WM_SYSCOMMAND:
  307. // Blow off moves (only really needed for 32bit land).
  308. if ((wParam & ~0x0F) == SC_MOVE)
  309. return TRUE;
  310. break;
  311. case WM_ACTIVATE:
  312. // If we're loosing the activation for some other reason than
  313. // the user click OK/CANCEL then bail.
  314. if (LOWORD(wParam) == WA_INACTIVE)
  315. {
  316. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  317. if (pdata->fEndDialogOnActivate)
  318. {
  319. pdata->fEndDialogOnActivate = FALSE;
  320. EndDialog(hwnd, SHTDN_NONE);
  321. }
  322. }
  323. break;
  324. }
  325. return FALSE;
  326. }
  327. /****************************************************************************
  328. ShutdownDialog
  329. --------------
  330. Launches the shutdown dialog.
  331. hWlx and pfnWlxDialogBoxParam MUST be null for this shell-only version
  332. Other flags are listed in shtdnp.h.
  333. ****************************************************************************/
  334. DWORD ShutdownDialog(HWND hwndParent, DWORD dwItems, DWORD dwItemSelect,
  335. LPCTSTR szUsername, DWORD dwFlags, void* hWlx,
  336. void* pfnWlxDialogBoxParam)
  337. {
  338. // Array of shutdown options - the dialog data
  339. SHUTDOWNDLGDATA data;
  340. DWORD dwResult;
  341. // Set the flags
  342. data.dwFlags = dwFlags;
  343. // Set the initially selected item
  344. data.dwItemSelect = dwItemSelect;
  345. // Read in the strings for the shutdown option names and descriptions
  346. if (BuildShutdownOptionArray(dwItems, szUsername, &data))
  347. {
  348. // Display the dialog and return the user's selection
  349. // ..if the caller wants, use a Wlx dialog box function
  350. if ((hWlx != NULL) || (pfnWlxDialogBoxParam != NULL))
  351. {
  352. // Error; winlogon should never call this
  353. // cheesy shell version of shutdown
  354. dwResult = SHTDN_NONE;
  355. }
  356. else
  357. {
  358. // Use standard dialog box
  359. dwResult = (DWORD) DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(IDD_EXITWINDOWS_DIALOG), hwndParent,
  360. Shutdown_DialogProc, (LPARAM) &data);
  361. }
  362. }
  363. else
  364. {
  365. dwResult = SHTDN_NONE;
  366. }
  367. return dwResult;
  368. }
  369. DWORD DownlevelShellShutdownDialog(HWND hwndParent, DWORD dwItems, LPCTSTR szUsername)
  370. {
  371. DWORD dwSelect = SHTDN_NONE;
  372. DWORD dwDialogResult;
  373. HKEY hkeyShutdown;
  374. DWORD dwType;
  375. DWORD dwDisposition;
  376. LONG lResult;
  377. // get the User's last selection.
  378. lResult = RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER,
  379. 0, 0, 0, KEY_READ, NULL, &hkeyShutdown, &dwDisposition);
  380. if (lResult == ERROR_SUCCESS)
  381. {
  382. DWORD cbData = sizeof(dwSelect);
  383. lResult = SHQueryValueEx(hkeyShutdown, SHUTDOWN_SETTING,
  384. 0, &dwType, (LPBYTE)&dwSelect, &cbData);
  385. RegCloseKey(hkeyShutdown);
  386. }
  387. if (dwSelect == SHTDN_NONE)
  388. {
  389. dwSelect = SHTDN_SHUTDOWN;
  390. }
  391. dwDialogResult = ShutdownDialog(hwndParent, dwItems, dwSelect,
  392. szUsername, SHTDN_NOPALETTECHANGE, NULL, NULL);
  393. if (dwDialogResult != SHTDN_NONE)
  394. {
  395. // Save back the user's choice to the registry
  396. if (RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER,
  397. 0, 0, 0, KEY_WRITE, NULL, &hkeyShutdown, &dwDisposition) == ERROR_SUCCESS)
  398. {
  399. RegSetValueEx(hkeyShutdown, SHUTDOWN_SETTING,
  400. 0, REG_DWORD, (LPBYTE)&dwDialogResult, sizeof(dwDialogResult));
  401. RegCloseKey(hkeyShutdown);
  402. }
  403. }
  404. return dwDialogResult;
  405. }