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.

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