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.

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