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.

2362 lines
69 KiB

  1. //e+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: mslock.c
  7. //
  8. // Contents: Microsoft Logon GUI DLL
  9. //
  10. // History: 7-14-94 RichardW Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "msgina.h"
  14. #include <stdio.h>
  15. #include <wchar.h>
  16. #include "shlwapi.h"
  17. #include "shlwapip.h"
  18. #define WM_SMARTCARD_ASYNC_MESSAGE (WM_USER + 201)
  19. #define WM_SMARTCARD_ERROR_DISPLAY_1 (WM_USER + 202)
  20. #define WM_SMARTCARD_ERROR_DISPLAY_2 (WM_USER + 203)
  21. #define MSGINA_DLG_ASYNC_PROCESSING 122
  22. static UINT ctrlNoDomain[] =
  23. {
  24. IDOK,
  25. IDCANCEL,
  26. IDD_UNLOCK_OPTIONS,
  27. IDD_KBLAYOUT_ICON,
  28. };
  29. static UINT ctrlNoUserName[] =
  30. {
  31. IDD_UNLOCK_DOMAIN,
  32. IDD_UNLOCK_DOMAIN_LABEL,
  33. IDD_UNLOCK_PASSWORD,
  34. IDC_UNLOCK_PASSWORD_LABEL,
  35. IDOK,
  36. IDCANCEL,
  37. IDD_UNLOCK_OPTIONS,
  38. IDD_KBLAYOUT_ICON,
  39. };
  40. //
  41. // Define the structure used to pass data into the lock dialogs
  42. //
  43. typedef enum _LOCKED_STATE_DIALOGS {
  44. LockedDialog,
  45. PasswordDialog,
  46. PINDialog
  47. } LOCKED_STATE_DIALOGS ;
  48. typedef enum _ACTION_TAKEN {
  49. None,
  50. SmartCardInserted,
  51. SmartCardRemoved,
  52. CancelHit
  53. } ACTION_TAKEN ;
  54. typedef struct {
  55. PGLOBALS pGlobals;
  56. TIME LockTime;
  57. } LOCK_DATA;
  58. typedef LOCK_DATA *PLOCK_DATA;
  59. typedef struct _UNLOCK_DLG_STATE {
  60. PGLOBALS pGlobals ;
  61. DWORD dwSasType ;
  62. ACTION_TAKEN ActionTaken;
  63. BOOL fKillTimer;
  64. BOOL fUserBeingPrompted;
  65. BOOL fCardRemoved;
  66. } UNLOCK_DLG_STATE, * PUNLOCK_DLG_STATE ;
  67. typedef struct _ASYNC_UNLOCK_DATA {
  68. PGLOBALS pGlobals;
  69. HWND hDlg;
  70. PUNLOCK_DLG_STATE pUnlockDlgState;
  71. UNICODE_STRING UserName;
  72. UNICODE_STRING Domain;
  73. UNICODE_STRING Password;
  74. DWORD Reserved;
  75. } ASYNC_UNLOCK_DATA, * PASYNC_UNLOCK_DATA;
  76. typedef struct _UNLOCK_MESSAGE {
  77. NTSTATUS Status ;
  78. UINT Resource ;
  79. } UNLOCK_MESSAGE, * PUNLOCK_MESSAGE ;
  80. UNLOCK_MESSAGE UnlockMessages[] = {
  81. { STATUS_LOGON_FAILURE, IDS_UNLOCK_FAILED_BAD_PWD },
  82. { STATUS_INVALID_LOGON_HOURS, IDS_INVALID_LOGON_HOURS },
  83. { STATUS_INVALID_WORKSTATION, IDS_INVALID_WORKSTATION },
  84. { STATUS_ACCOUNT_DISABLED, IDS_ACCOUNT_DISABLED },
  85. { STATUS_NO_LOGON_SERVERS, IDS_LOGON_NO_DOMAIN },
  86. { STATUS_LOGON_TYPE_NOT_GRANTED, IDS_LOGON_TYPE_NOT_GRANTED },
  87. { STATUS_NO_TRUST_LSA_SECRET, IDS_NO_TRUST_LSA_SECRET },
  88. { STATUS_TRUSTED_DOMAIN_FAILURE, IDS_TRUSTED_DOMAIN_FAILURE },
  89. { STATUS_TRUSTED_RELATIONSHIP_FAILURE, IDS_TRUSTED_RELATIONSHIP_FAILURE },
  90. { STATUS_ACCOUNT_EXPIRED, IDS_ACCOUNT_EXPIRED },
  91. { STATUS_NETLOGON_NOT_STARTED, IDS_NETLOGON_NOT_STARTED },
  92. { STATUS_ACCOUNT_LOCKED_OUT, IDS_ACCOUNT_LOCKED },
  93. { STATUS_SMARTCARD_WRONG_PIN, IDS_STATUS_SMARTCARD_WRONG_PIN_UNLOCK },
  94. { STATUS_SMARTCARD_CARD_BLOCKED, IDS_STATUS_SMARTCARD_CARD_BLOCKED_UNLOCK },
  95. { STATUS_SMARTCARD_NO_CARD, IDS_STATUS_SMARTCARD_NO_CARD_UNLOCK },
  96. { STATUS_SMARTCARD_NO_KEY_CONTAINER, IDS_STATUS_SMARTCARD_NO_KEY_CONTAINER_UNLOCK },
  97. { STATUS_SMARTCARD_NO_CERTIFICATE, IDS_STATUS_SMARTCARD_NO_CERTIFICATE_UNLOCK },
  98. { STATUS_SMARTCARD_NO_KEYSET, IDS_STATUS_SMARTCARD_NO_KEYSET_UNLOCK },
  99. { STATUS_SMARTCARD_IO_ERROR, IDS_STATUS_SMARTCARD_IO_ERROR_UNLOCK },
  100. { STATUS_SMARTCARD_CERT_EXPIRED, IDS_STATUS_SMARTCARD_CERT_EXPIRED_UNLOCK },
  101. { STATUS_SMARTCARD_CERT_REVOKED, IDS_STATUS_SMARTCARD_CERT_REVOKED_UNLOCK },
  102. { STATUS_ISSUING_CA_UNTRUSTED, IDS_STATUS_ISSUING_CA_UNTRUSTED_UNLOCK },
  103. { STATUS_REVOCATION_OFFLINE_C, IDS_STATUS_REVOCATION_OFFLINE_C_UNLOCK },
  104. { STATUS_PKINIT_CLIENT_FAILURE, IDS_STATUS_PKINIT_CLIENT_FAILURE_UNLOCK }
  105. };
  106. //
  107. // Private prototypes
  108. //
  109. BOOL LockedDlgInit(HWND, PGLOBALS);
  110. BOOL UnlockDlgInit(HWND, PGLOBALS, DWORD SasType);
  111. INT_PTR AttemptUnlock(HWND, PGLOBALS, PUNLOCK_DLG_STATE);
  112. BOOL WINAPI LogoffWaitDlgProc(HWND, UINT, DWORD, LONG);
  113. VOID UnlockShowOptions(PGLOBALS pGlobals, HWND hDlg, BOOL fShow);
  114. VOID DisplaySmartCardUnlockErrMessage(PGLOBALS pGlobals, HWND hDlg, DWORD dwErrorType, NTSTATUS Status, INT_PTR *pResult);
  115. BOOL ValidateSC(PGLOBALS pGlobals);
  116. HICON hLockedIcon = NULL;
  117. HICON hUnlockIcon = NULL;
  118. // declared in mslogon.c
  119. LRESULT CALLBACK DisableEditSubClassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uiID, DWORD_PTR dwRefData);
  120. BOOL ReplacedPossibleDisplayName (WCHAR *pszUsername);
  121. void
  122. SetLockedInfo(
  123. PGLOBALS pGlobals,
  124. HWND hDlg,
  125. UINT ControlId)
  126. {
  127. TCHAR Buffer1[MAX_STRING_BYTES];
  128. TCHAR Buffer2[MAX_STRING_BYTES];
  129. //
  130. // Set the locked message
  131. //
  132. if ( pGlobals->Domain[0] == TEXT('\0') )
  133. {
  134. if (lstrlen(pGlobals->UserFullName) == 0) {
  135. //
  136. // There is no full name, so don't try to print one out
  137. //
  138. LoadString(hDllInstance, IDS_LOCKED_EMAIL_NFN_MESSAGE, Buffer1, MAX_STRING_BYTES);
  139. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->UserName );
  140. } else {
  141. LoadString(hDllInstance, IDS_LOCKED_EMAIL_MESSAGE, Buffer1, MAX_STRING_BYTES);
  142. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->UserName, pGlobals->UserFullName);
  143. }
  144. }
  145. else
  146. {
  147. if (lstrlen(pGlobals->UserFullName) == 0) {
  148. //
  149. // There is no full name, so don't try to print one out
  150. //
  151. LoadString(hDllInstance, IDS_LOCKED_NFN_MESSAGE, Buffer1, MAX_STRING_BYTES);
  152. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain, pGlobals->UserName );
  153. } else {
  154. LoadString(hDllInstance, IDS_LOCKED_MESSAGE, Buffer1, MAX_STRING_BYTES);
  155. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain, pGlobals->UserName, pGlobals->UserFullName);
  156. }
  157. }
  158. SetWindowText(GetDlgItem(hDlg, ControlId), Buffer2);
  159. }
  160. /***************************************************************************\
  161. * FUNCTION: LockedDlgProc
  162. *
  163. * PURPOSE: Processes messages for the workstation locked dialog
  164. *
  165. * RETURNS:
  166. * DLG_SUCCESS - the user pressed Ctrl-Alt-Del
  167. * DLG_LOGOFF() - the user was asynchronously logged off.
  168. * DLG_SCREEN_SAVER_TIMEOUT - the screen-saver should be started
  169. * DLG_FAILURE - the dialog could not be displayed.
  170. *
  171. * HISTORY:
  172. *
  173. * 12-09-91 Davidc Created.
  174. *
  175. \***************************************************************************/
  176. INT_PTR
  177. CALLBACK
  178. LockedDlgProc(
  179. HWND hDlg,
  180. UINT message,
  181. WPARAM wParam,
  182. LPARAM lParam
  183. )
  184. {
  185. PGLOBALS pGlobals = (PGLOBALS) GetWindowLongPtr( hDlg, GWLP_USERDATA);
  186. switch (message)
  187. {
  188. case WM_INITDIALOG:
  189. SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
  190. pGlobals = (PGLOBALS) lParam ;
  191. if (GetDisableCad(pGlobals))
  192. {
  193. // Set our size to zero so we we don't appear
  194. SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE |
  195. SWP_NOREDRAW | SWP_NOZORDER);
  196. pWlxFuncs->WlxSasNotify( pGlobals->hGlobalWlx,
  197. WLX_SAS_TYPE_CTRL_ALT_DEL );
  198. }
  199. else
  200. {
  201. if (!LockedDlgInit(hDlg, pGlobals)) {
  202. EndDialog(hDlg, DLG_FAILURE);
  203. }
  204. }
  205. return(TRUE);
  206. case WLX_WM_SAS:
  207. if ( wParam != WLX_SAS_TYPE_SC_REMOVE &&
  208. wParam != WLX_SAS_TYPE_SC_FIRST_READER_ARRIVED &&
  209. wParam != WLX_SAS_TYPE_SC_LAST_READER_REMOVED )
  210. {
  211. EndDialog(hDlg, MSGINA_DLG_SUCCESS);
  212. }
  213. return(TRUE);
  214. case WM_ERASEBKGND:
  215. return PaintBranding(hDlg, (HDC)wParam, 0, FALSE, FALSE, COLOR_BTNFACE);
  216. case WM_QUERYNEWPALETTE:
  217. return BrandingQueryNewPalete(hDlg);
  218. case WM_PALETTECHANGED:
  219. return BrandingPaletteChanged(hDlg, (HWND)wParam);
  220. }
  221. // We didn't process this message
  222. return FALSE;
  223. }
  224. /***************************************************************************\
  225. * FUNCTION: LockedDlgInit
  226. *
  227. * PURPOSE: Handles initialization of locked workstation dialog
  228. *
  229. * RETURNS: TRUE on success, FALSE on failure
  230. *
  231. * HISTORY:
  232. *
  233. * 12-09-91 Davidc Created.
  234. *
  235. \***************************************************************************/
  236. BOOL
  237. LockedDlgInit(
  238. HWND hDlg,
  239. PGLOBALS pGlobals
  240. )
  241. {
  242. ULONG_PTR Value;
  243. SetWelcomeCaption(hDlg);
  244. SetLockedInfo(pGlobals, hDlg, IDD_LOCKED_NAME_INFO);
  245. SetupSystemMenu(hDlg);
  246. // Size for the branding image we are going to add.
  247. SizeForBranding(hDlg, FALSE);
  248. if ( !hLockedIcon )
  249. {
  250. hLockedIcon = LoadImage( hDllInstance,
  251. MAKEINTRESOURCE( IDI_LOCKED),
  252. IMAGE_ICON,
  253. 0, 0,
  254. LR_DEFAULTCOLOR );
  255. }
  256. SendMessage( GetDlgItem(hDlg, IDD_LOCKED_ICON),
  257. STM_SETICON,
  258. (WPARAM)hLockedIcon,
  259. 0 );
  260. // Stop filtering SC events so SC unlock works
  261. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  262. WLX_OPTION_USE_SMART_CARD,
  263. 1,
  264. NULL
  265. );
  266. //
  267. // is this a smartcard gina?
  268. //
  269. pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
  270. WLX_OPTION_SMART_CARD_PRESENT,
  271. &Value
  272. );
  273. if ( Value )
  274. {
  275. TCHAR szInsertCard[256];
  276. szInsertCard[0] = 0;
  277. // Also change unlock message to mention smartcard
  278. LoadString(hDllInstance, IDS_INSERTCARDORSAS_UNLOCK, szInsertCard, ARRAYSIZE(szInsertCard));
  279. SetDlgItemText(hDlg, IDD_LOCKED_INSTRUCTIONS, szInsertCard);
  280. }
  281. CentreWindow(hDlg);
  282. return TRUE;
  283. }
  284. //+---------------------------------------------------------------------------
  285. //
  286. // Function: WlxDisplayLockedNotice
  287. //
  288. // Synopsis:
  289. //
  290. // Effects:
  291. //
  292. // Arguments: [pWlxContext] --
  293. //
  294. // Requires:
  295. //
  296. // Returns:
  297. //
  298. // Signals:
  299. //
  300. // Modifies:
  301. //
  302. // Algorithm:
  303. //
  304. // History: 6-16-98 RichardW Created
  305. //
  306. // Notes:
  307. //
  308. //----------------------------------------------------------------------------
  309. VOID
  310. WINAPI
  311. WlxDisplayLockedNotice(
  312. PVOID pWlxContext
  313. )
  314. {
  315. PGLOBALS pGlobals;
  316. pGlobals = (PGLOBALS) pWlxContext;
  317. GetSystemTimeAsFileTime( (LPFILETIME) &pGlobals->LockTime);
  318. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx, LOGON_TIMEOUT);
  319. pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  320. hDllInstance,
  321. (LPWSTR) MAKEINTRESOURCE(IDD_LOCKED_DIALOG),
  322. NULL,
  323. LockedDlgProc,
  324. (LPARAM) pGlobals );
  325. }
  326. BOOL
  327. SmartCardInsterted(
  328. PGLOBALS pGlobals)
  329. {
  330. PWLX_SC_NOTIFICATION_INFO ScInfo = NULL ;
  331. pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
  332. WLX_OPTION_SMART_CARD_INFO,
  333. (ULONG_PTR *) &ScInfo );
  334. if ( ScInfo )
  335. {
  336. LocalFree(ScInfo);
  337. return (TRUE);
  338. }
  339. else
  340. {
  341. return (FALSE);
  342. }
  343. }
  344. int
  345. WINAPI
  346. WlxWkstaLockedSAS(
  347. PVOID pWlxContext,
  348. DWORD dwSasType
  349. )
  350. {
  351. PGLOBALS pGlobals;
  352. DWORD Result;
  353. UNLOCK_DLG_STATE UnlockDlgState ;
  354. BOOL fContinue = FALSE;
  355. LOCKED_STATE_DIALOGS PreviousState;
  356. LOCKED_STATE_DIALOGS CurrentState;
  357. pGlobals = (PGLOBALS) pWlxContext;
  358. UnlockDlgState.pGlobals = pGlobals ;
  359. UnlockDlgState.dwSasType = dwSasType ;
  360. UnlockDlgState.ActionTaken = None ;
  361. //
  362. // Set the previous state based on whether CAD is disabled, and
  363. // the current SAS type
  364. //
  365. if (GetDisableCad(pGlobals))
  366. {
  367. PreviousState = PasswordDialog;
  368. //
  369. // If the CAD is disabled, then go directly to the PIN dialog
  370. //
  371. if (SmartCardInsterted(pGlobals))
  372. {
  373. UnlockDlgState.dwSasType = WLX_SAS_TYPE_SC_INSERT;
  374. CurrentState = PINDialog;
  375. }
  376. else
  377. {
  378. CurrentState = PasswordDialog;
  379. }
  380. }
  381. else
  382. {
  383. PreviousState = LockedDialog;
  384. //
  385. // Set the current state based on the SAS we are receiving
  386. //
  387. if (dwSasType == WLX_SAS_TYPE_SC_INSERT)
  388. {
  389. CurrentState = PINDialog;
  390. }
  391. else
  392. {
  393. CurrentState = PasswordDialog;
  394. }
  395. }
  396. do
  397. {
  398. UnlockDlgState.ActionTaken = None;
  399. fContinue = FALSE;
  400. Result = pWlxFuncs->WlxDialogBoxParam(
  401. pGlobals->hGlobalWlx,
  402. hDllInstance,
  403. MAKEINTRESOURCE(IDD_UNLOCK_DIALOG),
  404. NULL,
  405. (DLGPROC) UnlockDlgProc,
  406. (LPARAM) &UnlockDlgState );
  407. //
  408. // Make a transition based on the current dialog
  409. // (the one that has just ended)
  410. //
  411. switch (CurrentState)
  412. {
  413. case PasswordDialog:
  414. //
  415. // If the password dialog was just being displayed
  416. // and a smartcard was inserted, then loop back
  417. // and display the PIN dialog, otherwise, if the
  418. // password dialog was dismissed for any other reason,
  419. // then get out.
  420. //
  421. if (UnlockDlgState.ActionTaken == SmartCardInserted)
  422. {
  423. PreviousState = PasswordDialog;
  424. CurrentState = PINDialog;
  425. UnlockDlgState.dwSasType = WLX_SAS_TYPE_SC_INSERT; // go to PIN dlg
  426. fContinue = TRUE;
  427. }
  428. break;
  429. case PINDialog:
  430. //
  431. // If the PIN dialog was just being displayed
  432. // and a smartcard was removed or cancel was hit, AND
  433. // the dialog that was displayed before this was the
  434. // password dialog, then loop back and display the
  435. // password dialog again, otherwise, if the PIN dialog
  436. // was dismissed for any other reason, then get out.
  437. //
  438. if ((UnlockDlgState.ActionTaken == SmartCardRemoved) ||
  439. (UnlockDlgState.ActionTaken == CancelHit))
  440. {
  441. if (PreviousState == PasswordDialog)
  442. {
  443. CurrentState = PasswordDialog;
  444. UnlockDlgState.dwSasType = WLX_SAS_TYPE_CTRL_ALT_DEL; // go to PWD Dlg
  445. fContinue = TRUE;
  446. }
  447. }
  448. break;
  449. }
  450. } while (fContinue);
  451. switch (Result)
  452. {
  453. case MSGINA_DLG_SUCCESS:
  454. if ( (pGlobals->SmartCardOption == 0) ||
  455. (!pGlobals->SmartCardLogon)
  456. )
  457. {
  458. // As no action will be taken on SC removal, we can filter these events
  459. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  460. WLX_OPTION_USE_SMART_CARD,
  461. 0,
  462. NULL );
  463. }
  464. CheckPasswordExpiry( pGlobals, FALSE );
  465. return(WLX_SAS_ACTION_UNLOCK_WKSTA);
  466. case MSGINA_DLG_FAILURE:
  467. case WLX_DLG_INPUT_TIMEOUT:
  468. case WLX_DLG_SCREEN_SAVER_TIMEOUT:
  469. return(WLX_SAS_ACTION_NONE);
  470. case WLX_DLG_USER_LOGOFF:
  471. return(WLX_SAS_ACTION_LOGOFF);
  472. case MSGINA_DLG_FORCE_LOGOFF:
  473. return(WLX_SAS_ACTION_FORCE_LOGOFF);
  474. default:
  475. DebugLog((DEB_WARN, "Unexpected return code from UnlockDlgProc, %d\n", Result));
  476. return(WLX_SAS_ACTION_NONE);
  477. }
  478. }
  479. BOOL
  480. ValidateSC(
  481. PGLOBALS pGlobals)
  482. {
  483. PWLX_SC_NOTIFICATION_INFO ScInfo = NULL ;
  484. pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
  485. WLX_OPTION_SMART_CARD_INFO,
  486. (ULONG_PTR *) &ScInfo );
  487. //
  488. // Validate the SC info against some common user
  489. // errors before the PIN dialog appears
  490. //
  491. if ( ScInfo )
  492. {
  493. if ( ( ScInfo->pszReader ) &&
  494. ( ScInfo->pszCard == NULL ) )
  495. {
  496. //
  497. // The card could not be read. Might not be
  498. // inserted correctly.
  499. //
  500. LocalFree(ScInfo);
  501. TimeoutMessageBox( NULL, pGlobals, IDS_CARD_NOT_RECOGNIZED,
  502. IDS_LOGON_MESSAGE,
  503. MB_OK | MB_ICONEXCLAMATION,
  504. LOGON_TIMEOUT );
  505. return FALSE;
  506. }
  507. if ( ( ScInfo->pszReader ) &&
  508. ( ScInfo->pszCryptoProvider == NULL ) )
  509. {
  510. //
  511. // Got a card, but the CSP for it could not be
  512. // found.
  513. //
  514. LocalFree(ScInfo);
  515. TimeoutMessageBox( NULL, pGlobals, IDS_CARD_CSP_NOT_RECOGNIZED,
  516. IDS_LOGON_MESSAGE,
  517. MB_OK | MB_ICONEXCLAMATION,
  518. LOGON_TIMEOUT );
  519. return FALSE;
  520. }
  521. LocalFree(ScInfo);
  522. }
  523. return TRUE;
  524. }
  525. /***************************************************************************\
  526. * FUNCTION: UnlockDlgProc
  527. *
  528. * PURPOSE: Processes messages for the workstation unlock dialog
  529. *
  530. * RETURNS:
  531. * DLG_SUCCESS - the user unlocked the workstation successfully.
  532. * DLG_FAILURE - the user failed to unlock the workstation.
  533. * DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
  534. *
  535. * HISTORY:
  536. *
  537. * 12-09-91 Davidc Created.
  538. *
  539. \***************************************************************************/
  540. static UINT ctrlNoCancel[] =
  541. {
  542. IDOK,
  543. };
  544. INT_PTR
  545. CALLBACK
  546. UnlockDlgProc(
  547. HWND hDlg,
  548. UINT message,
  549. WPARAM wParam,
  550. LPARAM lParam
  551. )
  552. {
  553. PGLOBALS pGlobals = NULL;
  554. INT_PTR Result;
  555. PUNLOCK_DLG_STATE pUnlockDlgState;
  556. pUnlockDlgState = (PUNLOCK_DLG_STATE) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  557. if (message != WM_INITDIALOG)
  558. {
  559. pGlobals = pUnlockDlgState->pGlobals;
  560. }
  561. switch (message)
  562. {
  563. case WM_INITDIALOG:
  564. pUnlockDlgState = (PUNLOCK_DLG_STATE) lParam ;
  565. // Screen saver will run if set to expire >= 2 minutes
  566. pWlxFuncs->WlxSetTimeout(pUnlockDlgState->pGlobals->hGlobalWlx,
  567. (GetDisableCad(pUnlockDlgState->pGlobals) ? TIMEOUT_NONE : LOGON_TIMEOUT) );
  568. // Limit the maximum password length to 127
  569. SendDlgItemMessage(hDlg, IDD_UNLOCK_PASSWORD, EM_SETLIMITTEXT, (WPARAM) 127, 0);
  570. SetWindowLongPtr(hDlg, GWLP_USERDATA, (ULONG_PTR) pUnlockDlgState );
  571. //
  572. // If this is an sc insert, then make sure the card is inserted correctly.
  573. //
  574. if ( pUnlockDlgState->dwSasType == WLX_SAS_TYPE_SC_INSERT )
  575. {
  576. if (!ValidateSC( pUnlockDlgState->pGlobals ))
  577. {
  578. EndDialog(hDlg, DLG_FAILURE);
  579. }
  580. }
  581. if (!UnlockDlgInit(hDlg, pUnlockDlgState->pGlobals, pUnlockDlgState->dwSasType ))
  582. {
  583. EndDialog(hDlg, DLG_FAILURE);
  584. }
  585. // Disable edits in username / password box
  586. SetWindowSubclass(GetDlgItem(hDlg, IDD_UNLOCK_NAME) , DisableEditSubClassProc, IDD_UNLOCK_NAME , 0);
  587. SetWindowSubclass(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), DisableEditSubClassProc, IDD_UNLOCK_PASSWORD, 0);
  588. return(SetPasswordFocus(hDlg));
  589. case WM_ERASEBKGND:
  590. return PaintBranding(hDlg, (HDC)wParam, 0, FALSE, FALSE, COLOR_BTNFACE);
  591. case WM_QUERYNEWPALETTE:
  592. return BrandingQueryNewPalete(hDlg);
  593. case WM_PALETTECHANGED:
  594. return BrandingPaletteChanged(hDlg, (HWND)wParam);
  595. case WM_COMMAND:
  596. switch (LOWORD(wParam))
  597. {
  598. case IDD_UNLOCK_NAME:
  599. switch (HIWORD(wParam))
  600. {
  601. case EN_CHANGE:
  602. // Ensure the domain box is enabled/disabled correctly
  603. // in case of a UPN name
  604. EnableDomainForUPN((HWND) lParam, GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN));
  605. return TRUE;
  606. default:
  607. break;
  608. }
  609. break;
  610. case IDCANCEL:
  611. pUnlockDlgState->ActionTaken = CancelHit;
  612. EndDialog(hDlg, DLG_FAILURE);
  613. return TRUE;
  614. case IDOK:
  615. //
  616. // Deal with combo-box UI requirements
  617. //
  618. if (HandleComboBoxOK(hDlg, IDD_UNLOCK_DOMAIN))
  619. {
  620. return(TRUE);
  621. }
  622. Result = AttemptUnlock(hDlg, pGlobals, pUnlockDlgState);
  623. if (Result != MSGINA_DLG_ASYNC_PROCESSING)
  624. {
  625. //
  626. // If they failed, let them try again, otherwise get out.
  627. //
  628. if (Result != DLG_FAILURE)
  629. {
  630. EndDialog(hDlg, Result);
  631. }
  632. // Clear the password field
  633. SetDlgItemText(hDlg, IDD_UNLOCK_PASSWORD, NULL);
  634. SetPasswordFocus(hDlg);
  635. }
  636. else
  637. {
  638. //
  639. // Let the async thread do the work, then it will send a
  640. // WM_SMARTCARD_ASYNC_MESSAGE message when it is done.
  641. // Meanwhile, disable controls so they don't get mucked with
  642. //
  643. EnableWindow( GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), FALSE );
  644. EnableWindow( GetDlgItem(hDlg, IDOK), FALSE );
  645. EnableWindow( GetDlgItem(hDlg, IDCANCEL), FALSE );
  646. EnableWindow( GetDlgItem(hDlg, IDC_UNLOCK_PASSWORD_LABEL), FALSE );
  647. }
  648. return TRUE;
  649. case IDD_UNLOCK_OPTIONS:
  650. UnlockShowOptions(pGlobals, hDlg, !pGlobals->UnlockOptionsShown);
  651. return TRUE;
  652. }
  653. break;
  654. case WM_SMARTCARD_ASYNC_MESSAGE:
  655. switch (wParam)
  656. {
  657. case MSGINA_DLG_SUCCESS:
  658. EndDialog(hDlg, MSGINA_DLG_SUCCESS);
  659. break;
  660. case MSGINA_DLG_FORCE_LOGOFF:
  661. EndDialog(hDlg, MSGINA_DLG_FORCE_LOGOFF);
  662. break;
  663. case MSGINA_DLG_FAILURE:
  664. EnableWindow( GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), TRUE );
  665. EnableWindow( GetDlgItem(hDlg, IDOK), TRUE );
  666. EnableWindow( GetDlgItem(hDlg, IDCANCEL), TRUE );
  667. EnableWindow( GetDlgItem(hDlg, IDC_UNLOCK_PASSWORD_LABEL), TRUE );
  668. // Clear the password field
  669. SetDlgItemText(hDlg, IDD_UNLOCK_PASSWORD, NULL);
  670. SetPasswordFocus(hDlg);
  671. break;
  672. }
  673. break;
  674. case WM_SMARTCARD_ERROR_DISPLAY_1:
  675. DisplaySmartCardUnlockErrMessage(pGlobals, hDlg, 1, (NTSTATUS) wParam, (INT_PTR *) lParam);
  676. return (TRUE);
  677. break;
  678. case WM_SMARTCARD_ERROR_DISPLAY_2:
  679. DisplaySmartCardUnlockErrMessage(pGlobals, hDlg, 2, (NTSTATUS) wParam, (INT_PTR *) lParam);
  680. return (TRUE);
  681. break;
  682. case WLX_WM_SAS:
  683. // Ignore it
  684. if ( wParam == WLX_SAS_TYPE_CTRL_ALT_DEL )
  685. {
  686. return( TRUE );
  687. }
  688. //
  689. // If we are in the middle of a smart card unlock then...
  690. //
  691. if ( pGlobals->LogonInProgress )
  692. {
  693. //
  694. // SC_REMOVE is really the only interesting SAS, if we get it,
  695. // kill the dialog.
  696. //
  697. if ( wParam == WLX_SAS_TYPE_SC_REMOVE )
  698. {
  699. //
  700. // If the card removal happened while the user is being
  701. // prompted for a yes/no question, then just note that
  702. // we got the removal and deal with it after the questions
  703. // is answered.
  704. //
  705. // Otherwise, kill the dialog
  706. //
  707. if ( pUnlockDlgState->fUserBeingPrompted )
  708. {
  709. pUnlockDlgState->fCardRemoved = TRUE;
  710. ShowWindow(hDlg, SW_HIDE);
  711. }
  712. else
  713. {
  714. pUnlockDlgState->ActionTaken = SmartCardRemoved;
  715. EndDialog(hDlg, DLG_FAILURE);
  716. }
  717. }
  718. return( TRUE );
  719. }
  720. //
  721. // If this is an insert and we are in the password state, then
  722. // go to the PIN state
  723. //
  724. if ( ( wParam == WLX_SAS_TYPE_SC_INSERT ) &&
  725. ( IsWindowVisible( GetDlgItem( hDlg, IDD_UNLOCK_OPTIONS ) ) == TRUE ) )
  726. {
  727. //
  728. // Check for some common SC problems before ending the dialog and
  729. // going to the PIN state
  730. //
  731. if ( !ValidateSC( pGlobals ) )
  732. {
  733. return( TRUE );
  734. }
  735. pUnlockDlgState->ActionTaken = SmartCardInserted;
  736. EndDialog(hDlg, DLG_FAILURE);
  737. }
  738. //
  739. // if this is a smart card unlock, if it is removed, kill the dialog.
  740. //
  741. if ( ( wParam == WLX_SAS_TYPE_SC_REMOVE ) &&
  742. ( IsWindowVisible( GetDlgItem( hDlg, IDD_UNLOCK_OPTIONS ) ) == FALSE ) )
  743. {
  744. pUnlockDlgState->ActionTaken = SmartCardRemoved;
  745. EndDialog(hDlg, DLG_FAILURE);
  746. }
  747. else if(wParam == WLX_SAS_TYPE_SC_REMOVE)
  748. {
  749. //
  750. // Already in the password dialog
  751. //
  752. return ( TRUE );
  753. }
  754. if ( wParam == WLX_SAS_TYPE_AUTHENTICATED ) {
  755. EndDialog( hDlg, MSGINA_DLG_SUCCESS );
  756. return TRUE;
  757. } else if ( wParam == WLX_SAS_TYPE_USER_LOGOFF ) {
  758. EndDialog( hDlg, MSGINA_DLG_USER_LOGOFF );
  759. return TRUE;
  760. }
  761. return( FALSE );
  762. case WM_CLOSE:
  763. break;
  764. case WM_DESTROY:
  765. FreeLayoutInfo (LAYOUT_CUR_USER);
  766. if ( pGlobals->ActiveArray )
  767. {
  768. DCacheFreeArray( pGlobals->ActiveArray );
  769. pGlobals->ActiveArray = NULL ;
  770. }
  771. RemoveWindowSubclass(GetDlgItem(hDlg, IDD_UNLOCK_NAME), DisableEditSubClassProc, IDD_UNLOCK_NAME);
  772. RemoveWindowSubclass(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), DisableEditSubClassProc, IDD_UNLOCK_PASSWORD);
  773. break;
  774. case WM_TIMER:
  775. if ( wParam == 0 )
  776. {
  777. HDC hDC;
  778. RtlEnterCriticalSection(&pGlobals->csGlobals);
  779. if ( pGlobals->LogonInProgress )
  780. {
  781. if (pGlobals->cxBand != 0)
  782. {
  783. pGlobals->xBandOffset = (pGlobals->xBandOffset+5) % pGlobals->cxBand;
  784. }
  785. }
  786. if ( !pGlobals->LogonInProgress || pUnlockDlgState->fKillTimer )
  787. {
  788. pGlobals->xBandOffset = 0;
  789. KillTimer(hDlg, 0);
  790. //
  791. // Reset timeout to normal
  792. //
  793. pWlxFuncs->WlxSetTimeout(
  794. pGlobals->hGlobalWlx,
  795. (GetDisableCad(pGlobals) ? TIMEOUT_NONE : LOGON_TIMEOUT));
  796. }
  797. RtlLeaveCriticalSection(&pGlobals->csGlobals);
  798. hDC = GetDC(hDlg);
  799. if ( hDC )
  800. {
  801. PaintBranding( hDlg, hDC, pGlobals->xBandOffset, TRUE, FALSE, COLOR_BTNFACE );
  802. ReleaseDC( hDlg, hDC );
  803. }
  804. return FALSE;
  805. }
  806. else if ( wParam == TIMER_MYLANGUAGECHECK )
  807. {
  808. LayoutCheckHandler(hDlg, LAYOUT_CUR_USER);
  809. }
  810. break;
  811. }
  812. // We didn't process the message
  813. return(FALSE);
  814. }
  815. /***************************************************************************\
  816. * FUNCTION: UnlockDlgInit
  817. *
  818. * PURPOSE: Handles initialization of security options dialog
  819. *
  820. * RETURNS: TRUE on success, FALSE on failure
  821. *
  822. * HISTORY:
  823. *
  824. * 12-09-91 Davidc Created.
  825. *
  826. \***************************************************************************/
  827. static UINT ctrlNoOptions[] =
  828. {
  829. IDOK,
  830. IDCANCEL,
  831. IDD_KBLAYOUT_ICON,
  832. };
  833. BOOL
  834. UnlockDlgInit(
  835. HWND hDlg,
  836. PGLOBALS pGlobals,
  837. DWORD SasType
  838. )
  839. {
  840. RECT rc, rc2;
  841. WCHAR Label[ MAX_PATH ];
  842. int err ;
  843. DWORD dwSize ;
  844. DWORD dwType ;
  845. DWORD dwValue ;
  846. dwSize = sizeof( DWORD );
  847. dwValue = 0 ;
  848. err = RegQueryValueEx( WinlogonKey,
  849. FORCE_UNLOCK_LOGON,
  850. 0,
  851. &dwType,
  852. (PBYTE) &dwValue,
  853. &dwSize );
  854. if ( err || ( dwType != REG_DWORD ) )
  855. {
  856. dwValue = 0 ;
  857. }
  858. if ( dwValue )
  859. {
  860. pGlobals->UnlockBehavior |= UNLOCK_FORCE_AUTHENTICATION ;
  861. }
  862. else
  863. {
  864. pGlobals->UnlockBehavior &= ~(UNLOCK_FORCE_AUTHENTICATION );
  865. }
  866. SetWelcomeCaption( hDlg );
  867. SetLockedInfo( pGlobals, hDlg, IDD_UNLOCK_NAME_INFO );
  868. if ( !hLockedIcon )
  869. {
  870. hLockedIcon = LoadImage( hDllInstance,
  871. MAKEINTRESOURCE( IDI_LOCKED),
  872. IMAGE_ICON,
  873. 0, 0,
  874. LR_DEFAULTCOLOR );
  875. }
  876. SendMessage( GetDlgItem( hDlg, IDD_UNLOCK_ICON),
  877. STM_SETICON,
  878. (WPARAM)hLockedIcon,
  879. 0 );
  880. DisplayLanguageIcon (hDlg, LAYOUT_CUR_USER, GetKeyboardLayout(0));
  881. // Size for the branding image we are going to add.
  882. SizeForBranding(hDlg, FALSE);
  883. pGlobals->xBandOffset = 0;
  884. //
  885. // Fill in the username
  886. //
  887. if ( SasType == WLX_SAS_TYPE_SC_INSERT )
  888. {
  889. RECT rc = {0};
  890. RECT rc2 = {0};
  891. //
  892. // No username, hide the field and move other controls up
  893. //
  894. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_MESSAGE), &rc);
  895. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), &rc2);
  896. MoveControls(hDlg, ctrlNoUserName,
  897. sizeof(ctrlNoUserName)/sizeof(ctrlNoUserName[0]),
  898. 0, -(rc2.top-rc.top),
  899. TRUE);
  900. // Hide the unnecessary text for SC insert
  901. ShowDlgItem( hDlg, IDD_UNLOCK_MESSAGE, FALSE);
  902. ShowDlgItem( hDlg, IDD_UNLOCK_NAME_INFO, FALSE);
  903. // Also remove the unlock icon; when the dialog gets this small, there
  904. // isn't room for this guy and the kblayout icon.
  905. ShowDlgItem( hDlg, IDD_UNLOCK_ICON, FALSE);
  906. ShowDlgItem( hDlg, IDD_UNLOCK_NAME, FALSE );
  907. EnableWindow( GetDlgItem(hDlg, IDD_UNLOCK_NAME), FALSE );
  908. ShowDlgItem( hDlg, IDC_UNLOCK_NAME_LABEL, FALSE );
  909. // Disable and hide domain
  910. ShowDlgItem( hDlg, IDD_UNLOCK_DOMAIN, FALSE );
  911. EnableWindow( GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN), FALSE);
  912. ShowDlgItem( hDlg, IDD_UNLOCK_DOMAIN_LABEL, FALSE);
  913. LoadString(hDllInstance, IDS_PIN, Label, MAX_PATH);
  914. SetDlgItemText( hDlg, IDC_UNLOCK_PASSWORD_LABEL, Label );
  915. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), &rc);
  916. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN), &rc2);
  917. MoveControls(hDlg, ctrlNoDomain,
  918. ARRAYSIZE(ctrlNoDomain),
  919. 0, -(rc2.bottom-rc.bottom),
  920. TRUE);
  921. pGlobals->ShowDomainBox = FALSE;
  922. //
  923. // The options button is useless, remove it
  924. //
  925. GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rc);
  926. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_OPTIONS), &rc2);
  927. MoveControls(hDlg, ctrlNoOptions,
  928. sizeof(ctrlNoOptions)/sizeof(ctrlNoOptions[0]),
  929. rc2.right-rc.right, 0,
  930. FALSE);
  931. ShowDlgItem(hDlg, IDD_UNLOCK_OPTIONS, FALSE);
  932. // Stop filtering SC events so SC unlock works
  933. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  934. WLX_OPTION_USE_SMART_CARD,
  935. 1,
  936. NULL
  937. );
  938. }
  939. else if (ForceNoDomainUI())
  940. {
  941. RECT rc = {0};
  942. RECT rc2 = {0};
  943. // Populate username
  944. SetDlgItemText(hDlg, IDD_UNLOCK_NAME, pGlobals->UserName);
  945. // Disable and hide domain
  946. ShowDlgItem( hDlg, IDD_UNLOCK_DOMAIN, FALSE );
  947. EnableWindow( GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN), FALSE);
  948. ShowDlgItem( hDlg, IDD_UNLOCK_DOMAIN_LABEL, FALSE);
  949. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), &rc);
  950. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN), &rc2);
  951. MoveControls(hDlg, ctrlNoDomain,
  952. ARRAYSIZE(ctrlNoDomain),
  953. 0, -(rc2.bottom-rc.bottom),
  954. TRUE);
  955. pGlobals->ShowDomainBox = FALSE;
  956. }
  957. else
  958. {
  959. SetDlgItemText(hDlg, IDD_UNLOCK_NAME, pGlobals->UserName);
  960. pGlobals->ShowDomainBox = TRUE;
  961. // Stop filtering SC events so SC unlock works
  962. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  963. WLX_OPTION_USE_SMART_CARD,
  964. 1,
  965. NULL
  966. );
  967. }
  968. //
  969. // Get trusted domain list and select appropriate domain
  970. //
  971. if ( !DCacheValidateCache( pGlobals->Cache ) )
  972. {
  973. ASSERT( pGlobals->ActiveArray == NULL );
  974. DCacheUpdateMinimal( pGlobals->Cache,
  975. pGlobals->Domain,
  976. TRUE );
  977. }
  978. pGlobals->ActiveArray = DCacheCopyCacheArray( pGlobals->Cache );
  979. if ( pGlobals->ActiveArray )
  980. {
  981. DCachePopulateListBoxFromArray( pGlobals->ActiveArray,
  982. GetDlgItem( hDlg, IDD_UNLOCK_DOMAIN ),
  983. pGlobals->Domain );
  984. }
  985. else
  986. {
  987. EndDialog( hDlg, MSGINA_DLG_FAILURE );
  988. }
  989. #if 0
  990. //
  991. // Ensure that the domain the user logged on with is always in the
  992. // combo-box so even if the Lsa is in a bad way the user will always
  993. // be able to unlock the workstation. Don't do this if the user is logged
  994. // in locally or else we'll get TWO local machines in the list
  995. //
  996. cchComputer = ARRAYSIZE(szComputer);
  997. szComputer[0] = 0;
  998. GetComputerName(szComputer, &cchComputer);
  999. if ( pGlobals->Domain[0] && (0 != lstrcmpi(szComputer, pGlobals->Domain)))
  1000. {
  1001. HWND hwndDomain = GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN);
  1002. if (SendMessage(hwndDomain, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pGlobals->Domain) == CB_ERR)
  1003. {
  1004. DebugLog((DEB_ERROR, "Domain combo-box doesn't contain logged on domain, adding it manually for unlock\n"));
  1005. SendMessage(hwndDomain, CB_ADDSTRING, 0, (LPARAM)pGlobals->Domain);
  1006. }
  1007. }
  1008. #endif
  1009. //
  1010. // If we are not part fo the domain then lets rip out the domain field,
  1011. // and if we do that lets remove the options button.
  1012. //
  1013. if ( !IsMachineDomainMember() )
  1014. {
  1015. //
  1016. // If we're not part of a domain, make sure to hide the domain field
  1017. //
  1018. GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rc);
  1019. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_OPTIONS), &rc2);
  1020. MoveControls(hDlg, ctrlNoOptions,
  1021. sizeof(ctrlNoOptions)/sizeof(ctrlNoOptions[0]),
  1022. rc2.right-rc.right, 0,
  1023. FALSE);
  1024. ShowDlgItem(hDlg, IDD_UNLOCK_DOMAIN_LABEL, FALSE);
  1025. ShowDlgItem(hDlg, IDD_UNLOCK_DOMAIN, FALSE);
  1026. ShowDlgItem(hDlg, IDD_UNLOCK_OPTIONS, FALSE);
  1027. }
  1028. // remove the cancel button if no C-A-D required
  1029. // NOTE: if we are going to the PIN dialog we always need a cancel button
  1030. if ((GetDisableCad(pGlobals)) && (SasType != WLX_SAS_TYPE_SC_INSERT))
  1031. EnableDlgItem(hDlg, IDCANCEL, FALSE);
  1032. // Position window on screen
  1033. CentreWindow(hDlg);
  1034. // Hide the options pane
  1035. pGlobals->UnlockOptionsShown = TRUE;
  1036. UnlockShowOptions(pGlobals, hDlg, FALSE);
  1037. return TRUE;
  1038. }
  1039. VOID
  1040. DisplaySmartCardUnlockErrMessage(
  1041. PGLOBALS pGlobals,
  1042. HWND hDlg,
  1043. DWORD dwErrorType,
  1044. NTSTATUS Status,
  1045. INT_PTR *pResult)
  1046. {
  1047. int i;
  1048. UINT Resource = 0;
  1049. TCHAR Buffer1[MAX_STRING_BYTES];
  1050. TCHAR Buffer2[MAX_STRING_BYTES];
  1051. BOOL fStringFound = FALSE;
  1052. if ( dwErrorType == 1 )
  1053. {
  1054. *pResult = TimeoutMessageBox(hDlg,
  1055. pGlobals,
  1056. IDS_FORCE_LOGOFF_WARNING,
  1057. IDS_WINDOWS_MESSAGE,
  1058. MB_OKCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON2,
  1059. TIMEOUT_CURRENT);
  1060. return;
  1061. }
  1062. //
  1063. // At this point we need to display an error message, and the just
  1064. // relinquish control back to the unlock dialog thread
  1065. //
  1066. for ( i = 0 ;
  1067. i < sizeof( UnlockMessages ) / sizeof( UNLOCK_MESSAGE ) ;
  1068. i++ )
  1069. {
  1070. if ( UnlockMessages[i].Status == Status )
  1071. {
  1072. if (Status == STATUS_LOGON_FAILURE)
  1073. {
  1074. Resource = IDS_UNLOCK_FAILED_BAD_PIN ;
  1075. }
  1076. else
  1077. {
  1078. Resource = UnlockMessages[i].Resource ;
  1079. }
  1080. break;
  1081. }
  1082. }
  1083. if ( Resource != 0 )
  1084. {
  1085. if( Resource == IDS_LOGON_NO_DOMAIN )
  1086. {
  1087. // Need to build the domain name into the string.
  1088. LoadString(hDllInstance, Resource, Buffer1, MAX_STRING_BYTES);
  1089. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain);
  1090. }
  1091. else
  1092. {
  1093. LoadString(hDllInstance, Resource, Buffer2, MAX_STRING_BYTES);
  1094. }
  1095. fStringFound = TRUE;
  1096. }
  1097. if ( !fStringFound )
  1098. {
  1099. //
  1100. // They're not the logged on user and they're not an admin.
  1101. // Tell them they failed to unlock the workstation.
  1102. //
  1103. if ( lstrlen(pGlobals->UserFullName) == 0 )
  1104. {
  1105. if ( pGlobals->Domain[0] == L'\0' )
  1106. {
  1107. LoadString(hDllInstance, IDS_UNLOCK_FAILED_EMAIL_NFN, Buffer1, MAX_STRING_BYTES);
  1108. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1,
  1109. pGlobals->UserName
  1110. );
  1111. }
  1112. else
  1113. {
  1114. LoadString(hDllInstance, IDS_UNLOCK_FAILED_NFN, Buffer1, MAX_STRING_BYTES);
  1115. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain,
  1116. pGlobals->UserName
  1117. );
  1118. }
  1119. }
  1120. else
  1121. {
  1122. if ( pGlobals->Domain[0] == L'\0' )
  1123. {
  1124. LoadString(hDllInstance, IDS_UNLOCK_FAILED_EMAIL, Buffer1, MAX_STRING_BYTES);
  1125. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1,
  1126. pGlobals->UserName,
  1127. pGlobals->UserFullName
  1128. );
  1129. }
  1130. else
  1131. {
  1132. LoadString(hDllInstance, IDS_UNLOCK_FAILED, Buffer1, MAX_STRING_BYTES);
  1133. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain,
  1134. pGlobals->UserName,
  1135. pGlobals->UserFullName
  1136. );
  1137. }
  1138. }
  1139. }
  1140. LoadString(hDllInstance, IDS_WORKSTATION_LOCKED, Buffer1, MAX_STRING_BYTES);
  1141. *pResult = TimeoutMessageBoxlpstr(
  1142. hDlg,
  1143. pGlobals,
  1144. Buffer2,
  1145. Buffer1,
  1146. MB_OK | MB_ICONSTOP,
  1147. TIMEOUT_CURRENT);
  1148. }
  1149. //+---------------------------------------------------------------------------
  1150. //
  1151. // Function: SmartCardUnlockLogonThread
  1152. //
  1153. // Synopsis: Does the logon call in an async thread so that a pulsing bar
  1154. // can be shown in the UI.
  1155. //
  1156. // Arguments: [pData] --
  1157. //
  1158. // History:
  1159. //
  1160. // Notes:
  1161. //
  1162. //----------------------------------------------------------------------------
  1163. DWORD
  1164. WINAPI
  1165. SmartCardUnlockLogonThread(
  1166. PASYNC_UNLOCK_DATA pData)
  1167. {
  1168. INT_PTR Result;
  1169. BOOL IsLoggedOnUser;
  1170. BOOL IsAdmin;
  1171. NTSTATUS Status;
  1172. BOOL Unlocked;
  1173. PGLOBALS pGlobals = pData->pGlobals;
  1174. //
  1175. // Kick off the call to the LSA
  1176. //
  1177. Unlocked = UnlockLogon(
  1178. pData->pGlobals,
  1179. TRUE,
  1180. pData->UserName.Buffer,
  1181. pData->Domain.Buffer,
  1182. &pData->Password,
  1183. &Status,
  1184. &IsAdmin,
  1185. &IsLoggedOnUser,
  1186. NULL,
  1187. NULL );
  1188. //
  1189. // Logon thread is done running, so stop showing the pulsing bar
  1190. //
  1191. pData->pUnlockDlgState->fKillTimer = TRUE;
  1192. //
  1193. // Get rid of the PIN
  1194. //
  1195. RtlZeroMemory( pData->Password.Buffer, pData->Password.Length );
  1196. if ( Unlocked && IsLoggedOnUser )
  1197. {
  1198. pGlobals->SmartCardLogon = TRUE;
  1199. //
  1200. // Logon succeeded, so tell the main thread that
  1201. //
  1202. PostMessage( pData->hDlg, WM_SMARTCARD_ASYNC_MESSAGE, MSGINA_DLG_SUCCESS, 0 );
  1203. goto Return;
  1204. }
  1205. else if ( Unlocked && IsAdmin)
  1206. {
  1207. //
  1208. // This is an admin trying to logon over another user, so send a message to the
  1209. // main dialog so it can ask the user if they would like to continue
  1210. //
  1211. pData->pUnlockDlgState->fUserBeingPrompted = TRUE;
  1212. SendMessage( pData->hDlg, WM_SMARTCARD_ERROR_DISPLAY_1, Status, (LPARAM) &Result );
  1213. //
  1214. // If the smart card was removed while the user was being prompted, and
  1215. // the user elected not to logoff the current user, then just go back
  1216. // to the locked dialog
  1217. //
  1218. if ( (pData->pUnlockDlgState->fCardRemoved) && (Result != MSGINA_DLG_SUCCESS) )
  1219. {
  1220. //
  1221. // Simulate the "card removed" SAS
  1222. //
  1223. pGlobals->LogonInProgress = FALSE;
  1224. PostMessage( pData->hDlg, WLX_WM_SAS, WLX_SAS_TYPE_SC_REMOVE, (LPARAM) NULL );
  1225. }
  1226. else
  1227. {
  1228. //
  1229. // Post the result of the prompt back to the main thread and then get out of this thread
  1230. //
  1231. PostMessage(
  1232. pData->hDlg,
  1233. WM_SMARTCARD_ASYNC_MESSAGE,
  1234. (Result == MSGINA_DLG_SUCCESS) ? MSGINA_DLG_FORCE_LOGOFF : MSGINA_DLG_FAILURE,
  1235. Result );
  1236. }
  1237. goto Return;
  1238. }
  1239. //
  1240. // At this point an error occurred, so ask the main thread to display an error message,
  1241. //
  1242. SendMessage( pData->hDlg, WM_SMARTCARD_ERROR_DISPLAY_2, Status, (LPARAM) &Result );
  1243. if (DLG_INTERRUPTED(Result))
  1244. {
  1245. Result = SetInterruptFlag( MSGINA_DLG_FAILURE ) ;
  1246. }
  1247. //
  1248. // Let the main thread know that this thread is exiting
  1249. //
  1250. PostMessage( pData->hDlg, WM_SMARTCARD_ASYNC_MESSAGE, MSGINA_DLG_FAILURE, Result );
  1251. Return:
  1252. pGlobals->LogonInProgress = FALSE;
  1253. LocalFree( pData );
  1254. return( 0 );
  1255. }
  1256. //+---------------------------------------------------------------------------
  1257. //
  1258. // Function: UnlockLogonThread
  1259. //
  1260. // Synopsis: Does the logon call in an async thread so that the user
  1261. // unlock is faster.
  1262. //
  1263. // Arguments: [pData] --
  1264. //
  1265. // History: 7-03-96 RichardW Created
  1266. //
  1267. // Notes:
  1268. //
  1269. //----------------------------------------------------------------------------
  1270. DWORD
  1271. WINAPI
  1272. UnlockLogonThread(
  1273. PASYNC_UNLOCK_DATA pData)
  1274. {
  1275. BOOL Ignored ;
  1276. NTSTATUS Status ;
  1277. //
  1278. // Give everything a moment to switch back, restart, etc.
  1279. //
  1280. Sleep( 500 );
  1281. //
  1282. // Kick off the call to the LSA
  1283. //
  1284. UnlockLogon(
  1285. pData->pGlobals,
  1286. FALSE,
  1287. pData->UserName.Buffer,
  1288. pData->Domain.Buffer,
  1289. &pData->Password,
  1290. &Status,
  1291. &Ignored,
  1292. &Ignored,
  1293. NULL,
  1294. NULL );
  1295. //
  1296. // Get rid of the password, then free the parameters
  1297. //
  1298. RtlZeroMemory( pData->Password.Buffer, pData->Password.Length );
  1299. LocalFree( pData );
  1300. return( 0 );
  1301. }
  1302. //+---------------------------------------------------------------------------
  1303. //
  1304. // Function: UnlockLogonAsync
  1305. //
  1306. // Synopsis: Sets up the async thread so that
  1307. //
  1308. // Effects:
  1309. //
  1310. // Arguments: [pGlobals] --
  1311. // [UserName] --
  1312. // [Domain] --
  1313. // [PasswordString] --
  1314. //
  1315. // Requires:
  1316. //
  1317. // Returns:
  1318. //
  1319. // Signals:
  1320. //
  1321. // Modifies:
  1322. //
  1323. // Algorithm:
  1324. //
  1325. // History: 7-03-96 RichardW Created
  1326. //
  1327. // Notes:
  1328. //
  1329. //----------------------------------------------------------------------------
  1330. BOOL
  1331. UnlockLogonAsync(
  1332. IN PGLOBALS pGlobals,
  1333. IN PUNLOCK_DLG_STATE pUnlockDlgState,
  1334. IN PWCHAR UserName,
  1335. IN PWCHAR Domain,
  1336. IN PUNICODE_STRING PasswordString,
  1337. IN HWND hDlg,
  1338. IN BOOL SmartCardUnlock
  1339. )
  1340. {
  1341. DWORD UserLength;
  1342. DWORD DomainLength;
  1343. PASYNC_UNLOCK_DATA pData;
  1344. HANDLE Thread;
  1345. DWORD Tid;
  1346. UserLength = (DWORD) wcslen( UserName ) * sizeof(WCHAR);
  1347. DomainLength = (DWORD) wcslen( Domain ) * sizeof(WCHAR);
  1348. pData = LocalAlloc( LMEM_FIXED, sizeof( ASYNC_UNLOCK_DATA ) +
  1349. UserLength + DomainLength +
  1350. PasswordString->Length + 3 * sizeof(WCHAR) );
  1351. if ( !pData )
  1352. {
  1353. return FALSE;
  1354. }
  1355. pData->pGlobals = pGlobals;
  1356. pData->hDlg = hDlg;
  1357. pData->pUnlockDlgState = pUnlockDlgState;
  1358. pData->UserName.Length = (WORD)UserLength;
  1359. pData->UserName.MaximumLength = (WORD)(UserLength + sizeof(WCHAR));
  1360. pData->UserName.Buffer = (PWSTR) (pData + 1);
  1361. CopyMemory( pData->UserName.Buffer, UserName, UserLength + sizeof(WCHAR) );
  1362. pData->Domain.Length = (WORD)DomainLength;
  1363. pData->Domain.MaximumLength = (WORD)(DomainLength + sizeof(WCHAR));
  1364. pData->Domain.Buffer = pData->UserName.Buffer + (UserLength / 2) + 1;
  1365. CopyMemory( pData->Domain.Buffer, Domain, DomainLength + sizeof(WCHAR) );
  1366. pData->Password.Length = PasswordString->Length;
  1367. pData->Password.MaximumLength = PasswordString->Length + sizeof(WCHAR) ;
  1368. pData->Password.Buffer = pData->Domain.Buffer + (DomainLength / 2) + 1;
  1369. CopyMemory( pData->Password.Buffer,
  1370. PasswordString->Buffer,
  1371. PasswordString->Length + 2);
  1372. Thread = CreateThread( NULL,
  1373. 0,
  1374. SmartCardUnlock ? SmartCardUnlockLogonThread: UnlockLogonThread,
  1375. pData,
  1376. 0,
  1377. &Tid );
  1378. if ( Thread )
  1379. {
  1380. CloseHandle( Thread );
  1381. }
  1382. else
  1383. {
  1384. ZeroMemory( pData->Password.Buffer, pData->Password.Length );
  1385. LocalFree( pData );
  1386. return ( FALSE );
  1387. }
  1388. return ( TRUE );
  1389. }
  1390. /***************************************************************************\
  1391. * FUNCTION: AttemptUnlock
  1392. *
  1393. * PURPOSE: Tries to unlock the workstation using the current values in the
  1394. * unlock dialog controls
  1395. *
  1396. * RETURNS:
  1397. * DLG_SUCCESS - the user unlocked the workstation successfully.
  1398. * DLG_FAILURE - the user failed to unlock the workstation.
  1399. * DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
  1400. *
  1401. * HISTORY:
  1402. *
  1403. * 12-09-91 Davidc Created.
  1404. *
  1405. \***************************************************************************/
  1406. INT_PTR
  1407. AttemptUnlock(
  1408. HWND hDlg,
  1409. PGLOBALS pGlobals,
  1410. PUNLOCK_DLG_STATE pUnlockDlgState)
  1411. {
  1412. TCHAR UserName[MAX_STRING_BYTES];
  1413. TCHAR Domain[MAX_STRING_BYTES];
  1414. TCHAR Password[MAX_STRING_BYTES];
  1415. UCHAR PasswordHash[ PASSWORD_HASH_SIZE ];
  1416. BOOL Unlocked;
  1417. BOOL DifferentAccount;
  1418. INT_PTR Result;
  1419. UNICODE_STRING PasswordString;
  1420. TCHAR Buffer1[MAX_STRING_BYTES];
  1421. TCHAR Buffer2[MAX_STRING_BYTES];
  1422. UCHAR IgnoreSeed;
  1423. DWORD StringSize;
  1424. BOOL SmartCardUnlock ;
  1425. BOOL IsAdmin = FALSE;
  1426. BOOL IsLoggedOnUser ;
  1427. BOOL AlreadyLogged ;
  1428. BOOL NewPassword ;
  1429. NTSTATUS Status = STATUS_SUCCESS ;
  1430. HWND hwndDomain = GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN);
  1431. INT iDomainSelection;
  1432. PDOMAIN_CACHE_ENTRY Entry ;
  1433. BOOL PasswordExpiryWarning;
  1434. PVOID ProfileBuffer;
  1435. ULONG ProfileBufferLength;
  1436. BOOL fStringFound = FALSE;
  1437. RECT rc;
  1438. UserName[0] = TEXT('\0');
  1439. Domain[0] = TEXT('\0');
  1440. Password[0] = TEXT('\0');
  1441. Buffer1[0] = TEXT('\0');
  1442. Buffer2[0] = TEXT('\0');
  1443. //
  1444. // We need to do some things differently when a smart card is used. The way to
  1445. // tell is find out if the username field is active.
  1446. //
  1447. AlreadyLogged = FALSE ;
  1448. NewPassword = FALSE ;
  1449. Unlocked = FALSE;
  1450. if ( !IsWindowEnabled( GetDlgItem( hDlg, IDD_UNLOCK_NAME ) ) )
  1451. {
  1452. SmartCardUnlock = TRUE ;
  1453. DifferentAccount = TRUE ;
  1454. }
  1455. else
  1456. {
  1457. SmartCardUnlock = FALSE ;
  1458. StringSize = GetDlgItemText(hDlg, IDD_UNLOCK_NAME, UserName, MAX_STRING_BYTES);
  1459. if (StringSize == MAX_STRING_BYTES)
  1460. {
  1461. UserName[MAX_STRING_BYTES-1] = TEXT('\0');
  1462. }
  1463. //
  1464. // check to see if this is the fancy "my computer" entry or the somewhat less fancy
  1465. // "use the UPN" entry
  1466. //
  1467. iDomainSelection = (INT)SendMessage(hwndDomain, CB_GETCURSEL, 0, 0);
  1468. Entry = (PDOMAIN_CACHE_ENTRY) SendMessage(hwndDomain, CB_GETITEMDATA, (WPARAM)iDomainSelection, 0);
  1469. if ( Entry == (PDOMAIN_CACHE_ENTRY) CB_ERR )
  1470. {
  1471. //
  1472. // Our list is hosed in some way.
  1473. //
  1474. GetDlgItemText( hDlg, IDD_UNLOCK_DOMAIN, Domain, MAX_STRING_BYTES );
  1475. }
  1476. else
  1477. {
  1478. wcscpy( Domain, Entry->FlatName.Buffer );
  1479. }
  1480. // If we are forcing a NoDomainUI, populate the domain with the local machine name now
  1481. if (ForceNoDomainUI())
  1482. {
  1483. DWORD chSize = ARRAYSIZE(Domain);
  1484. if (!GetComputerName(Domain, &chSize))
  1485. {
  1486. *Domain = 0;
  1487. }
  1488. }
  1489. if ( wcschr( UserName, TEXT('@') ) )
  1490. {
  1491. Domain[0] = TEXT('\0');
  1492. }
  1493. DifferentAccount = (lstrcmpi(UserName, pGlobals->UserName)) ||
  1494. (lstrcmpi(Domain, pGlobals->Domain)) ;
  1495. }
  1496. StringSize = GetDlgItemText(hDlg, IDD_UNLOCK_PASSWORD, Password, MAX_STRING_BYTES);
  1497. if (StringSize == MAX_STRING_BYTES)
  1498. {
  1499. Password[MAX_STRING_BYTES-1] = TEXT('\0');
  1500. }
  1501. RtlInitUnicodeString( &PasswordString, Password );
  1502. HashPassword(&PasswordString, PasswordHash );
  1503. //
  1504. // Check if this is the logged-on user. Do it through the security package
  1505. // if this was a smart card logon to begin with, if this is a smart card unlock,
  1506. // or if we're supposed to under all circumstances.
  1507. //
  1508. //
  1509. // Also check if password expiry warning will appear after unklocking. If so, then
  1510. // for a hit to the DC to update our profile info to make sure the user didn't
  1511. // already change their password on another machine.
  1512. //
  1513. PasswordExpiryWarning = ShouldPasswordExpiryWarningBeShown(pGlobals, FALSE, NULL);
  1514. if ( ( PasswordExpiryWarning ) ||
  1515. ( pGlobals->UnlockBehavior & UNLOCK_FORCE_AUTHENTICATION ) ||
  1516. ( SmartCardUnlock ) ||
  1517. ( pGlobals->SmartCardLogon ) ||
  1518. ( DifferentAccount ) )
  1519. {
  1520. //
  1521. // Init profile buffer
  1522. //
  1523. ProfileBuffer = NULL;
  1524. AlreadyLogged = TRUE ;
  1525. if ( SmartCardUnlock )
  1526. {
  1527. //
  1528. // Use the LogonInProgress bool to signal the fact that SmartCardAsyncUnlock
  1529. // is in progress
  1530. //
  1531. pGlobals->LogonInProgress = TRUE;
  1532. GetClientRect( hDlg, &rc );
  1533. pGlobals->cxBand = rc.right-rc.left;
  1534. pUnlockDlgState->fKillTimer = FALSE;
  1535. pUnlockDlgState->fUserBeingPrompted = FALSE;
  1536. pUnlockDlgState->fCardRemoved = FALSE;
  1537. SetTimer(hDlg, 0, 20, NULL);
  1538. // Set timeout to infinite while attempting to logon
  1539. pWlxFuncs->WlxSetTimeout( pGlobals->hGlobalWlx, TIMEOUT_NONE );
  1540. //
  1541. // Kick off the thread to do the unlock
  1542. //
  1543. if (UnlockLogonAsync( pGlobals,
  1544. pUnlockDlgState,
  1545. UserName,
  1546. Domain,
  1547. &PasswordString,
  1548. hDlg,
  1549. TRUE ))
  1550. {
  1551. HidePassword( &IgnoreSeed, &PasswordString );
  1552. return ( MSGINA_DLG_ASYNC_PROCESSING );
  1553. }
  1554. else
  1555. {
  1556. //Status = STATUS_E_FAIL; // SET THIS TO SOMETHING REASONABLE
  1557. goto AsyncUnlockError;
  1558. }
  1559. }
  1560. Unlocked = UnlockLogon( pGlobals,
  1561. SmartCardUnlock,
  1562. UserName,
  1563. Domain,
  1564. &PasswordString,
  1565. &Status,
  1566. &IsAdmin,
  1567. &IsLoggedOnUser,
  1568. &ProfileBuffer,
  1569. &ProfileBufferLength );
  1570. // Special handling for failed unlock on personal or professional
  1571. // machines that are NOT joined to a domain. In this case it's
  1572. // probably a user who disabled friendly UI and only knows of
  1573. // their "display name" not their real "logon name". This
  1574. // transparently maps one to the other to allow unlocks using
  1575. // the "display name".
  1576. if ((Status == STATUS_LOGON_FAILURE) &&
  1577. (IsOS(OS_PERSONAL) || IsOS(OS_PROFESSIONAL)) &&
  1578. !IsMachineDomainMember()) // using our version to optimize caching
  1579. {
  1580. if (ReplacedPossibleDisplayName(UserName))
  1581. {
  1582. DifferentAccount = (lstrcmpi(UserName, pGlobals->UserName)) ||
  1583. (lstrcmpi(Domain, pGlobals->Domain)) ;
  1584. Unlocked = UnlockLogon( pGlobals,
  1585. SmartCardUnlock,
  1586. UserName,
  1587. Domain,
  1588. &PasswordString,
  1589. &Status,
  1590. &IsAdmin,
  1591. &IsLoggedOnUser,
  1592. &ProfileBuffer,
  1593. &ProfileBufferLength );
  1594. }
  1595. }
  1596. //
  1597. // If this unlocked, and is the logged on user,
  1598. // then check to see if we should update all the in-memory passwords
  1599. //
  1600. if ( ( Unlocked ) &&
  1601. ( IsLoggedOnUser ) )
  1602. {
  1603. //
  1604. // Could be a password update. Check:
  1605. //
  1606. if (RtlEqualMemory( PasswordHash, pGlobals->PasswordHash, PASSWORD_HASH_SIZE ) == FALSE )
  1607. {
  1608. // RevealPassword( &pGlobals->PasswordString );
  1609. UpdateWithChangedPassword(
  1610. pGlobals,
  1611. hDlg,
  1612. TRUE,
  1613. UserName,
  1614. Domain,
  1615. L"",
  1616. Password,
  1617. (PMSV1_0_INTERACTIVE_PROFILE)ProfileBuffer );
  1618. //
  1619. // Do not hide! Update will rehide the global copy of the password.
  1620. //
  1621. }
  1622. }
  1623. //
  1624. // Free profile buffer
  1625. //
  1626. if ( ProfileBuffer )
  1627. {
  1628. LsaFreeReturnBuffer(ProfileBuffer);
  1629. }
  1630. if ( Unlocked )
  1631. {
  1632. DifferentAccount = !IsLoggedOnUser ;
  1633. }
  1634. }
  1635. //
  1636. // Used to be just "else" here, ie:
  1637. // !PasswordExpiryWarning &&
  1638. // !( pGlobals->UnlockBehavior & UNLOCK_FORCE_AUTHENTICATION ) &&
  1639. // !SmartCardUnlock && !pGlobals->SmartCardLogon
  1640. // !DifferentAccount
  1641. // but that's not enough if the user ignored all expiry warnings to date
  1642. // and his password expired while locked (#404780)
  1643. //
  1644. // So the new logic is:
  1645. // If we didn't enter the previous block (tested by means of AlreadyLogged) or
  1646. // we entered it but it failed (and cached unlock is allowed and we didn't
  1647. // previously unlocked/logged on with a SC)
  1648. //
  1649. if ( ( AlreadyLogged == FALSE ) ||
  1650. ( ( Unlocked == FALSE ) &&
  1651. !( pGlobals->UnlockBehavior & UNLOCK_FORCE_AUTHENTICATION ) &&
  1652. !( pGlobals->SmartCardLogon )
  1653. )
  1654. )
  1655. {
  1656. //
  1657. // un-hide the original password text so that we can
  1658. // do the compare.
  1659. //
  1660. // WARNING: We originally tried doing this comparison
  1661. // with old and new passwords hidden. This is
  1662. // not a good idea because the hide routine
  1663. // will allow matches that shouldn't match.
  1664. //
  1665. // RevealPassword( &pGlobals->PasswordString );
  1666. Unlocked = ( (lstrcmp(Domain, pGlobals->Domain) == 0) &&
  1667. (lstrcmpi(UserName, pGlobals->UserName) == 0) &&
  1668. (RtlEqualMemory( PasswordHash, pGlobals->PasswordHash, PASSWORD_HASH_SIZE ) == TRUE ) );
  1669. //
  1670. // re-hide the original password - use the same seed
  1671. //
  1672. // HidePassword( &pGlobals->Seed, &pGlobals->PasswordString );
  1673. if ( ( !Unlocked ) &&
  1674. ( AlreadyLogged == FALSE ) ) // We already tried UnlockLogon otherwise
  1675. {
  1676. //
  1677. // The password doesn't match what we have cached. User
  1678. // could have changed the password from another machine.
  1679. // Let's do the logon, and it if works, we update everything.
  1680. //
  1681. //
  1682. // Init profile buffer
  1683. //
  1684. ProfileBuffer = NULL;
  1685. AlreadyLogged = TRUE ;
  1686. Unlocked = UnlockLogon( pGlobals,
  1687. FALSE,
  1688. UserName,
  1689. Domain,
  1690. &PasswordString,
  1691. &Status,
  1692. &IsAdmin,
  1693. &IsLoggedOnUser,
  1694. &ProfileBuffer,
  1695. &ProfileBufferLength );
  1696. if ( ( Unlocked ) && ( IsLoggedOnUser ) )
  1697. {
  1698. //
  1699. // This logon worked. Must be a new password.
  1700. //
  1701. // RevealPassword( &pGlobals->PasswordString );
  1702. UpdateWithChangedPassword(
  1703. pGlobals,
  1704. hDlg,
  1705. TRUE,
  1706. UserName,
  1707. Domain,
  1708. L"",
  1709. Password,
  1710. (PMSV1_0_INTERACTIVE_PROFILE)ProfileBuffer );
  1711. //
  1712. // Do not hide! Update will rehide the global copy of the password.
  1713. //
  1714. }
  1715. //
  1716. // Free profile buffer
  1717. //
  1718. if ( ProfileBuffer )
  1719. {
  1720. LsaFreeReturnBuffer(ProfileBuffer);
  1721. }
  1722. if ( Unlocked )
  1723. {
  1724. DifferentAccount = !IsLoggedOnUser ;
  1725. }
  1726. }
  1727. }
  1728. if (Unlocked && !DifferentAccount ) {
  1729. if ( (!AlreadyLogged) &&
  1730. ( ( pGlobals->UnlockBehavior & UNLOCK_NO_NETWORK) == 0 ) )
  1731. {
  1732. UnlockLogonAsync( pGlobals,
  1733. NULL,
  1734. UserName,
  1735. Domain,
  1736. &PasswordString,
  1737. NULL,
  1738. FALSE );
  1739. }
  1740. //
  1741. // Hide the new password to prevent it being paged cleartext.
  1742. //
  1743. HidePassword( &IgnoreSeed, &PasswordString );
  1744. pGlobals->SmartCardLogon = SmartCardUnlock;
  1745. return(MSGINA_DLG_SUCCESS);
  1746. }
  1747. //
  1748. // Check for an admin logon and force the user off
  1749. //
  1750. if ( DifferentAccount )
  1751. {
  1752. if ( !AlreadyLogged )
  1753. {
  1754. // PJM... Unreachable.
  1755. IsAdmin = TestUserForAdmin( pGlobals,
  1756. UserName,
  1757. Domain,
  1758. &PasswordString );
  1759. }
  1760. if ( IsAdmin ) {
  1761. //
  1762. // Hide the new password to prevent it being paged cleartext.
  1763. //
  1764. HidePassword( &IgnoreSeed, &PasswordString );
  1765. Result = TimeoutMessageBox(hDlg,
  1766. pGlobals,
  1767. IDS_FORCE_LOGOFF_WARNING,
  1768. IDS_WINDOWS_MESSAGE,
  1769. MB_OKCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON2,
  1770. TIMEOUT_CURRENT);
  1771. if (Result == MSGINA_DLG_SUCCESS) {
  1772. return(MSGINA_DLG_FORCE_LOGOFF);
  1773. }
  1774. return(Result);
  1775. }
  1776. }
  1777. else
  1778. {
  1779. //
  1780. // Cheap way to force a logon attempt, and hit the lockout yada yada
  1781. //
  1782. if ( !AlreadyLogged )
  1783. {
  1784. // PJM... Unreachable.
  1785. UnlockLogon( pGlobals,
  1786. SmartCardUnlock,
  1787. UserName,
  1788. Domain,
  1789. &PasswordString,
  1790. &Status,
  1791. &IsAdmin,
  1792. &IsLoggedOnUser,
  1793. NULL,
  1794. NULL );
  1795. }
  1796. }
  1797. AsyncUnlockError:
  1798. //
  1799. // Hide the password to prevent it being paged cleartext.
  1800. //
  1801. HidePassword( &IgnoreSeed, &PasswordString );
  1802. if ( !DifferentAccount )
  1803. {
  1804. int i ;
  1805. UINT Resource = 0 ;
  1806. for ( i = 0 ;
  1807. i < sizeof( UnlockMessages ) / sizeof( UNLOCK_MESSAGE ) ;
  1808. i++ )
  1809. {
  1810. if ( UnlockMessages[i].Status == Status )
  1811. {
  1812. Resource = UnlockMessages[i].Resource ;
  1813. break;
  1814. }
  1815. }
  1816. if ( Resource == 0 )
  1817. {
  1818. Resource = IDS_UNLOCK_FAILED_BAD_PWD ;
  1819. }
  1820. if(Resource == IDS_LOGON_NO_DOMAIN)
  1821. {
  1822. // Need to build the domain name into the string.
  1823. LoadString(hDllInstance, Resource, Buffer1, MAX_STRING_BYTES);
  1824. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain);
  1825. }
  1826. else
  1827. {
  1828. LoadString(hDllInstance, Resource, Buffer2, MAX_STRING_BYTES);
  1829. }
  1830. fStringFound = TRUE;
  1831. }
  1832. else
  1833. {
  1834. //
  1835. // They're not the logged on user and they're not an admin.
  1836. // Tell them they failed to unlock the workstation.
  1837. //
  1838. if ( lstrlen(pGlobals->UserFullName) == 0 ) {
  1839. //
  1840. // No full name.
  1841. //
  1842. if ( pGlobals->Domain[0] == L'\0' )
  1843. {
  1844. //
  1845. // UPN logon:
  1846. //
  1847. LoadString(hDllInstance, IDS_UNLOCK_FAILED_EMAIL_NFN, Buffer1, MAX_STRING_BYTES);
  1848. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1,
  1849. pGlobals->UserName
  1850. );
  1851. }
  1852. else
  1853. {
  1854. LoadString(hDllInstance, IDS_UNLOCK_FAILED_NFN, Buffer1, MAX_STRING_BYTES);
  1855. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain,
  1856. pGlobals->UserName
  1857. );
  1858. }
  1859. } else {
  1860. if ( pGlobals->Domain[0] == L'\0' )
  1861. {
  1862. //
  1863. // UPN Logon:
  1864. //
  1865. LoadString(hDllInstance, IDS_UNLOCK_FAILED_EMAIL, Buffer1, MAX_STRING_BYTES);
  1866. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1,
  1867. pGlobals->UserName,
  1868. pGlobals->UserFullName
  1869. );
  1870. }
  1871. else
  1872. {
  1873. LoadString(hDllInstance, IDS_UNLOCK_FAILED, Buffer1, MAX_STRING_BYTES);
  1874. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, pGlobals->Domain,
  1875. pGlobals->UserName,
  1876. pGlobals->UserFullName
  1877. );
  1878. }
  1879. }
  1880. }
  1881. LoadString(hDllInstance, IDS_WORKSTATION_LOCKED, Buffer1, MAX_STRING_BYTES);
  1882. Result = TimeoutMessageBoxlpstr(hDlg,
  1883. pGlobals,
  1884. Buffer2,
  1885. Buffer1,
  1886. MB_OK | MB_ICONSTOP,
  1887. TIMEOUT_CURRENT);
  1888. if (DLG_INTERRUPTED(Result)) {
  1889. return( SetInterruptFlag( MSGINA_DLG_FAILURE ) );
  1890. }
  1891. return(MSGINA_DLG_FAILURE);
  1892. }
  1893. /****************************************************************************\
  1894. *
  1895. * FUNCTION: UnlockShowOptions
  1896. *
  1897. * PURPOSE: Hide the options part of the unlock dialog
  1898. *
  1899. * RETURNS: Nothing
  1900. *
  1901. * HISTORY:
  1902. *
  1903. * 15-dec-97 daviddv - Created
  1904. *
  1905. \****************************************************************************/
  1906. VOID UnlockShowOptions(PGLOBALS pGlobals, HWND hDlg, BOOL fShow)
  1907. {
  1908. RECT rc, rc2;
  1909. INT dy;
  1910. TCHAR szBuffer[32];
  1911. if ( pGlobals->UnlockOptionsShown != fShow )
  1912. {
  1913. //
  1914. // Show hide optional fields in the dialog
  1915. //
  1916. if (pGlobals->ShowDomainBox)
  1917. {
  1918. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_PASSWORD), &rc);
  1919. GetWindowRect(GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN), &rc2);
  1920. dy = rc2.bottom-rc.bottom;
  1921. MoveControls(hDlg, ctrlNoDomain,
  1922. sizeof(ctrlNoDomain)/sizeof(ctrlNoDomain[0]),
  1923. 0, fShow ? dy:-dy,
  1924. TRUE);
  1925. ShowDlgItem(hDlg, IDD_UNLOCK_DOMAIN_LABEL, fShow);
  1926. ShowDlgItem(hDlg, IDD_UNLOCK_DOMAIN, fShow);
  1927. }
  1928. ShowDlgItem(hDlg, IDD_KBLAYOUT_ICON, fShow);
  1929. //
  1930. // Change the options button to reflect the open/close state
  1931. //
  1932. LoadString(hDllInstance, fShow ? IDS_LESSOPTIONS:IDS_MOREOPTIONS,
  1933. szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  1934. SetDlgItemText(hDlg, IDD_UNLOCK_OPTIONS, szBuffer);
  1935. }
  1936. pGlobals->UnlockOptionsShown = fShow;
  1937. // Enable or disable the domain box depending on whether a UPN name has been typed
  1938. EnableDomainForUPN(GetDlgItem(hDlg, IDD_UNLOCK_NAME), GetDlgItem(hDlg, IDD_UNLOCK_DOMAIN));
  1939. }