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.

523 lines
16 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. StringCchPrintf(szTemp,
  119. ARRAYSIZE(szTemp),
  120. pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  121. szUsername);
  122. }
  123. else
  124. {
  125. StringCchPrintf(szTemp,
  126. ARRAYSIZE(szTemp),
  127. pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  128. TEXT(""));
  129. }
  130. // Now we have the real logoff title in szTemp; copy is back
  131. StringCchCopy(pdata->rgShutdownOptions[pdata->cShutdownOptions].szName,
  132. ARRAYSIZE(pdata->rgShutdownOptions[pdata->cShutdownOptions].szName),
  133. szTemp);
  134. // Success!
  135. pdata->cShutdownOptions ++;
  136. }
  137. }
  138. if (dwItems & SHTDN_SHUTDOWN)
  139. {
  140. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SHUTDOWN;
  141. fSuccess &= LoadShutdownOptionStrings(IDS_SHUTDOWN_NAME,
  142. IDS_SHUTDOWN_DESC,
  143. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  144. }
  145. if (dwItems & SHTDN_RESTART)
  146. {
  147. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_RESTART;
  148. fSuccess &= LoadShutdownOptionStrings(IDS_RESTART_NAME,
  149. IDS_RESTART_DESC,
  150. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  151. }
  152. if (dwItems & SHTDN_RESTART_DOS)
  153. {
  154. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_RESTART_DOS;
  155. fSuccess &= LoadShutdownOptionStrings(IDS_RESTARTDOS_NAME,
  156. IDS_RESTARTDOS_DESC,
  157. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  158. }
  159. if (dwItems & SHTDN_SLEEP)
  160. {
  161. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SLEEP;
  162. fSuccess &= LoadShutdownOptionStrings(IDS_SLEEP_NAME,
  163. IDS_SLEEP_DESC,
  164. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  165. }
  166. if (dwItems & SHTDN_SLEEP2)
  167. {
  168. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_SLEEP2;
  169. fSuccess &= LoadShutdownOptionStrings(IDS_SLEEP2_NAME,
  170. IDS_SLEEP2_DESC,
  171. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  172. }
  173. if (dwItems & SHTDN_HIBERNATE)
  174. {
  175. pdata->rgShutdownOptions[pdata->cShutdownOptions].dwOption = SHTDN_HIBERNATE;
  176. fSuccess &= LoadShutdownOptionStrings(IDS_HIBERNATE_NAME,
  177. IDS_HIBERNATE_DESC,
  178. &(pdata->rgShutdownOptions[pdata->cShutdownOptions ++]));
  179. }
  180. return fSuccess;
  181. }
  182. BOOL Shutdown_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  183. {
  184. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA) lParam;
  185. HWND hwndCombo;
  186. int iOption;
  187. int iComboItem;
  188. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) lParam);
  189. // Hide the help button and move over OK and Cancel if applicable
  190. if (pdata->dwFlags & SHTDN_NOHELP)
  191. {
  192. static UINT rgidNoHelp[] = {IDOK, IDCANCEL};
  193. RECT rc1, rc2;
  194. int dx;
  195. HWND hwndHelp = GetDlgItem(hwnd, IDHELP);
  196. EnableWindow(hwndHelp, FALSE);
  197. ShowWindow(hwndHelp, SW_HIDE);
  198. GetWindowRect(hwndHelp, &rc1);
  199. GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc2);
  200. dx = rc1.left - rc2.left;
  201. MoveControls(hwnd, rgidNoHelp, ARRAYSIZE(rgidNoHelp), dx, 0, FALSE);
  202. }
  203. // Add the items specified to the combo box
  204. hwndCombo = GetDlgItem(hwnd, IDC_EXITOPTIONS_COMBO);
  205. for (iOption = 0; iOption < pdata->cShutdownOptions; iOption ++)
  206. {
  207. // Add the option
  208. iComboItem = ComboBox_AddString(hwndCombo,
  209. pdata->rgShutdownOptions[iOption].szName);
  210. if (iComboItem != (int) CB_ERR)
  211. {
  212. // Store a pointer to the option
  213. ComboBox_SetItemData(hwndCombo, iComboItem,
  214. &(pdata->rgShutdownOptions[iOption]));
  215. // See if we should select this option
  216. if (pdata->rgShutdownOptions[iOption].dwOption == pdata->dwItemSelect)
  217. {
  218. ComboBox_SetCurSel(hwndCombo, iComboItem);
  219. }
  220. }
  221. }
  222. // If we don't have a selection in the combo, do a default selection
  223. if (ComboBox_GetCurSel(hwndCombo) == CB_ERR)
  224. {
  225. ComboBox_SetCurSel(hwndCombo, 0);
  226. }
  227. SetShutdownOptionDescription(hwndCombo,
  228. GetDlgItem(hwnd, IDC_EXITOPTIONS_DESCRIPTION));
  229. // If we get an activate message, dismiss the dialog, since we just lost
  230. // focus
  231. pdata->fEndDialogOnActivate = TRUE;
  232. return TRUE;
  233. }
  234. DWORD GetOptionSelection(HWND hwndCombo)
  235. {
  236. DWORD dwResult;
  237. PSHUTDOWNOPTION pOption;
  238. int iItem = ComboBox_GetCurSel(hwndCombo);
  239. if (iItem != (int) CB_ERR)
  240. {
  241. pOption = (PSHUTDOWNOPTION) ComboBox_GetItemData(hwndCombo, iItem);
  242. dwResult = pOption->dwOption;
  243. }
  244. else
  245. {
  246. dwResult = SHTDN_NONE;
  247. }
  248. return dwResult;
  249. }
  250. void SetShutdownOptionDescription(HWND hwndCombo, HWND hwndStatic)
  251. {
  252. int iItem;
  253. PSHUTDOWNOPTION pOption;
  254. iItem = ComboBox_GetCurSel(hwndCombo);
  255. if (iItem != CB_ERR)
  256. {
  257. pOption = (PSHUTDOWNOPTION) ComboBox_GetItemData(hwndCombo, iItem);
  258. SetWindowText(hwndStatic, pOption->szDesc);
  259. }
  260. }
  261. BOOL Shutdown_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  262. {
  263. BOOL fHandled = FALSE;
  264. DWORD dwDlgResult;
  265. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA)
  266. GetWindowLongPtr(hwnd, GWLP_USERDATA);
  267. switch (id)
  268. {
  269. case IDOK:
  270. dwDlgResult = GetOptionSelection(GetDlgItem(hwnd, IDC_EXITOPTIONS_COMBO));
  271. if (dwDlgResult != SHTDN_NONE)
  272. {
  273. pdata->fEndDialogOnActivate = FALSE;
  274. fHandled = TRUE;
  275. EndDialog(hwnd, (int) dwDlgResult);
  276. }
  277. break;
  278. case IDCANCEL:
  279. pdata->fEndDialogOnActivate = FALSE;
  280. EndDialog(hwnd, (int) SHTDN_NONE);
  281. fHandled = TRUE;
  282. break;
  283. case IDC_EXITOPTIONS_COMBO:
  284. if (codeNotify == CBN_SELCHANGE)
  285. {
  286. SetShutdownOptionDescription(hwndCtl,
  287. GetDlgItem(hwnd, IDC_EXITOPTIONS_DESCRIPTION));
  288. fHandled = TRUE;
  289. }
  290. break;
  291. case IDHELP:
  292. WinHelp(hwnd, TEXT("windows.hlp>proc4"), HELP_CONTEXT, (DWORD) IDH_TRAY_SHUTDOWN_HELP);
  293. break;
  294. }
  295. return fHandled;
  296. }
  297. BOOL_PTR CALLBACK Shutdown_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  298. LPARAM lParam)
  299. {
  300. switch (uMsg)
  301. {
  302. HANDLE_MSG(hwnd, WM_INITDIALOG, Shutdown_OnInitDialog);
  303. HANDLE_MSG(hwnd, WM_COMMAND, Shutdown_OnCommand);
  304. case WM_INITMENUPOPUP:
  305. {
  306. EnableMenuItem((HMENU)wParam, SC_MOVE, MF_BYCOMMAND|MF_GRAYED);
  307. }
  308. break;
  309. case WM_SYSCOMMAND:
  310. // Blow off moves (only really needed for 32bit land).
  311. if ((wParam & ~0x0F) == SC_MOVE)
  312. return TRUE;
  313. break;
  314. case WM_ACTIVATE:
  315. // If we're loosing the activation for some other reason than
  316. // the user click OK/CANCEL then bail.
  317. if (LOWORD(wParam) == WA_INACTIVE)
  318. {
  319. PSHUTDOWNDLGDATA pdata = (PSHUTDOWNDLGDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  320. if (pdata->fEndDialogOnActivate)
  321. {
  322. pdata->fEndDialogOnActivate = FALSE;
  323. EndDialog(hwnd, SHTDN_NONE);
  324. }
  325. }
  326. break;
  327. }
  328. return FALSE;
  329. }
  330. /****************************************************************************
  331. ShutdownDialog
  332. --------------
  333. Launches the shutdown dialog.
  334. hWlx and pfnWlxDialogBoxParam MUST be null for this shell-only version
  335. Other flags are listed in shtdnp.h.
  336. ****************************************************************************/
  337. DWORD ShutdownDialog(HWND hwndParent, DWORD dwItems, DWORD dwItemSelect,
  338. LPCTSTR szUsername, DWORD dwFlags, void* hWlx,
  339. void* pfnWlxDialogBoxParam)
  340. {
  341. // Array of shutdown options - the dialog data
  342. SHUTDOWNDLGDATA data;
  343. DWORD dwResult;
  344. // Set the flags
  345. data.dwFlags = dwFlags;
  346. // Set the initially selected item
  347. data.dwItemSelect = dwItemSelect;
  348. // Read in the strings for the shutdown option names and descriptions
  349. if (BuildShutdownOptionArray(dwItems, szUsername, &data))
  350. {
  351. // Display the dialog and return the user's selection
  352. // ..if the caller wants, use a Wlx dialog box function
  353. if ((hWlx != NULL) || (pfnWlxDialogBoxParam != NULL))
  354. {
  355. // Error; winlogon should never call this
  356. // cheesy shell version of shutdown
  357. dwResult = SHTDN_NONE;
  358. }
  359. else
  360. {
  361. // Use standard dialog box
  362. dwResult = (DWORD) DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(IDD_EXITWINDOWS_DIALOG), hwndParent,
  363. Shutdown_DialogProc, (LPARAM) &data);
  364. }
  365. }
  366. else
  367. {
  368. dwResult = SHTDN_NONE;
  369. }
  370. return dwResult;
  371. }
  372. DWORD DownlevelShellShutdownDialog(HWND hwndParent, DWORD dwItems, LPCTSTR szUsername)
  373. {
  374. DWORD dwSelect = SHTDN_NONE;
  375. DWORD dwDialogResult;
  376. HKEY hkeyShutdown;
  377. DWORD dwType;
  378. DWORD dwDisposition;
  379. LONG lResult;
  380. // get the User's last selection.
  381. lResult = RegCreateKeyEx(HKEY_CURRENT_USER,
  382. REGSTR_PATH_EXPLORER,
  383. 0,
  384. 0,
  385. 0,
  386. KEY_QUERY_VALUE,
  387. NULL,
  388. &hkeyShutdown,
  389. &dwDisposition);
  390. if (lResult == ERROR_SUCCESS)
  391. {
  392. DWORD cbData = sizeof(dwSelect);
  393. lResult = SHQueryValueEx(hkeyShutdown,
  394. SHUTDOWN_SETTING,
  395. 0,
  396. &dwType,
  397. (LPBYTE)&dwSelect,
  398. &cbData);
  399. RegCloseKey(hkeyShutdown);
  400. }
  401. if (dwSelect == SHTDN_NONE)
  402. {
  403. dwSelect = SHTDN_SHUTDOWN;
  404. }
  405. dwDialogResult = ShutdownDialog(hwndParent,
  406. dwItems,
  407. dwSelect,
  408. szUsername,
  409. SHTDN_NOPALETTECHANGE,
  410. NULL,
  411. NULL);
  412. if (dwDialogResult != SHTDN_NONE)
  413. {
  414. // Save back the user's choice to the registry
  415. if (RegCreateKeyEx(HKEY_CURRENT_USER,
  416. REGSTR_PATH_EXPLORER,
  417. 0,
  418. 0,
  419. 0,
  420. KEY_SET_VALUE,
  421. NULL,
  422. &hkeyShutdown,
  423. &dwDisposition) == ERROR_SUCCESS)
  424. {
  425. RegSetValueEx(hkeyShutdown,
  426. SHUTDOWN_SETTING,
  427. 0,
  428. REG_DWORD,
  429. (LPBYTE)&dwDialogResult,
  430. sizeof(dwDialogResult));
  431. RegCloseKey(hkeyShutdown);
  432. }
  433. }
  434. return dwDialogResult;
  435. }