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.

706 lines
20 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: options.c
  3. *
  4. * Copyright (c) 1991, Microsoft Corporation
  5. *
  6. * Implementation of functions to support security options dialog.
  7. *
  8. * History:
  9. * 12-05-91 Davidc Created.
  10. \***************************************************************************/
  11. #include "msgina.h"
  12. #include "shtdnp.h"
  13. #include <stdio.h>
  14. #include <wchar.h>
  15. #pragma hdrstop
  16. #define CTRL_TASKLIST_SHELL
  17. #define LPTSTR LPWSTR
  18. #define BOOLIFY(expr) (!!(expr))
  19. //
  20. // Private prototypes
  21. //
  22. INT_PTR WINAPI
  23. OptionsDlgProc(
  24. HWND hDlg,
  25. UINT message,
  26. WPARAM wParam,
  27. LPARAM lParam
  28. );
  29. BOOL OptionsDlgInit(HWND);
  30. INT_PTR WINAPI
  31. EndWindowsSessionDlgProc(
  32. HWND hDlg,
  33. UINT message,
  34. WPARAM wParam,
  35. LPARAM lParam
  36. );
  37. /******************************************************************************
  38. *
  39. * HandleFailedDisconnect
  40. *
  41. * Tell the user why the disconnect from the current Logon failed.
  42. *
  43. * ENTRY:
  44. * hDlg (input)
  45. * This dialog's window handle.
  46. * SessionId (input)
  47. * The user's current SessionId.
  48. *
  49. * EXIT:
  50. *
  51. ******************************************************************************/
  52. VOID
  53. HandleFailedDisconnect( HWND hDlg,
  54. ULONG SessionId,
  55. PGLOBALS pGlobals )
  56. {
  57. DWORD Error;
  58. TCHAR Buffer1[MAX_STRING_BYTES];
  59. TCHAR Buffer2[MAX_STRING_BYTES];
  60. TCHAR Buffer3[MAX_STRING_BYTES];
  61. Error = GetLastError();
  62. switch (Error) {
  63. default:
  64. LoadString( hDllInstance, IDS_MULTIUSER_UNEXPECTED_DISCONNECT_FAILURE,
  65. Buffer1, MAX_STRING_BYTES );
  66. FormatMessage(
  67. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  68. NULL, Error, 0, Buffer3, MAX_STRING_BYTES, NULL );
  69. _snwprintf(Buffer2, MAX_STRING_BYTES, Buffer1, SessionId, Buffer3);
  70. LoadString( hDllInstance, IDS_MULTIUSER_DISCONNECT_FAILED,
  71. Buffer1, MAX_STRING_BYTES );
  72. TimeoutMessageBoxlpstr( hDlg, pGlobals, Buffer2,
  73. Buffer1,
  74. MB_OK | MB_ICONEXCLAMATION,
  75. TIMEOUT_CURRENT );
  76. break;
  77. }
  78. }
  79. /***************************************************************************\
  80. * SecurityOptions
  81. *
  82. * Show the user the security options dialog and do what they ask.
  83. *
  84. * Returns:
  85. * MSGINA_DLG_SUCCESS if everything went OK and the user wants to continue
  86. * DLG_LOCK_WORKSTAION if the user chooses to lock the workstation
  87. * DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
  88. * MSGINA_DLG_FAILURE if the dialog cannot be brought up.
  89. *
  90. * History:
  91. * 12-09-91 Davidc Created.
  92. \***************************************************************************/
  93. INT_PTR
  94. SecurityOptions(
  95. PGLOBALS pGlobals)
  96. {
  97. int Result;
  98. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx, OPTIONS_TIMEOUT);
  99. Result = pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  100. hDllInstance,
  101. (LPTSTR)IDD_OPTIONS_DIALOG,
  102. NULL,
  103. OptionsDlgProc,
  104. (LPARAM) pGlobals);
  105. if (Result == WLX_DLG_INPUT_TIMEOUT)
  106. {
  107. Result = MSGINA_DLG_SUCCESS;
  108. }
  109. return(Result);
  110. }
  111. /***************************************************************************\
  112. *
  113. * FUNCTION: OptionsDlgProc
  114. *
  115. * PURPOSE: Processes messages for Security options dialog
  116. *
  117. \***************************************************************************/
  118. INT_PTR WINAPI
  119. OptionsDlgProc(
  120. HWND hDlg,
  121. UINT message,
  122. WPARAM wParam,
  123. LPARAM lParam
  124. )
  125. {
  126. PGLOBALS pGlobals = (PGLOBALS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  127. INT_PTR Result;
  128. HANDLE UserHandle;
  129. NTSTATUS Status;
  130. BOOL EnableResult;
  131. BOOL ControlKey;
  132. switch (message) {
  133. case WM_INITDIALOG:
  134. SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
  135. if (!OptionsDlgInit(hDlg))
  136. {
  137. EndDialog(hDlg, MSGINA_DLG_FAILURE);
  138. }
  139. return(TRUE);
  140. case WLX_WM_SAS:
  141. //
  142. // If this is someone hitting C-A-D, swallow it.
  143. //
  144. if (wParam == WLX_SAS_TYPE_CTRL_ALT_DEL)
  145. {
  146. return(TRUE);
  147. }
  148. //
  149. // Other SAS's (like timeout), return FALSE and let winlogon
  150. // deal with it.
  151. //
  152. DebugLog((DEB_TRACE, "Received SAS event %d, which we're letting winlogon cope with\n", wParam));
  153. return(FALSE);
  154. case WM_COMMAND:
  155. ControlKey = (GetKeyState(VK_LCONTROL) < 0) ||
  156. (GetKeyState(VK_RCONTROL) < 0) ;
  157. switch (LOWORD(wParam))
  158. {
  159. case IDCANCEL:
  160. EndDialog(hDlg, MSGINA_DLG_SUCCESS);
  161. return TRUE;
  162. case IDD_OPTIONS_CHANGEPWD:
  163. Result = ChangePassword(hDlg,
  164. pGlobals,
  165. pGlobals->UserName,
  166. pGlobals->Domain,
  167. CHANGEPWD_OPTION_ALL );
  168. if (DLG_INTERRUPTED(Result))
  169. {
  170. EndDialog(hDlg, Result);
  171. }
  172. return(TRUE);
  173. case IDD_OPTIONS_LOCK:
  174. EndDialog(hDlg, MSGINA_DLG_LOCK_WORKSTATION);
  175. return(TRUE);
  176. case IDD_OPTIONS_LOGOFF:
  177. if (ControlKey)
  178. {
  179. Result = TimeoutMessageBox(hDlg,
  180. pGlobals,
  181. IDS_LOGOFF_LOSE_CHANGES,
  182. IDS_LOGOFF_TITLE,
  183. MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONSTOP,
  184. TIMEOUT_CURRENT);
  185. if (Result == MSGINA_DLG_SUCCESS)
  186. {
  187. EndDialog(hDlg, MSGINA_DLG_FORCE_LOGOFF);
  188. }
  189. }
  190. else
  191. {
  192. //
  193. // Confirm the user really knows what they're doing.
  194. //
  195. Result = pWlxFuncs->WlxDialogBoxParam(
  196. pGlobals->hGlobalWlx,
  197. hDllInstance,
  198. MAKEINTRESOURCE(IDD_LOGOFFWINDOWS_DIALOG),
  199. hDlg,
  200. EndWindowsSessionDlgProc,
  201. (LPARAM)pGlobals);
  202. if (Result == MSGINA_DLG_SUCCESS)
  203. {
  204. EndDialog(hDlg, MSGINA_DLG_USER_LOGOFF);
  205. }
  206. }
  207. return(TRUE);
  208. case IDD_OPTIONS_SHUTDOWN:
  209. //
  210. // If they held down Ctrl while selecting shutdown - then
  211. // we'll do a quick and dirty reboot.
  212. // i.e. we skip the call to ExitWindows
  213. //
  214. if ( ControlKey && TestUserPrivilege(pGlobals->UserProcessData.UserToken, SE_SHUTDOWN_PRIVILEGE))
  215. {
  216. //
  217. // Check they know what they're doing
  218. //
  219. Result = TimeoutMessageBox(hDlg,
  220. pGlobals,
  221. IDS_REBOOT_LOSE_CHANGES,
  222. IDS_EMERGENCY_SHUTDOWN,
  223. MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONSTOP,
  224. TIMEOUT_CURRENT);
  225. if (Result == MSGINA_DLG_SUCCESS)
  226. {
  227. //
  228. // Impersonate the user for the shutdown call
  229. //
  230. UserHandle = ImpersonateUser( &pGlobals->UserProcessData, NULL );
  231. ASSERT(UserHandle != NULL);
  232. if ( UserHandle )
  233. {
  234. //
  235. // Enable the shutdown privilege
  236. // This should always succeed - we are either system or a user who
  237. // successfully passed the privilege check in ExitWindowsEx.
  238. //
  239. EnableResult = EnablePrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE);
  240. ASSERT(EnableResult);
  241. //
  242. // Do the final system shutdown pass (reboot). Note, if
  243. // the privilege was not enabled, the API will reject this
  244. // call.
  245. //
  246. Status = NtShutdownSystem(ShutdownReboot);
  247. }
  248. }
  249. if (Result != MSGINA_DLG_FAILURE)
  250. {
  251. EndDialog(hDlg, Result);
  252. }
  253. return(TRUE);
  254. }
  255. //
  256. // This is a normal shutdown request
  257. //
  258. // Check they know what they're doing and find
  259. // out if they want to reboot too.
  260. //
  261. Result = WinlogonShutdownDialog(hDlg, pGlobals, 0);
  262. // Pre-filter the Disconnect option and handle
  263. // it now since it may fail
  264. if (Result == MSGINA_DLG_DISCONNECT)
  265. {
  266. if ( pWlxFuncs->WlxDisconnect() )
  267. {
  268. Result = MSGINA_DLG_SUCCESS;
  269. }
  270. else
  271. {
  272. HandleFailedDisconnect(hDlg, pGlobals->MuGlobals.SessionId, pGlobals);
  273. Result = MSGINA_DLG_FAILURE;
  274. }
  275. }
  276. if (Result != MSGINA_DLG_FAILURE)
  277. {
  278. EndDialog(hDlg, Result);
  279. }
  280. return(TRUE);
  281. case IDD_OPTIONS_TASKLIST:
  282. EndDialog(hDlg, MSGINA_DLG_TASKLIST);
  283. //
  284. // Tickle the messenger so it will display any queue'd messages.
  285. // (This call is a kind of NoOp).
  286. //
  287. NetMessageNameDel(NULL,L"");
  288. return(TRUE);
  289. break;
  290. }
  291. case WM_ERASEBKGND:
  292. return PaintBranding(hDlg, (HDC)wParam, 0, FALSE, FALSE, COLOR_BTNFACE);
  293. case WM_QUERYNEWPALETTE:
  294. return BrandingQueryNewPalete(hDlg);
  295. case WM_PALETTECHANGED:
  296. return BrandingPaletteChanged(hDlg, (HWND)wParam);
  297. }
  298. // We didn't process the message
  299. return(FALSE);
  300. }
  301. /****************************************************************************
  302. FUNCTION: OptionsDlgInit
  303. PURPOSE: Handles initialization of security options dialog
  304. RETURNS: TRUE on success, FALSE on failure
  305. ****************************************************************************/
  306. BOOL OptionsDlgInit(
  307. HWND hDlg)
  308. {
  309. PGLOBALS pGlobals = (PGLOBALS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  310. TCHAR Buffer1[MAX_STRING_BYTES];
  311. TCHAR Buffer2[MAX_STRING_BYTES];
  312. BOOL Result;
  313. DWORD dwValue, dwType;
  314. HKEY hkeyPolicy;
  315. DWORD cbData;
  316. HANDLE hImpersonateUser = NULL;
  317. USHORT Flags = FT_TIME|FT_DATE;
  318. LCID locale;
  319. SetWelcomeCaption( hDlg );
  320. //
  321. // Set the logon info text
  322. //
  323. if (pGlobals->Domain[0] == TEXT('\0') )
  324. {
  325. //
  326. // there is no domain name
  327. //
  328. if ( lstrlen(pGlobals->UserFullName) == 0)
  329. {
  330. //
  331. // There is no full name
  332. //
  333. LoadString(hDllInstance, IDS_LOGON_EMAIL_NAME_NFN_INFO, Buffer1, MAX_STRING_BYTES);
  334. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->UserName);
  335. }
  336. else
  337. {
  338. LoadString(hDllInstance, IDS_LOGON_EMAIL_NAME_INFO, Buffer1, MAX_STRING_BYTES);
  339. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1,
  340. pGlobals->UserFullName,
  341. pGlobals->UserName);
  342. }
  343. }
  344. else
  345. {
  346. if ( lstrlen(pGlobals->UserFullName) == 0)
  347. {
  348. //
  349. // There is no full name
  350. //
  351. LoadString(hDllInstance, IDS_LOGON_NAME_NFN_INFO, Buffer1, MAX_STRING_BYTES);
  352. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain,
  353. pGlobals->UserName);
  354. }
  355. else
  356. {
  357. LoadString(hDllInstance, IDS_LOGON_NAME_INFO, Buffer1, MAX_STRING_BYTES);
  358. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->UserFullName,
  359. pGlobals->Domain,
  360. pGlobals->UserName);
  361. }
  362. }
  363. SetDlgItemText(hDlg, IDD_OPTIONS_LOGON_NAME_INFO, Buffer2);
  364. //
  365. // Set the logon time/date - but do it as the logged on user
  366. //
  367. hImpersonateUser = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  368. locale = GetUserDefaultLCID();
  369. if (((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC)
  370. || (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW)))
  371. {
  372. // Get the real item windows ExStyle.
  373. HWND hWnd = GetDlgItem(hDlg, IDD_OPTIONS_LOGON_DATE);
  374. DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
  375. if ((BOOLIFY(dwExStyle & WS_EX_RTLREADING)) != (BOOLIFY(dwExStyle & WS_EX_LAYOUTRTL)))
  376. Flags |= FT_RTL;
  377. else
  378. Flags |= FT_LTR;
  379. }
  380. Result = FormatTime(&pGlobals->LogonTime, Buffer1, sizeof(Buffer1) / sizeof(Buffer1[0]), Flags);
  381. if (hImpersonateUser)
  382. {
  383. StopImpersonating(hImpersonateUser);
  384. }
  385. ASSERT(Result);
  386. SetDlgItemText(hDlg, IDD_OPTIONS_LOGON_DATE, Buffer1);
  387. //
  388. // Check if DisableLockWorkstation is set for the entire machine
  389. //
  390. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY,
  391. 0, KEY_READ, &hkeyPolicy) == ERROR_SUCCESS)
  392. {
  393. dwValue = 0;
  394. cbData = sizeof(dwValue);
  395. RegQueryValueEx(hkeyPolicy, DISABLE_LOCK_WKSTA,
  396. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  397. if (dwValue)
  398. {
  399. EnableDlgItem(hDlg, IDD_OPTIONS_LOCK, FALSE);
  400. }
  401. RegCloseKey(hkeyPolicy);
  402. }
  403. //
  404. // Smart card only users can't change the password
  405. //
  406. if (pGlobals->Profile && (pGlobals->Profile->UserFlags & UF_SMARTCARD_REQUIRED))
  407. {
  408. EnableDlgItem(hDlg, IDD_OPTIONS_CHANGEPWD, FALSE);
  409. }
  410. //
  411. // Check for policy and then disable corresponding options
  412. //
  413. if (OpenHKeyCurrentUser(pGlobals)) {
  414. if (RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser,
  415. WINLOGON_POLICY_KEY,
  416. 0, KEY_READ, &hkeyPolicy) == ERROR_SUCCESS)
  417. {
  418. dwValue = 0;
  419. cbData = sizeof(dwValue);
  420. RegQueryValueEx(hkeyPolicy, DISABLE_LOCK_WKSTA,
  421. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  422. if (dwValue)
  423. {
  424. EnableDlgItem(hDlg, IDD_OPTIONS_LOCK, FALSE);
  425. }
  426. dwValue = 0;
  427. cbData = sizeof(dwValue);
  428. RegQueryValueEx(hkeyPolicy, DISABLE_TASK_MGR,
  429. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  430. if (dwValue)
  431. {
  432. EnableDlgItem(hDlg, IDD_OPTIONS_TASKLIST, FALSE);
  433. ShowDlgItem(hDlg, IDD_OPTIONS_TASKMGR_TEXT, FALSE);
  434. }
  435. dwValue = 0;
  436. cbData = sizeof(dwValue);
  437. RegQueryValueEx(hkeyPolicy, DISABLE_CHANGE_PASSWORD,
  438. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  439. if (dwValue)
  440. {
  441. EnableDlgItem(hDlg, IDD_OPTIONS_CHANGEPWD, FALSE);
  442. }
  443. RegCloseKey(hkeyPolicy);
  444. }
  445. if (RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser, EXPLORER_POLICY_KEY,
  446. 0, KEY_READ, &hkeyPolicy) == ERROR_SUCCESS)
  447. {
  448. dwValue = 0;
  449. cbData = sizeof(dwValue);
  450. RegQueryValueEx(hkeyPolicy, NOLOGOFF,
  451. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  452. if (dwValue)
  453. {
  454. EnableDlgItem(hDlg, IDD_OPTIONS_LOGOFF, FALSE);
  455. }
  456. dwValue = 0;
  457. cbData = sizeof(dwValue);
  458. RegQueryValueEx(hkeyPolicy, NOCLOSE,
  459. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  460. //
  461. // If this is not the system console, check the appropriate key in registry
  462. //
  463. if ( !g_Console ) {
  464. if (!TestUserPrivilege(pGlobals->UserProcessData.UserToken, SE_SHUTDOWN_PRIVILEGE)) {
  465. RegQueryValueEx(hkeyPolicy, NODISCONNECT,
  466. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  467. }
  468. }
  469. if (dwValue)
  470. {
  471. EnableDlgItem(hDlg, IDD_OPTIONS_SHUTDOWN, FALSE);
  472. }
  473. RegCloseKey(hkeyPolicy);
  474. }
  475. CloseHKeyCurrentUser(pGlobals);
  476. }
  477. // Position ourselves nicely
  478. SizeForBranding(hDlg, FALSE);
  479. CentreWindow(hDlg);
  480. return TRUE;
  481. }
  482. /***************************************************************************\
  483. * FUNCTION: EndWindowsSessionDlgProc
  484. *
  485. * PURPOSE: Processes messages for Logging off Windows Nt confirmation dialog
  486. *
  487. * RETURNS: MSGINA_DLG_SUCCESS - The user wants to logoff.
  488. * MSGINA_DLG_FAILURE - The user doesn't want to logoff.
  489. * DLG_INTERRUPTED() - a set defined in winlogon.h
  490. *
  491. * HISTORY:
  492. *
  493. * 05-17-92 Davidc Created.
  494. *
  495. \***************************************************************************/
  496. INT_PTR WINAPI
  497. EndWindowsSessionDlgProc(
  498. HWND hDlg,
  499. UINT message,
  500. WPARAM wParam,
  501. LPARAM lParam
  502. )
  503. {
  504. switch (message)
  505. {
  506. case WM_INITDIALOG:
  507. {
  508. HICON hIcon;
  509. SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
  510. // Load the 48 x 48 version of the logoff icon
  511. hIcon = LoadImage (hDllInstance, MAKEINTRESOURCE(IDI_STLOGOFF),
  512. IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
  513. if (hIcon)
  514. {
  515. SendDlgItemMessage (hDlg, IDD_LOGOFFICON, STM_SETICON, (WPARAM) hIcon, 0);
  516. }
  517. // Position ourselves nicely
  518. CentreWindow(hDlg);
  519. }
  520. return(TRUE);
  521. case WLX_WM_SAS:
  522. //
  523. // If this is someone hitting C-A-D, swallow it.
  524. //
  525. if (wParam == WLX_SAS_TYPE_CTRL_ALT_DEL)
  526. {
  527. return(TRUE);
  528. }
  529. //
  530. // Other SAS's (like timeout), return FALSE and let winlogon
  531. // deal with it.
  532. //
  533. return(FALSE);
  534. case WM_COMMAND:
  535. switch (LOWORD(wParam))
  536. {
  537. case IDOK:
  538. EndDialog(hDlg, MSGINA_DLG_SUCCESS);
  539. return(TRUE);
  540. case IDCANCEL:
  541. EndDialog(hDlg, MSGINA_DLG_FAILURE);
  542. return(TRUE);
  543. }
  544. break;
  545. }
  546. // We didn't process the message
  547. return(FALSE);
  548. }