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.

4915 lines
149 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: mslogon.c
  7. //
  8. // Contents: Microsoft Logon GUI DLL
  9. //
  10. // History: 7-14-94 RichardW Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "msgina.h"
  14. #include "shtdnp.h"
  15. #include "authmon.h"
  16. #include <stdio.h>
  17. #include <wchar.h>
  18. #include <wincrypt.h>
  19. #include <sclogon.h>
  20. #include "shlwapi.h"
  21. #include "shlwapip.h"
  22. #include "winsta.h"
  23. #include "wtsapi32.h"
  24. #include <keymgr.h>
  25. #include <passrec.h>
  26. typedef void (WINAPI *RUNDLLPROC)(HWND hWndStub,HINSTANCE hInstance,LPWSTR szCommandLine,int nShow);
  27. typedef struct _MSGINA_LOGON_PARAMETERS {
  28. PGLOBALS pGlobals;
  29. DWORD SasType;
  30. } MSGINA_LOGON_PARAMETERS, * PMSGINA_LOGON_PARAMETERS ;
  31. #define WINSTATIONS_DISABLED TEXT("WinStationsDisabled")
  32. //
  33. // Number of seconds we will display the legal notices
  34. // before timing out.
  35. //
  36. #define LEGAL_NOTICE_TIMEOUT 120
  37. #define LOGON_SLEEP_PERIOD 750
  38. #define WM_LOGONPROMPT WM_USER + 257
  39. #define WM_LOGONCOMPLETE WM_USER + 258
  40. #define WM_HANDLEFAILEDLOGON WM_USER + 259
  41. #define WM_DCACHE_COMPLETE WM_USER + 260
  42. #define MAX_CAPTION_LENGTH 256
  43. // Maximum size of a UPN name we allow at present
  44. #define MAX_UPN_NAME_SIZE 520
  45. typedef struct FAILEDLOGONINFO_t
  46. {
  47. PGLOBALS pGlobals;
  48. NTSTATUS Status;
  49. NTSTATUS SubStatus;
  50. TCHAR UserName[UNLEN + DNLEN + 2];
  51. TCHAR Domain[DNLEN + 1];
  52. } FAILEDLOGONINFO, *PFAILEDLOGONINFO;
  53. typedef struct _LEGALINFO
  54. {
  55. LPTSTR NoticeText;
  56. LPTSTR CaptionText;
  57. } LEGALINFO, *PLEGALINFO;
  58. // Also defined in wstrpc.c
  59. #define INET_CONNECTOR_EVENT_NAME L"Global\\TermSrvInetConnectorEvent"
  60. #define TERMSERV_EVENTSOURCE L"TermService"
  61. // Also defined in icaevent.mc
  62. #define EVENT_BAD_TSINTERNET_USER 1007
  63. //
  64. // Globals:
  65. //
  66. static WNDPROC OldCBWndProc;
  67. HICON hSteadyFlag;
  68. HICON hWavingFlag;
  69. HICON hAuditFull;
  70. extern HICON hLockedIcon;
  71. BOOL IsPswBackupAvailable;
  72. BOOL s_fAttemptedAutoLogon;
  73. BOOL g_fHelpAssistantLogon = FALSE;
  74. //
  75. // Prototypes:
  76. //
  77. INT_PTR
  78. DisplayLegalNotices(
  79. PGLOBALS pGlobals
  80. );
  81. BOOL
  82. GetLegalNotices(
  83. LPTSTR lpSubKey,
  84. LPTSTR *NoticeText,
  85. LPTSTR *CaptionText
  86. );
  87. INT_PTR WINAPI
  88. LogonDlgCBProc(
  89. HWND hDlg,
  90. UINT message,
  91. WPARAM wParam,
  92. LPARAM lParam
  93. );
  94. INT_PTR WINAPI
  95. LogonDlgUsernameProc(
  96. HWND hDlg,
  97. UINT message,
  98. WPARAM wParam,
  99. LPARAM lParam
  100. );
  101. INT_PTR WINAPI
  102. LogonDlgProc(
  103. HWND hDlg,
  104. UINT message,
  105. WPARAM wParam,
  106. LPARAM lParam
  107. );
  108. BOOL
  109. LogonDlgInit(
  110. HWND hDlg,
  111. BOOL bAutoLogon,
  112. DWORD SasType
  113. );
  114. NTSTATUS
  115. UpnFromCert(
  116. IN PCCERT_CONTEXT pCert,
  117. IN OUT DWORD *pcUpn,
  118. IN OUT LPWSTR pUPN
  119. );
  120. BOOL
  121. WINAPI
  122. QuerySwitchConsoleCredentials(
  123. PGLOBALS pGlobals,
  124. HANDLE * phUserToken,
  125. PLUID pLogonId);
  126. // Global structure for a failed logon filled in by the worker thread to be consumed
  127. // by the ui thread.
  128. FAILEDLOGONINFO g_failinfo;
  129. void PostFailedLogonMessage(HWND hDlg,
  130. PGLOBALS pGlobals,
  131. NTSTATUS Status,
  132. NTSTATUS SubStatus,
  133. PWCHAR UserName,
  134. PWCHAR Domain
  135. );
  136. INT_PTR
  137. HandleFailedLogon(
  138. HWND hDlg
  139. );
  140. VOID
  141. ReportBootGood(
  142. PGLOBALS pGlobals
  143. );
  144. VOID LogonShowOptions(
  145. PGLOBALS pGlobals,
  146. HWND hDlg,
  147. BOOL fShow,
  148. BOOL fSticky);
  149. VOID AttemptLogonSetControls(
  150. PGLOBALS pGlobals,
  151. HWND hDlg
  152. );
  153. INT_PTR
  154. AttemptLogon(
  155. HWND hDlg
  156. );
  157. DWORD
  158. AttemptLogonThread(
  159. PGLOBALS pGlobals
  160. );
  161. BOOL
  162. GetAndAllocateLogonSid(
  163. HANDLE hToken,
  164. PSID *pLogonSid
  165. );
  166. BOOL GetSessionZeroUser(LPTSTR szUser);
  167. BOOL FastUserSwitchingEnabled();
  168. //
  169. // control tables for showing/hiding options
  170. //
  171. static UINT ctrlNoShutdown[] =
  172. {
  173. IDOK,
  174. IDCANCEL,
  175. };
  176. static UINT ctrlNoCancel[] =
  177. {
  178. IDOK,
  179. };
  180. static UINT ctrlNoDomain[] =
  181. {
  182. IDOK,
  183. IDCANCEL,
  184. IDD_LOGON_SHUTDOWN,
  185. IDD_LOGON_OPTIONS,
  186. IDD_LOGON_RASBOX,
  187. IDD_KBLAYOUT_ICON,
  188. };
  189. static UINT ctrlNoRAS[] =
  190. {
  191. IDOK,
  192. IDCANCEL,
  193. IDD_LOGON_SHUTDOWN,
  194. IDD_LOGON_OPTIONS,
  195. IDD_KBLAYOUT_ICON,
  196. };
  197. static UINT ctrlNoOptions[] =
  198. {
  199. IDOK,
  200. IDCANCEL,
  201. IDD_LOGON_SHUTDOWN,
  202. IDD_KBLAYOUT_ICON,
  203. };
  204. static UINT ctrlNoLegalBanner[] =
  205. {
  206. IDD_LOGON_NAME_LABEL,
  207. IDD_LOGON_NAME,
  208. IDD_LOGON_PASSWORD_LABEL,
  209. IDD_LOGON_PASSWORD,
  210. IDD_LOGON_DOMAIN_LABEL,
  211. IDD_LOGON_DOMAIN,
  212. IDD_LOGON_RASBOX,
  213. IDD_KBLAYOUT_ICON,
  214. IDOK,
  215. IDCANCEL,
  216. IDD_LOGON_SHUTDOWN,
  217. IDD_LOGON_OPTIONS,
  218. };
  219. static UINT ctrlNoUserName[] =
  220. {
  221. IDD_LOGON_PASSWORD_LABEL,
  222. IDD_LOGON_PASSWORD,
  223. IDD_LOGON_DOMAIN_LABEL,
  224. IDD_LOGON_DOMAIN,
  225. IDD_LOGON_RASBOX,
  226. IDD_KBLAYOUT_ICON,
  227. IDOK,
  228. IDCANCEL,
  229. IDD_LOGON_SHUTDOWN,
  230. IDD_LOGON_OPTIONS,
  231. };
  232. // --------------------------------------------------------------------------
  233. // ::DisableEditSubClassProc
  234. //
  235. // Arguments: hwnd = See the platform SDK under WindowProc.
  236. // uMsg = See the platform SDK under WindowProc.
  237. // wParam = See the platform SDK under WindowProc.
  238. // lParam = See the platform SDK under WindowProc.
  239. // uiID = ID assigned at subclass time.
  240. // dwRefData = reference data assigned at subclass time.
  241. //
  242. // Returns: LRESULT
  243. //
  244. // Purpose: comctl32 subclass callback function. This allows us to not
  245. // process WM_CUT/WM_COPY/WM_PASTE/WM_CLEAR/WM_UNDO and any
  246. // other messages to be discarded.
  247. //
  248. // History: 2001-02-18 vtan created
  249. // --------------------------------------------------------------------------
  250. LRESULT CALLBACK DisableEditSubClassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uiID, DWORD_PTR dwRefData)
  251. {
  252. LRESULT lResult;
  253. switch (uMsg)
  254. {
  255. case WM_CUT:
  256. case WM_COPY:
  257. case WM_PASTE:
  258. case WM_CLEAR:
  259. case WM_UNDO:
  260. case WM_CONTEXTMENU:
  261. lResult = FALSE;
  262. break;
  263. default:
  264. lResult = DefSubclassProc(hwnd, uMsg, wParam, lParam);
  265. break;
  266. }
  267. return(lResult);
  268. }
  269. INT_PTR WINAPI
  270. LegalDlgProc(
  271. HWND hDlg,
  272. UINT message,
  273. WPARAM wParam,
  274. LPARAM lParam
  275. )
  276. {
  277. switch (message)
  278. {
  279. case WM_INITDIALOG:
  280. {
  281. PLEGALINFO pLegalInfo;
  282. pLegalInfo = (PLEGALINFO) lParam;
  283. SetWindowText (hDlg, pLegalInfo->CaptionText);
  284. SetWindowText (GetDlgItem(hDlg, IDD_LEGALTEXT), pLegalInfo->NoticeText);
  285. CentreWindow(hDlg);
  286. // Ensure the window is topmost so it's not obscured by the welcome screen.
  287. SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  288. return( TRUE );
  289. }
  290. case WM_COMMAND:
  291. {
  292. if (LOWORD(wParam) == IDOK)
  293. {
  294. EndDialog(hDlg, IDOK);
  295. }
  296. }
  297. break;
  298. }
  299. return FALSE;
  300. }
  301. /***************************************************************************\
  302. * FUNCTION: DisplayLegalNotices
  303. *
  304. * PURPOSE: Puts up a dialog box containing legal notices, if any.
  305. *
  306. * RETURNS: MSGINA_DLG_SUCCESS - the dialog was shown and dismissed successfully.
  307. * MSGINA_DLG_FAILURE - the dialog could not be shown
  308. * DLG_INTERRUPTED() - a set defined in winlogon.h
  309. *
  310. * HISTORY:
  311. *
  312. * Robertre 6-30-93 Created
  313. *
  314. \***************************************************************************/
  315. INT_PTR
  316. DisplayLegalNotices(
  317. PGLOBALS pGlobals
  318. )
  319. {
  320. INT_PTR Result = MSGINA_DLG_SUCCESS;
  321. LPTSTR NoticeText;
  322. LPTSTR CaptionText;
  323. LEGALINFO LegalInfo;
  324. if (GetLegalNotices( WINLOGON_POLICY_KEY, &NoticeText, &CaptionText ))
  325. {
  326. LegalInfo.NoticeText = NoticeText;
  327. LegalInfo.CaptionText = CaptionText;
  328. _Shell_LogonStatus_Hide();
  329. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx, LEGAL_NOTICE_TIMEOUT);
  330. Result = pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  331. hDllInstance,
  332. (LPTSTR) IDD_LEGALMSG,
  333. NULL,
  334. LegalDlgProc,
  335. (LPARAM) &LegalInfo );
  336. _Shell_LogonStatus_Show();
  337. Free( NoticeText );
  338. Free( CaptionText );
  339. }
  340. else if (GetLegalNotices( WINLOGON_KEY, &NoticeText, &CaptionText ))
  341. {
  342. LegalInfo.NoticeText = NoticeText;
  343. LegalInfo.CaptionText = CaptionText;
  344. _Shell_LogonStatus_Hide();
  345. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx, LEGAL_NOTICE_TIMEOUT);
  346. Result = pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  347. hDllInstance,
  348. (LPTSTR) IDD_LEGALMSG,
  349. NULL,
  350. LegalDlgProc,
  351. (LPARAM) &LegalInfo );
  352. _Shell_LogonStatus_Show();
  353. Free( NoticeText );
  354. Free( CaptionText );
  355. }
  356. return( Result );
  357. }
  358. /***************************************************************************\
  359. * FUNCTION: GetLegalNotices
  360. *
  361. * PURPOSE: Get legal notice information out of the registry.
  362. *
  363. * RETURNS: TRUE - Output parameters contain valid data
  364. * FALSE - No data returned.
  365. *
  366. * HISTORY:
  367. *
  368. * Robertre 6-30-93 Created
  369. *
  370. \***************************************************************************/
  371. BOOL
  372. GetLegalNotices(
  373. LPTSTR lpSubKey,
  374. LPTSTR *NoticeText,
  375. LPTSTR *CaptionText
  376. )
  377. {
  378. LPTSTR lpCaption, lpText;
  379. HKEY hKey;
  380. DWORD dwSize, dwType, dwMaxSize = 0;
  381. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey,
  382. 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  383. {
  384. RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL,
  385. NULL, NULL, NULL, NULL, &dwMaxSize,
  386. NULL, NULL);
  387. lpCaption = Alloc (dwMaxSize);
  388. if (!lpCaption) {
  389. RegCloseKey(hKey);
  390. return FALSE;
  391. }
  392. lpText = Alloc (dwMaxSize);
  393. if (!lpText) {
  394. Free(lpCaption);
  395. RegCloseKey(hKey);
  396. return FALSE;
  397. }
  398. dwSize = dwMaxSize;
  399. RegQueryValueEx(hKey, LEGAL_NOTICE_CAPTION_KEY,
  400. 0, &dwType, (LPBYTE)lpCaption, &dwSize);
  401. dwSize = dwMaxSize;
  402. RegQueryValueEx(hKey, LEGAL_NOTICE_TEXT_KEY,
  403. 0, &dwType, (LPBYTE)lpText, &dwSize);
  404. RegCloseKey(hKey);
  405. if (*lpCaption && *lpText) {
  406. *CaptionText = lpCaption;
  407. *NoticeText = lpText;
  408. return TRUE;
  409. }
  410. Free(lpCaption);
  411. Free(lpText);
  412. }
  413. return FALSE;
  414. }
  415. /***************************************************************************\
  416. * FUNCTION: Logon
  417. *
  418. * PURPOSE: Display the logon UI depending on the SAS type.
  419. *
  420. * RETURNS: -
  421. *
  422. * NOTES: If the logon is successful, the global structure is filled in
  423. * with the logon information.
  424. *
  425. * HISTORY:
  426. * 12-09-91 daviddv Comments.
  427. *
  428. \***************************************************************************/
  429. INT_PTR
  430. Logon(
  431. PGLOBALS pGlobals,
  432. DWORD SasType
  433. )
  434. {
  435. INT_PTR Result;
  436. MSGINA_LOGON_PARAMETERS Parm ;
  437. if ( SasType == WLX_SAS_TYPE_SC_REMOVE )
  438. {
  439. return WLX_SAS_ACTION_NONE ;
  440. }
  441. if( !g_Console )
  442. {
  443. //
  444. // Check if current session is HelpAssistant Session, HelpAssisant
  445. // session can not be console session.
  446. //
  447. g_fHelpAssistantLogon = WinStationIsHelpAssistantSession(
  448. SERVERNAME_CURRENT,
  449. LOGONID_CURRENT
  450. );
  451. }
  452. if ( SasType == WLX_SAS_TYPE_SC_INSERT )
  453. {
  454. PWLX_SC_NOTIFICATION_INFO ScInfo = NULL ;
  455. pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
  456. WLX_OPTION_SMART_CARD_INFO,
  457. (ULONG_PTR *) &ScInfo );
  458. //
  459. // Validate the SC info against some common user
  460. // errors before the PIN dialog appears
  461. //
  462. if ( ScInfo )
  463. {
  464. if ( ( ScInfo->pszReader ) &&
  465. ( ScInfo->pszCard == NULL ) )
  466. {
  467. //
  468. // The card could not be read. Might not be
  469. // inserted correctly.
  470. //
  471. LocalFree(ScInfo);
  472. TimeoutMessageBox( NULL, pGlobals, IDS_CARD_NOT_RECOGNIZED,
  473. IDS_LOGON_MESSAGE,
  474. MB_OK | MB_ICONEXCLAMATION,
  475. LOGON_TIMEOUT );
  476. return WLX_SAS_ACTION_NONE;
  477. }
  478. if ( ( ScInfo->pszReader ) &&
  479. ( ScInfo->pszCryptoProvider == NULL ) )
  480. {
  481. //
  482. // Got a card, but the CSP for it could not be
  483. // found.
  484. //
  485. LocalFree(ScInfo);
  486. TimeoutMessageBox( NULL, pGlobals, IDS_CARD_CSP_NOT_RECOGNIZED,
  487. IDS_LOGON_MESSAGE,
  488. MB_OK | MB_ICONEXCLAMATION,
  489. LOGON_TIMEOUT );
  490. return WLX_SAS_ACTION_NONE;
  491. }
  492. LocalFree(ScInfo);
  493. }
  494. }
  495. //
  496. // Asynchronously update domain cache if necessary.
  497. // We won't ask to wait so this routine will do no UI.
  498. // i.e. we can ignore the result.
  499. //
  500. // Result = UpdateDomainCache(pGlobals, NULL, FALSE);
  501. // ASSERT(!DLG_INTERRUPTED(Result));
  502. if( !g_fHelpAssistantLogon ) {
  503. //
  504. // See if there are legal notices in the registry.
  505. // If so, put them up in a message box
  506. //
  507. Result = DisplayLegalNotices( pGlobals );
  508. if ( Result != MSGINA_DLG_SUCCESS ) {
  509. return(WLX_SAS_ACTION_NONE);
  510. }
  511. //
  512. // Get the latest audit log status and store in our globals
  513. // If the audit log is full we show a different logon dialog.
  514. //
  515. GetAuditLogStatus(pGlobals);
  516. } else {
  517. //
  518. // fake it so audit log is not full, setting is from GetAuditLogStatus()
  519. //
  520. pGlobals->AuditLogFull = FALSE;
  521. pGlobals->AuditLogNearFull = FALSE;
  522. }
  523. Parm.pGlobals = pGlobals ;
  524. Parm.SasType = SasType ;
  525. //
  526. // Take their username and password and try to log them on
  527. //
  528. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx,
  529. ( (GetDisableCad(pGlobals) && IsActiveConsoleSession()) ? TIMEOUT_NONE : LOGON_TIMEOUT));
  530. Result = pWlxFuncs->WlxDialogBoxParam(pGlobals->hGlobalWlx,
  531. hDllInstance,
  532. MAKEINTRESOURCE(IDD_LOGON_DIALOG),
  533. NULL,
  534. LogonDlgProc,
  535. (LPARAM) &Parm );
  536. if ( Result == WLX_SAS_ACTION_LOGON )
  537. {
  538. if ( (pGlobals->SmartCardOption == 0) || (!pGlobals->SmartCardLogon) )
  539. {
  540. // As no action will be taken on SC removal, we can filter these events
  541. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  542. WLX_OPTION_USE_SMART_CARD,
  543. 0,
  544. NULL );
  545. }
  546. else
  547. {
  548. //
  549. // Continue to monitor the s/c device
  550. //
  551. NOTHING ;
  552. }
  553. }
  554. return(Result);
  555. }
  556. /***************************************************************************\
  557. * FUNCTION: LogonDlgCBProc
  558. *
  559. * PURPOSE: Processes messages for Logon dialog combo box
  560. *
  561. * RETURNS: Return value depends on message being sent.
  562. *
  563. * HISTORY:
  564. *
  565. * 05-21-93 RobertRe Created.
  566. *
  567. \***************************************************************************/
  568. INT_PTR WINAPI
  569. LogonDlgCBProc(
  570. HWND hwnd,
  571. UINT message,
  572. WPARAM wParam,
  573. LPARAM lParam
  574. )
  575. {
  576. TCHAR KeyPressed;
  577. // DbgPrint("message = %X\n",message);
  578. switch (message) {
  579. case WM_CHAR:
  580. {
  581. KeyPressed = (TCHAR) wParam;
  582. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG)KeyPressed);
  583. //
  584. // This fake CBN_SELCHANGE message will cause the
  585. // "Please wait..." dialog box to appear even if
  586. // the character pressed doesn't exist in the combobox yet.
  587. //
  588. PostMessage (GetParent(hwnd), WM_COMMAND,
  589. MAKELONG(0, CBN_SELCHANGE), 0);
  590. break;
  591. }
  592. }
  593. return CallWindowProc(OldCBWndProc,hwnd,message,wParam,lParam);
  594. }
  595. INT_PTR
  596. CALLBACK
  597. DomainCacheDlgProc(
  598. HWND hDlg,
  599. UINT Message,
  600. WPARAM wParam,
  601. LPARAM lParam
  602. )
  603. {
  604. PGLOBALS pGlobals ;
  605. DebugLog(( DEB_TRACE_DOMAIN, "DomainCacheDlgProc( %p, %x, %p, %p )\n",
  606. hDlg, Message, wParam, lParam ));
  607. switch ( Message )
  608. {
  609. case WM_INITDIALOG:
  610. pGlobals = (PGLOBALS) lParam ;
  611. if ( DCacheSetNotifyWindowIfNotReady(
  612. pGlobals->Cache,
  613. hDlg,
  614. WM_DCACHE_COMPLETE ) )
  615. {
  616. EndDialog( hDlg, TRUE );
  617. }
  618. return TRUE ;
  619. case WM_DCACHE_COMPLETE:
  620. EndDialog( hDlg, TRUE );
  621. return TRUE ;
  622. default:
  623. return FALSE ;
  624. }
  625. }
  626. BOOL IsAutoLogonUserInteractiveLogonRestricted (HWND hDlg)
  627. {
  628. WCHAR szUsername[UNLEN + 1]; // sizeof('\0')
  629. return((GetDlgItemText(hDlg, IDD_LOGON_NAME, szUsername, ARRAYSIZE(szUsername)) != 0) &&
  630. !ShellIsUserInteractiveLogonAllowed(szUsername));
  631. }
  632. BOOL HasDefaultPassword (TCHAR *pszPassword, int cchPassword)
  633. {
  634. DWORD dwType, dwPasswordSize;
  635. dwType = REG_NONE;
  636. dwPasswordSize = cchPassword * sizeof(TCHAR);
  637. return(ERROR_SUCCESS == RegQueryValueEx(WinlogonKey,
  638. DEFAULT_PASSWORD_KEY,
  639. NULL,
  640. &dwType,
  641. (LPBYTE)pszPassword,
  642. &dwPasswordSize) &&
  643. (REG_SZ == dwType));
  644. }
  645. // ==========================================================================================
  646. // Logon dialog has 2 formats, one that looks like logon dialog box, another that looks like
  647. // unlock desktop dialogbox. When user connects to session 0 from remote (tsclient) the
  648. // dialog that appears at console // need to change to unlock computer. so if session 0 is in
  649. // use, and if this session is created at active console. we change logon dialog to look like
  650. // "unlock computer" dialog.
  651. // This function SwitchLogonLocked does most of the stuff related to switching these
  652. // dialog controls.
  653. // Parameters:
  654. // HWND hDlg - dialog window handle,
  655. // BOOL bShowLocked - if true show locked dialog, if false show normal logon dialog.
  656. // BOOL bInit - TRUE when this function is called for the first time.
  657. // ==========================================================================================
  658. static bLocked = TRUE;
  659. BOOL IsthisUnlockWindowsDialog ()
  660. {
  661. return bLocked;
  662. }
  663. BOOL SwitchLogonLocked(HWND hDlg, BOOL bShowLocked, BOOL bInit)
  664. {
  665. UINT rgidLockControls[] = {IDC_GROUP_UNLOCK, IDD_UNLOCK_ICON, IDD_UNLOCK_MESSAGE, IDD_UNLOCK_NAME_INFO};
  666. static LockedControlHeight = 0;
  667. BOOL bShutdownWithoutLogon;
  668. int i;
  669. if (bShowLocked == bLocked && !bInit)
  670. {
  671. // nothing to do.
  672. return TRUE;
  673. }
  674. if (bInit)
  675. {
  676. {
  677. //
  678. // remember the reference rectangle height (groupbox) for control movements.
  679. //
  680. RECT rectLockedControls;
  681. HWND hWnd = GetDlgItem(hDlg, rgidLockControls[0]);
  682. GetWindowRect(hWnd, &rectLockedControls);
  683. LockedControlHeight = rectLockedControls.bottom - rectLockedControls.top;
  684. //
  685. // this group box was only for reference, now hide it forever.
  686. //
  687. ShowWindow(hWnd, SW_HIDE);
  688. }
  689. bLocked = TRUE;
  690. if ( !hLockedIcon )
  691. {
  692. hLockedIcon = LoadImage( hDllInstance,
  693. MAKEINTRESOURCE( IDI_LOCKED),
  694. IMAGE_ICON,
  695. 0, 0,
  696. LR_DEFAULTCOLOR );
  697. }
  698. SendMessage( GetDlgItem( hDlg, IDD_UNLOCK_ICON),
  699. STM_SETICON,
  700. (WPARAM)hLockedIcon,
  701. 0 );
  702. }
  703. // lets move controls arround, depending upon if lock controls are to be shown or not.
  704. if (bLocked != bShowLocked)
  705. {
  706. if (bShowLocked)
  707. {
  708. MoveChildren(hDlg, 0, LockedControlHeight);
  709. for ( i = 1; i < sizeof(rgidLockControls)/sizeof(rgidLockControls[0]); i++)
  710. {
  711. HWND hWnd = GetDlgItem(hDlg, rgidLockControls[i]);
  712. ASSERT(hWnd);
  713. EnableWindow(hWnd, TRUE);
  714. ShowWindow(hWnd, SW_SHOW);
  715. }
  716. }
  717. else
  718. {
  719. for ( i = 1; i < sizeof(rgidLockControls)/sizeof(rgidLockControls[0]); i++)
  720. {
  721. HWND hWnd = GetDlgItem(hDlg, rgidLockControls[i]);
  722. ASSERT(hWnd);
  723. ShowWindow(hWnd, SW_HIDE);
  724. EnableWindow(hWnd, FALSE);
  725. }
  726. MoveChildren(hDlg, 0, -LockedControlHeight);
  727. }
  728. }
  729. // some more processing
  730. {
  731. if (bShowLocked)
  732. {
  733. TCHAR szUser[USERNAME_LENGTH + DOMAIN_LENGTH + 2];
  734. TCHAR szMessage[MAX_STRING_BYTES];
  735. TCHAR szFinalMessage[MAX_STRING_BYTES];
  736. if (GetSessionZeroUser(szUser))
  737. {
  738. LoadString(hDllInstance, IDS_LOCKED_EMAIL_NFN_MESSAGE, szMessage, MAX_STRING_BYTES);
  739. _snwprintf(szFinalMessage, sizeof(szFinalMessage)/sizeof(TCHAR), szMessage, szUser );
  740. }
  741. else
  742. {
  743. //
  744. // for some reason we could not get the current session zero user.
  745. //
  746. LoadString(hDllInstance, IDS_LOCKED_NO_USER_MESSAGE, szFinalMessage, MAX_STRING_BYTES);
  747. }
  748. SetDlgItemText(hDlg, IDD_UNLOCK_NAME_INFO, szFinalMessage);
  749. }
  750. //
  751. // update the dialog box caption, accordingly
  752. //
  753. {
  754. TCHAR szCaption[MAX_CAPTION_LENGTH];
  755. LoadString(hDllInstance, bShowLocked ? IDS_CAPTION_UNLOCK_DIALOG : IDS_CAPTION_LOGON_DIALOG, szCaption, ARRAYSIZE(szCaption));
  756. if ( szCaption[0] != TEXT('\0') )
  757. SetWindowText( hDlg, szCaption );
  758. }
  759. }
  760. bLocked = bShowLocked;
  761. if ( SafeBootMode == SAFEBOOT_MINIMAL )
  762. {
  763. bShutdownWithoutLogon = TRUE ;
  764. }
  765. else if (IsthisUnlockWindowsDialog() || !IsActiveConsoleSession())
  766. {
  767. bShutdownWithoutLogon = FALSE ;
  768. }
  769. else
  770. {
  771. bShutdownWithoutLogon = ReadWinlogonBoolValue(SHUTDOWN_WITHOUT_LOGON_KEY, TRUE);
  772. }
  773. EnableDlgItem(hDlg, IDD_LOGON_SHUTDOWN, bShutdownWithoutLogon);
  774. InvalidateRect(hDlg, NULL, TRUE);
  775. return TRUE;
  776. }
  777. /***************************************************************************\
  778. * FUNCTION: LogonDlgProc
  779. *
  780. * PURPOSE: Processes messages for Logon dialog
  781. *
  782. * RETURNS: MSGINA_DLG_SUCCESS - the user was logged on successfully
  783. * MSGINA_DLG_FAILURE - the logon failed,
  784. * DLG_INTERRUPTED() - a set defined in winlogon.h
  785. *
  786. * HISTORY:
  787. *
  788. * 12-09-91 Davidc Created.
  789. *
  790. \***************************************************************************/
  791. #define WM_HIDEOURSELVES (WM_USER + 1000)
  792. INT_PTR WINAPI
  793. LogonDlgProc(
  794. HWND hDlg,
  795. UINT message,
  796. WPARAM wParam,
  797. LPARAM lParam
  798. )
  799. {
  800. PGLOBALS pGlobals = (PGLOBALS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  801. INT_PTR Result;
  802. HWND CBHandle;
  803. BOOL fDisconnectOnTsAutoLogonFailure = FALSE;
  804. static BOOL bSessionZeroInUse = FALSE;
  805. static int iSessionRegistrationCount = 0;
  806. static BOOL bSmartCardInserted = FALSE;
  807. switch (message)
  808. {
  809. case WM_INITDIALOG:
  810. {
  811. TCHAR PasswordBuffer[127];
  812. BOOL bAutoLogon;
  813. PMSGINA_LOGON_PARAMETERS pParam ;
  814. pParam = (PMSGINA_LOGON_PARAMETERS) lParam ;
  815. pGlobals = pParam->pGlobals ;
  816. SetWindowLongPtr(hDlg, GWLP_USERDATA, (LPARAM)pGlobals);
  817. // Hide the keyboard accelerator keys to start
  818. SendMessage(hDlg, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0);
  819. // Limit the maximum password length to 127
  820. SendDlgItemMessage(hDlg, IDD_LOGON_PASSWORD, EM_SETLIMITTEXT, (WPARAM) 127, 0);
  821. s_fAttemptedAutoLogon = FALSE;
  822. //
  823. // Check if auto logon is enabled.
  824. //
  825. pGlobals->AutoAdminLogon = GetProfileInt( APPLICATION_NAME, AUTO_ADMIN_LOGON_KEY, 0 ) != 0;
  826. bAutoLogon = !pGlobals->IgnoreAutoAdminLogon;
  827. if ( !pGlobals->AutoAdminLogon || (!g_Console) ||
  828. ((GetAsyncKeyState(VK_SHIFT) < 0) && (GetProfileInt( APPLICATION_NAME, IGNORE_SHIFT_OVERRIDE_KEY, 0 ) == 0)) )
  829. {
  830. bAutoLogon = FALSE;
  831. }
  832. KdPrint(("AutoAdminLogon = %d, IgnoreAutoAdminLogon = %d, bAutoLogon = %d\n",
  833. pGlobals->AutoAdminLogon,
  834. pGlobals->IgnoreAutoAdminLogon,
  835. bAutoLogon ));
  836. //
  837. // Subclass the domain list control so we can filter messages
  838. //
  839. CBHandle = GetDlgItem(hDlg,IDD_LOGON_DOMAIN);
  840. SetWindowLongPtr(CBHandle, GWLP_USERDATA, 0);
  841. OldCBWndProc = (WNDPROC) SetWindowLongPtr(CBHandle, GWLP_WNDPROC, (LONG_PTR)LogonDlgCBProc);
  842. //
  843. // Subclass the user name and password edit also so we can disable edits
  844. //
  845. SetWindowSubclass(GetDlgItem(hDlg, IDD_LOGON_NAME) , DisableEditSubClassProc, IDD_LOGON_NAME , 0);
  846. SetWindowSubclass(GetDlgItem(hDlg, IDD_LOGON_PASSWORD), DisableEditSubClassProc, IDD_LOGON_PASSWORD, 0);
  847. ShellReleaseLogonMutex(FALSE);
  848. if (!LogonDlgInit(hDlg, bAutoLogon, pParam->SasType ))
  849. {
  850. bSmartCardInserted = FALSE;
  851. EndDialog(hDlg, MSGINA_DLG_FAILURE);
  852. return(TRUE);
  853. }
  854. //
  855. // If the default user for auto logon is present and the user is
  856. // restricted (interactive logon denied) then disable auto logon.
  857. //
  858. if (bAutoLogon && IsAutoLogonUserInteractiveLogonRestricted(hDlg))
  859. {
  860. bAutoLogon = FALSE;
  861. }
  862. //
  863. // If CAD is disabled, then gray out the Cancel button
  864. //
  865. if (GetDisableCad(pGlobals) && IsActiveConsoleSession())
  866. EnableDlgItem(hDlg, IDCANCEL, FALSE);
  867. //
  868. // this dialog has 2 formats, one that looks like logon dialog box,
  869. // another that looks like unlock desktop dialogbox.
  870. // we choose locked one, if session 0 is in use, and if this session is created at
  871. // active console.
  872. //
  873. if (g_IsTerminalServer &&
  874. IsActiveConsoleSession() &&
  875. NtCurrentPeb()->SessionId != 0 &&
  876. !FastUserSwitchingEnabled() &&
  877. !_ShellIsFriendlyUIActive())
  878. {
  879. TCHAR szUser[USERNAME_LENGTH + DOMAIN_LENGTH + 2];
  880. //
  881. // we are at temporary session created at console...
  882. //
  883. // check if a user is logged on at console session
  884. bSessionZeroInUse = GetSessionZeroUser(szUser);
  885. if (WinStationRegisterConsoleNotification(SERVERNAME_CURRENT, hDlg, NOTIFY_FOR_ALL_SESSIONS))
  886. {
  887. iSessionRegistrationCount++;
  888. }
  889. }
  890. else
  891. {
  892. //
  893. // this is not active console nonzero session.
  894. //
  895. bSessionZeroInUse = FALSE;
  896. }
  897. //
  898. //
  899. // now switch the control, accordigly to show logon or unlock dialog
  900. //
  901. SwitchLogonLocked(hDlg, bSessionZeroInUse, TRUE);
  902. if (g_IsTerminalServer) {
  903. BOOL fForceUPN;
  904. BOOL fPopulateFields = TRUE;
  905. BOOL fResult = FALSE;
  906. PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pAutoLogon;
  907. //
  908. // Query network WinStation client credentials for
  909. // auto logon
  910. //
  911. pGlobals->MuGlobals.pAutoLogon =
  912. LocalAlloc( LPTR, sizeof(WLX_CLIENT_CREDENTIALS_INFO_V2_0) );
  913. if (pGlobals->MuGlobals.pAutoLogon) {
  914. pGlobals->MuGlobals.pAutoLogon->dwType = WLX_CREDENTIAL_TYPE_V2_0;
  915. if (NtCurrentPeb()->SessionId != 0) {
  916. fResult = pWlxFuncs->WlxQueryTsLogonCredentials(
  917. pGlobals->MuGlobals.pAutoLogon
  918. );
  919. }
  920. if ( fResult &&
  921. (pGlobals->MuGlobals.pAutoLogon->pszUserName[0] || pGlobals->MuGlobals.pAutoLogon->pszDomain[0] )) {
  922. pAutoLogon = pGlobals->MuGlobals.pAutoLogon;
  923. fDisconnectOnTsAutoLogonFailure = pAutoLogon->fDisconnectOnLogonFailure;
  924. SetupCursor(TRUE); // hourglass cursor
  925. fForceUPN = GetProfileInt( APPLICATION_NAME, TEXT("TSForceUPN"), FALSE );
  926. if (fForceUPN)
  927. {
  928. fPopulateFields = FALSE; // never show old SAM style is UPN is forced
  929. }
  930. if (pAutoLogon->pszDomain[0] == TEXT('\0') && fForceUPN)
  931. {
  932. fForceUPN = FALSE; // domain name not provided, can't apply policy
  933. }
  934. if (fForceUPN && pGlobals->MuGlobals.pAutoLogon->pszUserName[0] )
  935. {
  936. LRESULT iDomain;
  937. HWND hwndDomain;
  938. PDOMAIN_CACHE_ENTRY Entry ;
  939. ULONG nSize;
  940. // Performance issue. We don't want to perform a UPN conversion
  941. // for local machine accounts (or unknown domains). When this
  942. // happens, the lookup will take a LONG time.
  943. hwndDomain = GetDlgItem( hDlg, IDD_LOGON_DOMAIN );
  944. iDomain = SendMessage( hwndDomain,
  945. CB_FINDSTRING,
  946. (WPARAM) -1,
  947. (LPARAM) pAutoLogon->pszDomain );
  948. fForceUPN = FALSE; // don't do the conversion
  949. if (iDomain != CB_ERR)
  950. {
  951. Entry = (PDOMAIN_CACHE_ENTRY) SendMessage( hwndDomain, CB_GETITEMDATA, (WPARAM)iDomain, 0);
  952. if ( Entry != (PDOMAIN_CACHE_ENTRY) CB_ERR && Entry != NULL)
  953. {
  954. switch (Entry->Type)
  955. {
  956. case DomainNt5:
  957. fForceUPN = TRUE; // Attempt the conversion
  958. break;
  959. }
  960. }
  961. }
  962. // Convert the domain\username into UPN format.
  963. // and make sure the dialog is in UPN form.
  964. // 2000/10/09 vtan: this function used to have two stack variables
  965. // szOldStyle and szUPNName that were TCHARs of MAX_UPN_NAME_SIZE size. The
  966. // fix for this makes these dynamically allocated to save stack space
  967. {
  968. TCHAR *pszOldStyle;
  969. TCHAR *pszUPNName;
  970. pszOldStyle = (TCHAR*)LocalAlloc(LMEM_FIXED, MAX_UPN_NAME_SIZE * sizeof(TCHAR));
  971. pszUPNName = (TCHAR*)LocalAlloc(LMEM_FIXED, MAX_UPN_NAME_SIZE * sizeof(TCHAR));
  972. if ((pszOldStyle != NULL) && (pszUPNName != NULL))
  973. {
  974. wsprintf(pszOldStyle, TEXT("%s\\%s"), pAutoLogon->pszDomain, pAutoLogon->pszUserName);
  975. nSize = MAX_PATH;
  976. fResult = TranslateName(
  977. pszOldStyle,
  978. NameSamCompatible,
  979. NameUserPrincipal,
  980. pszUPNName,
  981. &nSize
  982. );
  983. if (fResult)
  984. {
  985. // We now have the UPN form of the user account.
  986. SetDlgItemText( hDlg, IDD_LOGON_NAME, pszUPNName);
  987. }
  988. }
  989. if (pszOldStyle != NULL)
  990. {
  991. LocalFree(pszOldStyle);
  992. }
  993. if (pszUPNName != NULL)
  994. {
  995. LocalFree(pszUPNName);
  996. }
  997. }
  998. }
  999. if (fPopulateFields)
  1000. {
  1001. // display the old SAM style
  1002. SetDlgItemText( hDlg, IDD_LOGON_NAME, pAutoLogon->pszUserName );
  1003. SendMessage( GetDlgItem( hDlg, IDD_LOGON_DOMAIN ),
  1004. CB_SELECTSTRING,
  1005. (WPARAM) -1,
  1006. (LPARAM) pAutoLogon->pszDomain );
  1007. }
  1008. else
  1009. {
  1010. // Enable or disable the domain box depending on whether a UPN name has been typed
  1011. EnableDomainForUPN(GetDlgItem(hDlg, IDD_LOGON_NAME), GetDlgItem(hDlg, IDD_LOGON_DOMAIN));
  1012. // Since we're forcing UPN, hide the options dialog, but don't make it sticky
  1013. LogonShowOptions(pGlobals, hDlg, FALSE, FALSE);
  1014. }
  1015. // See if the administrator always wants password prompting
  1016. if ( TRUE == g_fHelpAssistantLogon || !pAutoLogon->fPromptForPassword ) {
  1017. SetDlgItemText( hDlg, IDD_LOGON_PASSWORD, pAutoLogon->pszPassword );
  1018. }
  1019. DCacheSetDefaultEntry(
  1020. pGlobals->Cache,
  1021. pAutoLogon->pszDomain,
  1022. NULL );
  1023. if( TRUE == g_fHelpAssistantLogon || !pGlobals->MuGlobals.pAutoLogon->fPromptForPassword )
  1024. {
  1025. FreeAutoLogonInfo( pGlobals );
  1026. // Drop through as if Enter had been pressed...
  1027. wParam = IDOK;
  1028. goto go_logon;
  1029. }
  1030. else
  1031. {
  1032. FreeAutoLogonInfo( pGlobals );
  1033. }
  1034. }
  1035. else
  1036. {
  1037. FreeAutoLogonInfo( pGlobals );
  1038. }
  1039. }
  1040. }
  1041. if (pGlobals->SmartCardLogon) {
  1042. if ( GetProfileString(APPLICATION_NAME, TEXT("DefaultPIN"), TEXT(""), PasswordBuffer, ARRAYSIZE(PasswordBuffer)) != 0 )
  1043. {
  1044. // Ensure we never write more than 127 chars into the password box
  1045. PasswordBuffer[126] = 0;
  1046. SetDlgItemText(hDlg, IDD_LOGON_PASSWORD, PasswordBuffer);
  1047. goto go_logon;
  1048. }
  1049. }
  1050. // save off the auto logon attempt.
  1051. s_fAttemptedAutoLogon = (bAutoLogon != FALSE);
  1052. if (bAutoLogon)
  1053. {
  1054. GetWindowRect(hDlg, &pGlobals->rcDialog);
  1055. SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
  1056. PostMessage(hDlg, WM_HIDEOURSELVES, 0, 0);
  1057. }
  1058. else
  1059. {
  1060. switch (_Shell_LogonDialog_Init(hDlg, SHELL_LOGONDIALOG_LOGGEDOFF))
  1061. {
  1062. case SHELL_LOGONDIALOG_NONE:
  1063. default:
  1064. {
  1065. //
  1066. // If auto logon isn't enabled, set the focus to the
  1067. // password edit control and leave.
  1068. //
  1069. return(SetPasswordFocus(hDlg));
  1070. }
  1071. case SHELL_LOGONDIALOG_LOGON:
  1072. {
  1073. GetWindowRect(hDlg, &pGlobals->rcDialog);
  1074. SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
  1075. PostMessage(hDlg, WM_HIDEOURSELVES, 0, 0);
  1076. goto go_logon;
  1077. }
  1078. case SHELL_LOGONDIALOG_EXTERNALHOST:
  1079. {
  1080. return(TRUE);
  1081. }
  1082. }
  1083. }
  1084. //
  1085. // Attempt to auto logon. If no default password
  1086. // specified, then this is a one shot attempt, which handles
  1087. // the case when auto logging on as Administrator.
  1088. //
  1089. if (HasDefaultPassword(PasswordBuffer, ARRAYSIZE(PasswordBuffer)) != FALSE)
  1090. {
  1091. // Ensure we never write more than 127 chars into the password box
  1092. PasswordBuffer[126] = 0;
  1093. SetDlgItemText(hDlg, IDD_LOGON_PASSWORD, PasswordBuffer);
  1094. }
  1095. else
  1096. {
  1097. NTSTATUS Status = STATUS_SUCCESS;
  1098. OBJECT_ATTRIBUTES ObjectAttributes;
  1099. LSA_HANDLE LsaHandle = NULL;
  1100. UNICODE_STRING SecretName;
  1101. PUNICODE_STRING SecretValue = NULL;
  1102. //
  1103. // Set up the object attributes to open the Lsa policy object
  1104. //
  1105. InitializeObjectAttributes(&ObjectAttributes,
  1106. NULL,
  1107. 0L,
  1108. (HANDLE)NULL,
  1109. NULL);
  1110. //
  1111. // Open the local LSA policy object
  1112. //
  1113. Status = LsaOpenPolicy( NULL,
  1114. &ObjectAttributes,
  1115. POLICY_VIEW_LOCAL_INFORMATION,
  1116. &LsaHandle
  1117. );
  1118. if (NT_SUCCESS(Status)) {
  1119. RtlInitUnicodeString(
  1120. &SecretName,
  1121. DEFAULT_PASSWORD_KEY
  1122. );
  1123. Status = LsaRetrievePrivateData(
  1124. LsaHandle,
  1125. &SecretName,
  1126. &SecretValue
  1127. );
  1128. if (NT_SUCCESS(Status)) {
  1129. if ( SecretValue->Length > 0 ) {
  1130. //
  1131. // If the password fits in the buffer, copy it there
  1132. // and null terminate
  1133. //
  1134. if (SecretValue->Length < sizeof(PasswordBuffer) - sizeof(WCHAR)) {
  1135. RtlCopyMemory(
  1136. PasswordBuffer,
  1137. SecretValue->Buffer,
  1138. SecretValue->Length
  1139. );
  1140. PasswordBuffer[SecretValue->Length/sizeof(WCHAR)] = L'\0';
  1141. SetDlgItemText(hDlg, IDD_LOGON_PASSWORD, PasswordBuffer);
  1142. } else {
  1143. Status = STATUS_INVALID_PARAMETER;
  1144. }
  1145. }
  1146. LsaFreeMemory(SecretValue);
  1147. }
  1148. LsaClose(LsaHandle);
  1149. }
  1150. if (!NT_SUCCESS(Status))
  1151. {
  1152. WriteProfileString( APPLICATION_NAME, AUTO_ADMIN_LOGON_KEY, TEXT("0") );
  1153. }
  1154. }
  1155. go_logon:
  1156. // Drop through as if Enter had been pressed...
  1157. wParam = IDOK;
  1158. }
  1159. // nb: deliberate drop through from above
  1160. case WM_COMMAND:
  1161. switch (HIWORD(wParam))
  1162. {
  1163. case CBN_DROPDOWN:
  1164. case CBN_SELCHANGE:
  1165. DebugLog((DEB_TRACE, "Got CBN_DROPDOWN\n"));
  1166. if ( !pGlobals->ListPopulated )
  1167. {
  1168. WCHAR Buffer[ 2 ];
  1169. if ( DCacheGetCacheState( pGlobals->Cache ) < DomainCacheRegistryCache )
  1170. {
  1171. pWlxFuncs->WlxDialogBoxParam(
  1172. pGlobals->hGlobalWlx,
  1173. hDllInstance,
  1174. (LPTSTR) IDD_WAITDOMAINCACHEVALID_DIALOG,
  1175. hDlg,
  1176. DomainCacheDlgProc,
  1177. (LPARAM) pGlobals );
  1178. }
  1179. if ( DCacheGetCacheState( pGlobals->Cache ) == DomainCacheReady )
  1180. {
  1181. PDOMAIN_CACHE_ARRAY ActiveArrayBackup ;
  1182. ActiveArrayBackup = pGlobals->ActiveArray;
  1183. pGlobals->ActiveArray = DCacheCopyCacheArray( pGlobals->Cache );
  1184. if ( pGlobals->ActiveArray )
  1185. {
  1186. DCacheFreeArray( ActiveArrayBackup ); // Not needed anymore
  1187. Buffer[ 0 ] = (WCHAR) GetWindowLongPtr( GetDlgItem( hDlg, IDD_LOGON_DOMAIN ),
  1188. GWLP_USERDATA );
  1189. Buffer[ 1 ] = L'\0';
  1190. DCachePopulateListBoxFromArray(
  1191. pGlobals->ActiveArray,
  1192. GetDlgItem( hDlg, IDD_LOGON_DOMAIN ),
  1193. Buffer );
  1194. pGlobals->ListPopulated = TRUE ;
  1195. }
  1196. else
  1197. {
  1198. //
  1199. // Restore the old array, otherwise the pointers in the
  1200. // combo items will point to freed memory
  1201. //
  1202. pGlobals->ActiveArray = ActiveArrayBackup ;
  1203. }
  1204. }
  1205. }
  1206. break;
  1207. default:
  1208. switch (LOWORD(wParam))
  1209. {
  1210. case IDD_LOGON_NAME:
  1211. {
  1212. switch(HIWORD(wParam))
  1213. {
  1214. case EN_CHANGE:
  1215. {
  1216. EnableDomainForUPN((HWND) lParam, GetDlgItem(hDlg, IDD_LOGON_DOMAIN));
  1217. return TRUE;
  1218. }
  1219. }
  1220. }
  1221. break;
  1222. case IDOK:
  1223. //
  1224. // Deal with combo-box UI requirements
  1225. //
  1226. if (HandleComboBoxOK(hDlg, IDD_LOGON_DOMAIN))
  1227. {
  1228. return(TRUE);
  1229. }
  1230. Result = AttemptLogon( hDlg );
  1231. if (Result == MSGINA_DLG_FAILURE)
  1232. {
  1233. if (!fDisconnectOnTsAutoLogonFailure &&
  1234. !g_fHelpAssistantLogon ) {
  1235. // Let the user try again
  1236. // Clear the password field and set focus to it
  1237. SetDlgItemText(hDlg, IDD_LOGON_PASSWORD, NULL);
  1238. SetPasswordFocus(hDlg);
  1239. } else {
  1240. bSmartCardInserted = FALSE;
  1241. EndDialog(hDlg, MSGINA_DLG_USER_LOGOFF);
  1242. }
  1243. return(TRUE);
  1244. }
  1245. return(TRUE);
  1246. case IDCANCEL:
  1247. {
  1248. if (!_Shell_LogonDialog_Cancel())
  1249. {
  1250. // If this is TS and the user hit ESC at the smart card pin prompt
  1251. // we want to switch to the password dialog
  1252. if (/*!g_Console && !IsActiveConsoleSession() && */pGlobals->SmartCardLogon) {
  1253. EndDialog(hDlg, bSmartCardInserted ? MSGINA_DLG_SMARTCARD_REMOVED : MSGINA_DLG_FAILURE);
  1254. bSmartCardInserted = FALSE;
  1255. return TRUE;
  1256. }
  1257. //
  1258. // Allow logon screen to go away if not at console
  1259. //
  1260. bSmartCardInserted = FALSE;
  1261. EndDialog(hDlg, !g_Console ? MSGINA_DLG_USER_LOGOFF
  1262. : MSGINA_DLG_FAILURE);
  1263. if (g_Console && !IsActiveConsoleSession()) {
  1264. pWlxFuncs->WlxDisconnect();
  1265. }
  1266. }
  1267. return(TRUE);
  1268. }
  1269. case IDD_LOGON_SHUTDOWN:
  1270. //
  1271. // This is a normal shutdown request
  1272. //
  1273. // Check they know what they're doing and find
  1274. // out if they want to reboot too.
  1275. //
  1276. // Note that we definitely don't want disconnect or logofff
  1277. // here since no one is logged on
  1278. Result = WinlogonShutdownDialog(hDlg, pGlobals, (SHTDN_DISCONNECT | SHTDN_LOGOFF));
  1279. if (DLG_SHUTDOWN(Result))
  1280. {
  1281. _Shell_LogonDialog_ShuttingDown();
  1282. bSmartCardInserted = FALSE;
  1283. EndDialog(hDlg, Result);
  1284. }
  1285. return(TRUE);
  1286. case IDD_LOGON_OPTIONS:
  1287. LogonShowOptions(pGlobals, hDlg, !pGlobals->LogonOptionsShown, TRUE);
  1288. return(TRUE);
  1289. }
  1290. break;
  1291. }
  1292. break;
  1293. case WM_TIMER:
  1294. {
  1295. switch (wParam)
  1296. {
  1297. case 0:
  1298. {
  1299. HDC hDC;
  1300. RtlEnterCriticalSection(&pGlobals->csGlobals);
  1301. if ( pGlobals->LogonInProgress )
  1302. {
  1303. if (pGlobals->cxBand != 0)
  1304. {
  1305. pGlobals->xBandOffset = (pGlobals->xBandOffset+5) % pGlobals->cxBand;
  1306. }
  1307. }
  1308. else
  1309. {
  1310. pGlobals->xBandOffset = 0;
  1311. KillTimer(hDlg, 0);
  1312. }
  1313. RtlLeaveCriticalSection(&pGlobals->csGlobals);
  1314. hDC = GetDC(hDlg);
  1315. if ( hDC )
  1316. {
  1317. PaintBranding(hDlg, hDC, pGlobals->xBandOffset, TRUE, TRUE, COLOR_BTNFACE);
  1318. ReleaseDC(hDlg, hDC);
  1319. }
  1320. return FALSE;
  1321. }
  1322. case TIMER_MYLANGUAGECHECK:
  1323. {
  1324. LayoutCheckHandler(hDlg, LAYOUT_DEF_USER);
  1325. break;
  1326. }
  1327. }
  1328. break;
  1329. }
  1330. case WM_ERASEBKGND:
  1331. return PaintBranding(hDlg, (HDC)wParam, 0, FALSE, TRUE, COLOR_BTNFACE);
  1332. case WM_QUERYNEWPALETTE:
  1333. return BrandingQueryNewPalete(hDlg);
  1334. case WM_PALETTECHANGED:
  1335. return BrandingPaletteChanged(hDlg, (HWND)wParam);
  1336. case WM_LOGONCOMPLETE:
  1337. {
  1338. _Shell_LogonDialog_LogonCompleted(lParam, pGlobals->UserName, pGlobals->Domain);
  1339. Result = lParam;
  1340. //
  1341. // Discard the logon in progress dialog if one is displayed
  1342. //
  1343. RtlEnterCriticalSection(&pGlobals->csGlobals);
  1344. pGlobals->LogonInProgress = FALSE;
  1345. RtlLeaveCriticalSection(&pGlobals->csGlobals);
  1346. AttemptLogonSetControls(pGlobals, hDlg);
  1347. if (Result == MSGINA_DLG_FAILURE)
  1348. {
  1349. if (fDisconnectOnTsAutoLogonFailure || g_fHelpAssistantLogon)
  1350. {
  1351. //
  1352. // If TermSrv Internet Connector is on
  1353. // don't allow a second chance at the logon dialog
  1354. //
  1355. //
  1356. // disconnect immediatly when fail to logon as helpassisant
  1357. //
  1358. bSmartCardInserted = FALSE;
  1359. EndDialog(hDlg, MSGINA_DLG_USER_LOGOFF);
  1360. break;
  1361. }
  1362. if (s_fAttemptedAutoLogon != FALSE)
  1363. {
  1364. s_fAttemptedAutoLogon = FALSE;
  1365. switch (_Shell_LogonDialog_Init(hDlg, SHELL_LOGONDIALOG_LOGGEDOFF))
  1366. {
  1367. case SHELL_LOGONDIALOG_LOGON:
  1368. goto go_logon;
  1369. break;
  1370. case SHELL_LOGONDIALOG_NONE:
  1371. case SHELL_LOGONDIALOG_EXTERNALHOST:
  1372. default:
  1373. break;
  1374. }
  1375. }
  1376. if (!_Shell_LogonDialog_UIHostActive())
  1377. {
  1378. // Let the user try again - clear the password
  1379. SetDlgItemText(hDlg, IDD_LOGON_PASSWORD, NULL);
  1380. SetPasswordFocus(hDlg);
  1381. // the logon failed, so lets ensure we show the options pane so they can update
  1382. // their domain selection if needed.
  1383. if ( !pGlobals->LogonOptionsShown )
  1384. LogonShowOptions(pGlobals, hDlg, TRUE, FALSE);
  1385. }
  1386. return(TRUE);
  1387. }
  1388. //
  1389. // Initialize the TS Profile path and Home dir globals. Also get
  1390. // all TS specific user-config data which is used in winlogon
  1391. //
  1392. if (!g_Console) //only do this for non-console sessions
  1393. {
  1394. HANDLE ImpersonationHandle;
  1395. BOOL rc;
  1396. // DbgPrint("Calling WlxQueryTerminalServicesData() for %ws %ws\n",pGlobals->UserName,pGlobals->Domain);
  1397. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  1398. ASSERT(ImpersonationHandle);
  1399. if (ImpersonationHandle != NULL)
  1400. {
  1401. //For WlxQueryTerminalServicesData() we need NT type names rather than
  1402. //UPN names, if we pass a UPN name it will try to resolve it
  1403. //(through ADS API) to NT name anyway. Besides, ADS API cannot
  1404. //resolve some UPN names and takes a long time to execute.
  1405. //So let's pass in an NT user and domain names.
  1406. PUNICODE_STRING pFlatUser ;
  1407. PUNICODE_STRING pFlatDomain ;
  1408. LPWSTR wszFlatUserName, wszFlatDomainName;
  1409. if(NT_SUCCESS(LsaGetUserName( &pFlatUser, &pFlatDomain )))
  1410. {
  1411. wszFlatUserName = (LPWSTR)LocalAlloc(LPTR,
  1412. pFlatUser->Length+sizeof(WCHAR));
  1413. wszFlatDomainName = (LPWSTR)LocalAlloc(LPTR,
  1414. pFlatDomain->Length+sizeof(WCHAR));
  1415. if(wszFlatUserName && wszFlatDomainName)
  1416. {
  1417. memcpy(wszFlatUserName, pFlatUser->Buffer,
  1418. pFlatUser->Length);
  1419. memcpy(wszFlatDomainName, pFlatDomain->Buffer,
  1420. pFlatDomain->Length);
  1421. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1422. &pGlobals->MuGlobals.TSData, wszFlatUserName, wszFlatDomainName);
  1423. }
  1424. else
  1425. {
  1426. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1427. &pGlobals->MuGlobals.TSData,pGlobals->UserName , pGlobals->Domain);
  1428. }
  1429. if(wszFlatUserName)
  1430. {
  1431. LocalFree(wszFlatUserName);
  1432. }
  1433. if(wszFlatDomainName)
  1434. {
  1435. LocalFree(wszFlatDomainName);
  1436. }
  1437. LsaFreeMemory( pFlatUser->Buffer );
  1438. LsaFreeMemory( pFlatUser );
  1439. LsaFreeMemory( pFlatDomain->Buffer );
  1440. LsaFreeMemory( pFlatDomain );
  1441. }
  1442. else
  1443. {
  1444. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1445. &pGlobals->MuGlobals.TSData,pGlobals->UserName , pGlobals->Domain);
  1446. }
  1447. rc = StopImpersonating(ImpersonationHandle);
  1448. ASSERT(rc);
  1449. }
  1450. }
  1451. bSmartCardInserted = FALSE;
  1452. EndDialog( hDlg, Result );
  1453. break;
  1454. }
  1455. case WM_HANDLEFAILEDLOGON:
  1456. {
  1457. INT_PTR Result;
  1458. if (_Shell_LogonDialog_LogonDisplayError(g_failinfo.Status, g_failinfo.SubStatus))
  1459. {
  1460. if (!IsWindowVisible(hDlg))
  1461. {
  1462. //
  1463. // The dialog was hidden for automatic logon. An error occurred.
  1464. // Show the dialog so the error can be seen and the problem corrected.
  1465. //
  1466. SetWindowPos(hDlg, NULL, 0, 0, pGlobals->rcDialog.right - pGlobals->rcDialog.left, pGlobals->rcDialog.bottom - pGlobals->rcDialog.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
  1467. ShowWindow(hDlg, SW_SHOW);
  1468. }
  1469. Result = HandleFailedLogon(hDlg);
  1470. }
  1471. else
  1472. {
  1473. Result = MSGINA_DLG_FAILURE;
  1474. }
  1475. SendMessage(hDlg, WM_LOGONCOMPLETE, 0, (LPARAM) Result);
  1476. return TRUE;
  1477. }
  1478. case WLX_WM_SAS:
  1479. // Give the consumer logon part a chance to handle the SAS
  1480. // or to key off the fact that a SAS has occurred.
  1481. (BOOL)_Shell_LogonDialog_DlgProc(hDlg, message, wParam, lParam);
  1482. if ((wParam == WLX_SAS_TYPE_TIMEOUT) ||
  1483. (wParam == WLX_SAS_TYPE_SCRNSVR_TIMEOUT) )
  1484. {
  1485. //
  1486. // If this was a timeout, return false, and let winlogon
  1487. // kill us later
  1488. //
  1489. bSmartCardInserted = FALSE;
  1490. return(FALSE);
  1491. }
  1492. if ( wParam == WLX_SAS_TYPE_SC_INSERT ) {
  1493. //
  1494. // If a password logon is already taking place then ignore this sas
  1495. //
  1496. if (pGlobals->LogonInProgress && !pGlobals->SmartCardLogon)
  1497. {
  1498. return(TRUE);
  1499. }
  1500. bSmartCardInserted = TRUE;
  1501. EndDialog( hDlg, MSGINA_DLG_SMARTCARD_INSERTED );
  1502. } else if ( wParam == WLX_SAS_TYPE_SC_REMOVE ) {
  1503. //
  1504. // If a password logon is already taking place then ignore this sas
  1505. //
  1506. if (pGlobals->LogonInProgress && !pGlobals->SmartCardLogon)
  1507. {
  1508. return(TRUE);
  1509. }
  1510. if ( bSmartCardInserted ) {
  1511. bSmartCardInserted = FALSE;
  1512. EndDialog( hDlg, MSGINA_DLG_SMARTCARD_REMOVED );
  1513. } else if ( pGlobals->SmartCardLogon ) {
  1514. // If this was a s/c initiated logon, then cancel
  1515. // the dialog. Otherwise, ignore it.
  1516. bSmartCardInserted = FALSE;
  1517. EndDialog( hDlg, MSGINA_DLG_FAILURE );
  1518. }
  1519. } else if ( wParam == WLX_SAS_TYPE_AUTHENTICATED )
  1520. {
  1521. bSmartCardInserted = FALSE;
  1522. _Shell_LogonDialog_LogonCompleted(MSGINA_DLG_SWITCH_CONSOLE, pGlobals->UserName, pGlobals->Domain);
  1523. EndDialog( hDlg, MSGINA_DLG_SWITCH_CONSOLE );
  1524. }
  1525. return(TRUE);
  1526. case WM_WTSSESSION_CHANGE:
  1527. ASSERT(iSessionRegistrationCount < 2);
  1528. //
  1529. // its possible, that we unregister for notification in wm_destroy and still receive this notification,
  1530. // as the notification may already have been sent.
  1531. //
  1532. if (iSessionRegistrationCount == 1)
  1533. {
  1534. if (lParam == 0)
  1535. {
  1536. //
  1537. // we are interested only in logon/logoff messages from session 0.
  1538. //
  1539. if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_LOGOFF)
  1540. {
  1541. bSessionZeroInUse = (wParam == WTS_SESSION_LOGON);
  1542. SwitchLogonLocked(hDlg, bSessionZeroInUse, FALSE);
  1543. }
  1544. }
  1545. }
  1546. break;
  1547. case WM_DESTROY:
  1548. // if registered for notification unregister now.
  1549. if (iSessionRegistrationCount)
  1550. {
  1551. WinStationUnRegisterConsoleNotification (SERVERNAME_CURRENT, hDlg);
  1552. iSessionRegistrationCount--;
  1553. ASSERT(iSessionRegistrationCount == 0);
  1554. }
  1555. _Shell_LogonDialog_Destroy();
  1556. FreeLayoutInfo(LAYOUT_DEF_USER);
  1557. if ( pGlobals->ActiveArray )
  1558. {
  1559. DCacheFreeArray( pGlobals->ActiveArray );
  1560. pGlobals->ActiveArray = NULL ;
  1561. }
  1562. RemoveWindowSubclass(GetDlgItem(hDlg, IDD_LOGON_NAME), DisableEditSubClassProc, IDD_LOGON_NAME);
  1563. RemoveWindowSubclass(GetDlgItem(hDlg, IDD_LOGON_PASSWORD), DisableEditSubClassProc, IDD_LOGON_PASSWORD);
  1564. break;
  1565. case WM_HIDEOURSELVES:
  1566. ShowWindow(hDlg, SW_HIDE);
  1567. break;
  1568. default:
  1569. if (_Shell_LogonDialog_DlgProc(hDlg, message, wParam, lParam) != FALSE)
  1570. {
  1571. return(TRUE);
  1572. }
  1573. }
  1574. return(FALSE);
  1575. }
  1576. /***************************************************************************\
  1577. * FUNCTION: LogonDlgInit
  1578. *
  1579. * PURPOSE: Handles initialization of logon dialog
  1580. *
  1581. * RETURNS: TRUE on success, FALSE on failure
  1582. *
  1583. * HISTORY:
  1584. *
  1585. * 12-09-91 Davidc Created.
  1586. *
  1587. \***************************************************************************/
  1588. BOOL
  1589. LogonDlgInit(
  1590. HWND hDlg,
  1591. BOOL bAutoLogon,
  1592. DWORD SasType
  1593. )
  1594. {
  1595. PGLOBALS pGlobals = (PGLOBALS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1596. LPTSTR String = NULL;
  1597. TCHAR LogonMsg[MAX_PATH];
  1598. BOOL RemoveLegalBanner;
  1599. BOOL ShowOptions = FALSE;
  1600. HKEY hKey;
  1601. int err;
  1602. DWORD RasDisable;
  1603. DWORD RasForce;
  1604. STRING Narrow;
  1605. SECURITY_STATUS Status;
  1606. RECT rc, rc2;
  1607. BOOL bHasLangIcon = FALSE;
  1608. ULONG CacheFlags ;
  1609. //
  1610. // Populate Security Package List:
  1611. //
  1612. RtlInitString( &Narrow, MICROSOFT_KERBEROS_NAME_A );
  1613. Status = LsaLookupAuthenticationPackage(
  1614. pGlobals->LsaHandle,
  1615. &Narrow,
  1616. &pGlobals->SmartCardLogonPackage );
  1617. //
  1618. // this (potential) failure is not critical. If it fails, then s/c logons later
  1619. // will fail.
  1620. //
  1621. RtlInitString( &Narrow, NEGOSSP_NAME_A );
  1622. Status = LsaLookupAuthenticationPackage(
  1623. pGlobals->LsaHandle,
  1624. &Narrow,
  1625. &pGlobals->PasswordLogonPackage );
  1626. if ( !NT_SUCCESS( Status ) )
  1627. {
  1628. return FALSE ;
  1629. }
  1630. //
  1631. // Update the caption for certain banks
  1632. //
  1633. SetWelcomeCaption(hDlg);
  1634. //
  1635. // Get username and domain last used to login
  1636. //
  1637. //
  1638. // Ignore the default user name unless on the active console
  1639. //
  1640. if (IsActiveConsoleSession())
  1641. {
  1642. String = NULL;
  1643. if ( pGlobals->AutoAdminLogon && pGlobals->IgnoreAutoAdminLogon)
  1644. {
  1645. String = AllocAndGetProfileString(APPLICATION_NAME, TEMP_DEFAULT_USER_NAME_KEY, TEXT(""));
  1646. }
  1647. if ( (!String) || (!String[0]) )
  1648. {
  1649. if ( String )
  1650. {
  1651. Free(String);
  1652. }
  1653. String = AllocAndGetProfileString(APPLICATION_NAME, DEFAULT_USER_NAME_KEY, TEXT(""));
  1654. }
  1655. if ( String )
  1656. {
  1657. if (!bAutoLogon && (ReadWinlogonBoolValue(DONT_DISPLAY_LAST_USER_KEY, FALSE) == TRUE))
  1658. {
  1659. String[0] = 0;
  1660. }
  1661. SetDlgItemText(hDlg, IDD_LOGON_NAME, String);
  1662. Free(String);
  1663. }
  1664. }
  1665. GetProfileString( APPLICATION_NAME,
  1666. DEFAULT_DOMAIN_NAME_KEY,
  1667. TEXT(""),
  1668. pGlobals->Domain,
  1669. MAX_STRING_BYTES );
  1670. if ( !DCacheValidateCache( pGlobals->Cache ) )
  1671. {
  1672. ASSERT( pGlobals->ActiveArray == NULL );
  1673. DCacheUpdateMinimal( pGlobals->Cache, pGlobals->Domain, TRUE );
  1674. }
  1675. else
  1676. {
  1677. //
  1678. // Set the current default:
  1679. //
  1680. DCacheSetDefaultEntry( pGlobals->Cache,
  1681. pGlobals->Domain,
  1682. NULL );
  1683. }
  1684. CacheFlags = DCacheGetFlags( pGlobals->Cache );
  1685. if ( ( CacheFlags & DCACHE_NO_CACHE ) &&
  1686. ( SafeBootMode != SAFEBOOT_MINIMAL ) &&
  1687. ( ( pGlobals->AutoAdminLogon ) ||
  1688. ( CacheFlags & DCACHE_DEF_UNKNOWN ) ) )
  1689. {
  1690. //
  1691. // Must wait for the cache to be populated
  1692. //
  1693. DCacheUpdateFull( pGlobals->Cache,
  1694. pGlobals->Domain );
  1695. CacheFlags = DCacheGetFlags( pGlobals->Cache );
  1696. }
  1697. pGlobals->ListPopulated = FALSE ;
  1698. pGlobals->ActiveArray = DCacheCopyCacheArray( pGlobals->Cache );
  1699. if ( pGlobals->ActiveArray )
  1700. {
  1701. DCachePopulateListBoxFromArray( pGlobals->ActiveArray,
  1702. GetDlgItem( hDlg, IDD_LOGON_DOMAIN ),
  1703. NULL );
  1704. }
  1705. else
  1706. {
  1707. EndDialog( hDlg, MSGINA_DLG_FAILURE );
  1708. }
  1709. pGlobals->ShowRasBox = FALSE;
  1710. if (g_Console) {
  1711. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1712. TEXT("Software\\Microsoft\\RAS"),
  1713. 0,
  1714. KEY_READ,
  1715. & hKey );
  1716. if ( err == 0 )
  1717. {
  1718. RegCloseKey( hKey );
  1719. if ( GetRasDialOutProtocols() &&
  1720. ( ( CacheFlags & DCACHE_MEMBER ) != 0 ) )
  1721. {
  1722. pGlobals->ShowRasBox = TRUE;
  1723. }
  1724. }
  1725. }
  1726. //
  1727. // If the audit log is full then display the banner, otherwise
  1728. // load the text from the resource if that gives us a string
  1729. // then set the control.
  1730. //
  1731. // Should neither of these apply then remove the control.
  1732. // The log full info is only displayed at the console so we
  1733. // don't disclose too much info in TS sessions.
  1734. //
  1735. RemoveLegalBanner = FALSE;
  1736. if ( pGlobals->AuditLogFull && !GetSystemMetrics(SM_REMOTESESSION))
  1737. {
  1738. if ( LoadString( hDllInstance, IDS_LOGON_LOG_FULL, LogonMsg, MAX_PATH ) )
  1739. {
  1740. SetDlgItemText( hDlg, IDD_LOGON_ANNOUNCE, LogonMsg );
  1741. }
  1742. else
  1743. {
  1744. RemoveLegalBanner = TRUE;
  1745. }
  1746. }
  1747. else
  1748. {
  1749. String = AllocAndGetProfileString( APPLICATION_NAME,
  1750. LOGON_MSG_KEY, TEXT("") );
  1751. if ( String )
  1752. {
  1753. if ( *String )
  1754. {
  1755. SetDlgItemText( hDlg, IDD_LOGON_ANNOUNCE, String );
  1756. }
  1757. else
  1758. {
  1759. RemoveLegalBanner = TRUE;
  1760. }
  1761. Free( String );
  1762. }
  1763. else
  1764. {
  1765. RemoveLegalBanner = TRUE;
  1766. }
  1767. }
  1768. if ( RemoveLegalBanner )
  1769. {
  1770. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_ANNOUNCE), &rc);
  1771. MoveControls(hDlg, ctrlNoLegalBanner,
  1772. sizeof(ctrlNoLegalBanner)/sizeof(ctrlNoLegalBanner[0]),
  1773. 0, rc.top-rc.bottom,
  1774. TRUE);
  1775. ShowDlgItem(hDlg, IDD_LOGON_ANNOUNCE, FALSE);
  1776. }
  1777. //
  1778. // Smart Card Specific Stuff:
  1779. //
  1780. if ( SasType == WLX_SAS_TYPE_SC_INSERT )
  1781. {
  1782. //
  1783. // remove the user name fields
  1784. //
  1785. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_NAME), &rc);
  1786. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_PASSWORD), &rc2);
  1787. MoveControls(hDlg, ctrlNoUserName,
  1788. sizeof(ctrlNoUserName)/sizeof(ctrlNoUserName[0]),
  1789. 0, -(rc2.top-rc.top),
  1790. TRUE);
  1791. ShowDlgItem(hDlg, IDD_LOGON_NAME_LABEL, FALSE);
  1792. EnableDlgItem(hDlg, IDD_LOGON_NAME_LABEL, FALSE);
  1793. ShowDlgItem(hDlg, IDD_LOGON_NAME, FALSE);
  1794. EnableDlgItem(hDlg, IDD_LOGON_NAME, FALSE);
  1795. SetDlgItemText( hDlg, IDD_LOGON_NAME, TEXT(""));
  1796. LoadString(hDllInstance, IDS_PIN, LogonMsg, MAX_PATH);
  1797. SetDlgItemText( hDlg, IDD_LOGON_PASSWORD_LABEL, LogonMsg );
  1798. pGlobals->SmartCardLogon = TRUE;
  1799. }
  1800. else
  1801. {
  1802. pGlobals->SmartCardLogon = FALSE;
  1803. }
  1804. //
  1805. // If this is safe boot and/or we are not part of a domain then lets
  1806. // remove the domain and nix out the RAS box.
  1807. //
  1808. if ((SafeBootMode == SAFEBOOT_MINIMAL)
  1809. || (!IsMachineDomainMember())
  1810. || (SasType == WLX_SAS_TYPE_SC_INSERT)
  1811. || (ForceNoDomainUI()))
  1812. {
  1813. ShowDlgItem(hDlg, IDD_LOGON_DOMAIN_LABEL, FALSE);
  1814. EnableDlgItem(hDlg, IDD_LOGON_DOMAIN_LABEL, FALSE);
  1815. ShowDlgItem(hDlg, IDD_LOGON_DOMAIN, FALSE);
  1816. EnableDlgItem(hDlg, IDD_LOGON_DOMAIN, FALSE);
  1817. pGlobals->ShowDomainBox = FALSE;
  1818. // Shorten the window since the domain box isn't used
  1819. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_PASSWORD), &rc);
  1820. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_DOMAIN), &rc2);
  1821. MoveControls(hDlg, ctrlNoDomain,
  1822. ARRAYSIZE(ctrlNoDomain),
  1823. 0, -(rc2.bottom-rc.bottom),
  1824. TRUE);
  1825. }
  1826. else
  1827. {
  1828. pGlobals->ShowDomainBox = TRUE;
  1829. }
  1830. bHasLangIcon = DisplayLanguageIcon(hDlg, LAYOUT_DEF_USER, GetKeyboardLayout(0));
  1831. //
  1832. // Handle showing the RAS box if needed
  1833. //
  1834. if ( pGlobals->ShowRasBox )
  1835. {
  1836. RasDisable = GetProfileInt( APPLICATION_NAME, RAS_DISABLE, 0 );
  1837. RasForce = GetProfileInt( APPLICATION_NAME, RAS_FORCE, 0 );
  1838. if (RasForce)
  1839. {
  1840. CheckDlgButton( hDlg, IDD_LOGON_RASBOX, 1 );
  1841. }
  1842. else
  1843. {
  1844. CheckDlgButton( hDlg, IDD_LOGON_RASBOX, 0 );
  1845. }
  1846. // SM_CLEANBOOT tells us we are in safe mode. In this case, disable since tapisrv isn't started
  1847. if (RasDisable || RasForce || GetSystemMetrics(SM_CLEANBOOT))
  1848. {
  1849. EnableDlgItem(hDlg, IDD_LOGON_RASBOX, FALSE);
  1850. }
  1851. else
  1852. {
  1853. EnableDlgItem(hDlg, IDD_LOGON_RASBOX, TRUE);
  1854. }
  1855. }
  1856. else
  1857. {
  1858. // If the domain box is hidden, then we'll have to shorten the dialog by the distance
  1859. // between the RAS box and the password box instead of the distance between the
  1860. // RAS box and the domain box since the RAS and Domain boxes will be on top of each other
  1861. BOOL fUsePassword = !pGlobals->ShowDomainBox;
  1862. CheckDlgButton( hDlg, IDD_LOGON_RASBOX, 0 );
  1863. EnableDlgItem(hDlg, IDD_LOGON_RASBOX, FALSE);
  1864. ShowDlgItem(hDlg, IDD_LOGON_RASBOX, FALSE);
  1865. GetWindowRect(GetDlgItem(hDlg, fUsePassword ? IDD_LOGON_PASSWORD : IDD_LOGON_DOMAIN), &rc);
  1866. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_RASBOX), &rc2);
  1867. if (!bHasLangIcon)
  1868. {
  1869. MoveControls(hDlg, ctrlNoRAS,
  1870. sizeof(ctrlNoRAS)/sizeof(ctrlNoRAS[0]),
  1871. 0, -(rc2.bottom-rc.bottom),
  1872. TRUE);
  1873. }
  1874. }
  1875. // Centre the window on the screen and bring it to the front
  1876. pGlobals->xBandOffset = 0; // band is not animated yet
  1877. SizeForBranding(hDlg, TRUE);
  1878. // Position the window at the same coords as the welcome window
  1879. if ((pGlobals->rcWelcome.right - pGlobals->rcWelcome.left) != 0)
  1880. {
  1881. SetWindowPos(hDlg, NULL, pGlobals->rcWelcome.left, pGlobals->rcWelcome.top,
  1882. 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  1883. }
  1884. else
  1885. {
  1886. CentreWindow(hDlg);
  1887. }
  1888. //
  1889. // Handle showing and hiding the logon bits
  1890. //
  1891. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  1892. &hKey) == ERROR_SUCCESS)
  1893. {
  1894. DWORD dwType, dwSize = sizeof(ShowOptions);
  1895. RegQueryValueEx (hKey, SHOW_LOGON_OPTIONS, NULL, &dwType,
  1896. (LPBYTE)&ShowOptions, &dwSize);
  1897. RegCloseKey (hKey);
  1898. }
  1899. pGlobals->LogonOptionsShown = TRUE;
  1900. LogonShowOptions(pGlobals, hDlg, ShowOptions, TRUE);
  1901. // Success
  1902. return TRUE;
  1903. }
  1904. /****************************************************************************\
  1905. *
  1906. * FUNCTION: LogonShowOptions
  1907. *
  1908. * PURPOSE: Hide the options part of the logon dialog
  1909. *
  1910. * RETURNS: Nothing
  1911. *
  1912. * HISTORY:
  1913. *
  1914. * 15-dec-97 daviddv - Created
  1915. *
  1916. \****************************************************************************/
  1917. VOID LogonShowOptions(PGLOBALS pGlobals, HWND hDlg, BOOL fShow, BOOL fSticky)
  1918. {
  1919. HKEY hKey;
  1920. RECT rc, rc2;
  1921. INT dy = 0;
  1922. INT dx = 0;
  1923. TCHAR szBuffer[32];
  1924. BOOL bHasLangIcon = TRUE;
  1925. DWORD RasDisable;
  1926. DWORD RasForce;
  1927. if ( pGlobals->LogonOptionsShown != fShow )
  1928. {
  1929. BOOL bShutdownWithoutLogon;
  1930. //
  1931. // Show/hide domain if it is present in the dialog
  1932. //
  1933. if (pGlobals->ShowDomainBox)
  1934. {
  1935. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_PASSWORD), &rc);
  1936. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_DOMAIN), &rc2);
  1937. dy += rc2.bottom-rc.bottom;
  1938. }
  1939. //
  1940. // If RAS is present then lets ensure that we remove that.
  1941. //
  1942. if (GetKeyboardLayoutList(0,NULL) < 2)
  1943. {
  1944. bHasLangIcon = FALSE;
  1945. }
  1946. if ( pGlobals->ShowRasBox || bHasLangIcon)
  1947. {
  1948. // Since the domain box may be hidden with the RAS box directly over
  1949. // top of it, we may need to use the space between the RAS box and the password
  1950. // box
  1951. BOOL fUsePassword = !pGlobals->ShowDomainBox;
  1952. GetWindowRect(GetDlgItem(hDlg, fUsePassword ? IDD_LOGON_PASSWORD : IDD_LOGON_DOMAIN), &rc);
  1953. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_RASBOX), &rc2);
  1954. dy += rc2.bottom-rc.bottom;
  1955. }
  1956. MoveControls(hDlg, ctrlNoRAS,
  1957. sizeof(ctrlNoRAS)/sizeof(ctrlNoRAS[0]),
  1958. 0, fShow ? dy:-dy,
  1959. TRUE);
  1960. // Handle showing or hiding the shutdown button
  1961. // and moving other controls.
  1962. ShowDlgItem(hDlg, IDD_KBLAYOUT_ICON, fShow);
  1963. EnableWindow(GetDlgItem(hDlg, IDD_KBLAYOUT_ICON), fShow);
  1964. ShowDlgItem(hDlg, IDD_LOGON_SHUTDOWN, fShow);
  1965. // Move the OK and Cancel buttons over if we are hiding shutdown
  1966. // ..Calculate one "button space". Assumes shutdown will always be on the left of options
  1967. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_SHUTDOWN), &rc);
  1968. GetWindowRect(GetDlgItem(hDlg, IDD_LOGON_OPTIONS), &rc2);
  1969. dx = rc2.left - rc.left;
  1970. // Move OK and Cancel left or right 1 button space
  1971. MoveControls(hDlg, ctrlNoShutdown,
  1972. sizeof(ctrlNoShutdown)/sizeof(ctrlNoShutdown[0]),
  1973. fShow ? -dx:dx, 0,
  1974. FALSE);
  1975. //
  1976. // if ShutdownWithoutLogon, use the proper 3 buttons: OK, Shutdown and Cancel
  1977. // instead of the 2 buttons OK and Cancel
  1978. //
  1979. if ( SafeBootMode == SAFEBOOT_MINIMAL )
  1980. {
  1981. bShutdownWithoutLogon = TRUE ;
  1982. }
  1983. else if (IsthisUnlockWindowsDialog() || !IsActiveConsoleSession())
  1984. {
  1985. bShutdownWithoutLogon = FALSE ;
  1986. }
  1987. else
  1988. {
  1989. bShutdownWithoutLogon = ReadWinlogonBoolValue(SHUTDOWN_WITHOUT_LOGON_KEY, TRUE);
  1990. }
  1991. EnableDlgItem(hDlg, IDD_LOGON_SHUTDOWN, (fShow) &&
  1992. (bShutdownWithoutLogon));
  1993. if ( pGlobals->ShowRasBox )
  1994. {
  1995. ShowDlgItem(hDlg, IDD_LOGON_RASBOX, fShow);
  1996. RasDisable = GetProfileInt(APPLICATION_NAME, RAS_DISABLE,0);
  1997. RasForce = GetProfileInt(APPLICATION_NAME, RAS_FORCE, 0);
  1998. // Never enable RAS for cleanboot
  1999. if (!GetSystemMetrics(SM_CLEANBOOT) && !RasForce && !RasDisable)
  2000. {
  2001. EnableWindow(GetDlgItem(hDlg, IDD_LOGON_RASBOX), fShow);
  2002. }
  2003. }
  2004. if ( pGlobals->ShowDomainBox )
  2005. {
  2006. ShowDlgItem(hDlg, IDD_LOGON_DOMAIN_LABEL, fShow);
  2007. EnableWindow(GetDlgItem(hDlg, IDD_LOGON_DOMAIN_LABEL), fShow);
  2008. ShowDlgItem(hDlg, IDD_LOGON_DOMAIN, fShow);
  2009. EnableWindow(GetDlgItem(hDlg, IDD_LOGON_DOMAIN), fShow);
  2010. }
  2011. if ( fSticky )
  2012. {
  2013. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
  2014. {
  2015. RegSetValueEx(hKey, SHOW_LOGON_OPTIONS, 0, REG_DWORD,
  2016. (LPBYTE)&fShow, sizeof(fShow));
  2017. RegCloseKey (hKey);
  2018. }
  2019. }
  2020. }
  2021. //
  2022. // Change the options button to reflect the open/close state
  2023. //
  2024. LoadString(hDllInstance, fShow ? IDS_LESSOPTIONS:IDS_MOREOPTIONS,
  2025. szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  2026. SetDlgItemText(hDlg, IDD_LOGON_OPTIONS, szBuffer);
  2027. pGlobals->LogonOptionsShown = fShow;
  2028. // Enable or disable the domain box depending on whether a UPN name has been typed
  2029. EnableDomainForUPN(GetDlgItem(hDlg, IDD_LOGON_NAME), GetDlgItem(hDlg, IDD_LOGON_DOMAIN));
  2030. }
  2031. /***************************************************************************\
  2032. * FUNCTION: AttemptLogonSetControls
  2033. *
  2034. * PURPOSE: Sets up the logon UI to animating and controls to the
  2035. * correct state.
  2036. *
  2037. * HISTORY:
  2038. *
  2039. * 02-05-98 diz Created
  2040. *
  2041. \***************************************************************************/
  2042. VOID AttemptLogonSetControls(
  2043. PGLOBALS pGlobals,
  2044. HWND hDlg
  2045. )
  2046. {
  2047. DWORD RasDisable;
  2048. static BOOL sbRasBoxOriginalyEnabled;
  2049. static BOOL sbShutDownOriginallyEnabled;
  2050. RtlEnterCriticalSection( &pGlobals->csGlobals );
  2051. EnableDlgItem(hDlg, IDD_LOGON_NAME_LABEL, !pGlobals->LogonInProgress);
  2052. EnableDlgItem(hDlg, IDD_LOGON_NAME, !pGlobals->LogonInProgress);
  2053. EnableDlgItem(hDlg, IDD_LOGON_PASSWORD_LABEL, !pGlobals->LogonInProgress);
  2054. EnableDlgItem(hDlg, IDD_LOGON_PASSWORD, !pGlobals->LogonInProgress);
  2055. EnableDlgItem(hDlg, IDD_LOGON_DOMAIN_LABEL, !pGlobals->LogonInProgress);
  2056. EnableDlgItem(hDlg, IDD_LOGON_DOMAIN, !pGlobals->LogonInProgress);
  2057. // If no logon is in progress, we want to enable domain box based on whether
  2058. // a UPN has been typed
  2059. if (!pGlobals->LogonInProgress)
  2060. {
  2061. EnableDomainForUPN(GetDlgItem(hDlg, IDD_LOGON_NAME), GetDlgItem(hDlg, IDD_LOGON_DOMAIN));
  2062. }
  2063. //
  2064. // MakarP: we should not enable all these control when !pGlobals->LogonInProgress, they should really be reverted back to their original state.
  2065. // but for now I am just looking after IDD_LOGON_RASBOX in remote connection cases to fix bug #267270
  2066. //
  2067. if (pGlobals->LogonInProgress)
  2068. {
  2069. sbRasBoxOriginalyEnabled = IsWindowEnabled(GetDlgItem(hDlg, IDD_LOGON_RASBOX));
  2070. RasDisable = GetProfileInt(APPLICATION_NAME, RAS_DISABLE, 0);
  2071. EnableDlgItem(hDlg, IDD_LOGON_RASBOX, !RasDisable && !pGlobals->LogonInProgress);
  2072. sbShutDownOriginallyEnabled = IsWindowEnabled(GetDlgItem(hDlg, IDD_LOGON_SHUTDOWN));
  2073. EnableDlgItem(hDlg, IDD_LOGON_SHUTDOWN, !pGlobals->LogonInProgress);
  2074. }
  2075. else
  2076. {
  2077. EnableDlgItem(hDlg, IDD_LOGON_RASBOX, sbRasBoxOriginalyEnabled);
  2078. EnableDlgItem(hDlg, IDD_LOGON_SHUTDOWN, sbShutDownOriginallyEnabled);
  2079. }
  2080. EnableDlgItem(hDlg, IDD_KBLAYOUT_ICON, !pGlobals->LogonInProgress);
  2081. EnableDlgItem(hDlg, IDD_LOGON_OPTIONS, !pGlobals->LogonInProgress);
  2082. //
  2083. // if ShutdownWithoutLogon, use the proper 3 buttons: OK, Shutdown and Cancel
  2084. // instead of the 2 buttons OK and Cancel
  2085. //
  2086. EnableDlgItem(hDlg, IDOK, !pGlobals->LogonInProgress);
  2087. if ( !GetDisableCad(pGlobals) )
  2088. EnableDlgItem(hDlg, IDCANCEL, !pGlobals->LogonInProgress);
  2089. RtlLeaveCriticalSection( &pGlobals->csGlobals );
  2090. }
  2091. /***************************************************************************\
  2092. * FUNCTION: AttemptLogon
  2093. *
  2094. * PURPOSE: Tries to the log the user on using the current values in the
  2095. * logon dialog controls
  2096. *
  2097. * RETURNS: MSGINA_DLG_SUCCESS - the user was logged on successfully
  2098. * MSGINA_DLG_FAILURE - the logon failed,
  2099. * DLG_INTERRUPTED() - a set defined in winlogon.h
  2100. *
  2101. * NOTES: If the logon is successful, the global structure is filled in
  2102. * with the logon information.
  2103. *
  2104. * HISTORY:
  2105. *
  2106. * 12-09-91 Davidc Created.
  2107. *
  2108. \***************************************************************************/
  2109. INT_PTR
  2110. AttemptLogon(
  2111. HWND hDlg
  2112. )
  2113. {
  2114. PGLOBALS pGlobals = (PGLOBALS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  2115. PWCHAR UserName = pGlobals->UserName;
  2116. PWCHAR Domain = pGlobals->Domain;
  2117. PWCHAR Password = pGlobals->Password;
  2118. PDOMAIN_CACHE_ENTRY Entry ;
  2119. RECT rc;
  2120. HANDLE hThread;
  2121. DWORD tid;
  2122. BOOL timeout;
  2123. PUCHAR Dummy;
  2124. BOOL RasBox;
  2125. UserName[0] = TEXT('\0');
  2126. Domain[0] = TEXT('\0');
  2127. Password[0] = TEXT('\0');
  2128. //
  2129. // Hide the password so it doesn't make it to the pagefile in
  2130. // cleartext. Do this before getting the username and password
  2131. // so that it can't easily be identified (by association with
  2132. // the username and password) if we should crash or be rebooted
  2133. // before getting a chance to encode it.
  2134. //
  2135. GetDlgItemText(hDlg, IDD_LOGON_PASSWORD, Password, MAX_STRING_BYTES);
  2136. RtlInitUnicodeString(&pGlobals->PasswordString, Password);
  2137. pGlobals->Seed = 0; // Causes the encode routine to assign a seed
  2138. HidePassword( &pGlobals->Seed, &pGlobals->PasswordString );
  2139. //
  2140. // Now get the username and domain
  2141. //
  2142. if ( pGlobals->SmartCardLogon == FALSE )
  2143. {
  2144. HWND hwndDomain = GetDlgItem(hDlg, IDD_LOGON_DOMAIN);
  2145. if (hwndDomain != NULL)
  2146. {
  2147. INT iDomainSel = (INT)SendMessage(hwndDomain, CB_GETCURSEL, 0, 0);
  2148. GetDlgItemText(hDlg, IDD_LOGON_NAME, UserName, MAX_STRING_BYTES);
  2149. //
  2150. // is this the magical "this computer" entry???
  2151. //
  2152. Entry = (PDOMAIN_CACHE_ENTRY) SendMessage( hwndDomain, CB_GETITEMDATA, (WPARAM)iDomainSel, 0);
  2153. }
  2154. else
  2155. {
  2156. Entry = (PDOMAIN_CACHE_ENTRY) CB_ERR;
  2157. }
  2158. if ( Entry != (PDOMAIN_CACHE_ENTRY) CB_ERR )
  2159. {
  2160. wcscpy( Domain, Entry->FlatName.Buffer );
  2161. }
  2162. else
  2163. {
  2164. Domain[0] = L'\0';
  2165. }
  2166. }
  2167. else
  2168. {
  2169. UserName[0] = TEXT('\0');
  2170. Domain[0] = TEXT('\0') ;
  2171. }
  2172. // If we are forcing a NoDomainUI, populate the domain with the local machine name now
  2173. if (ForceNoDomainUI())
  2174. {
  2175. DWORD chSize = MAX_STRING_BYTES;
  2176. if (GetComputerName(Domain, &chSize))
  2177. {
  2178. NOTHING;
  2179. }
  2180. else
  2181. {
  2182. *Domain = 0;
  2183. }
  2184. }
  2185. //
  2186. // If there is a at-sign in the name, assume that means that a UPN logon
  2187. // attempt is being made. Set the domain to NULL.
  2188. //
  2189. if ( wcschr( UserName, L'@' ) )
  2190. {
  2191. Domain[0] = TEXT('\0');
  2192. }
  2193. RtlInitUnicodeString(&pGlobals->UserNameString, UserName);
  2194. RtlInitUnicodeString(&pGlobals->DomainString, Domain);
  2195. //
  2196. // Ok, is the RASbox checked?
  2197. //
  2198. RasBox = IsDlgButtonChecked( hDlg, IDD_LOGON_RASBOX );
  2199. pGlobals->RasUsed = FALSE;
  2200. if ( RasBox == BST_CHECKED )
  2201. {
  2202. //
  2203. // Reset the current timeout so that they neatly clean up before
  2204. // winlogon up and blows them away.
  2205. //
  2206. pWlxFuncs->WlxSetTimeout( pGlobals->hGlobalWlx, 5 * 60 );
  2207. if ( !PopupRasPhonebookDlg( hDlg, pGlobals, &timeout) )
  2208. {
  2209. return( MSGINA_DLG_FAILURE );
  2210. }
  2211. pGlobals->RasUsed = TRUE;
  2212. //
  2213. // Reinitialize strings in case they've changed
  2214. //
  2215. RtlInitUnicodeString( &pGlobals->UserNameString, UserName );
  2216. //
  2217. // Ping Netlogon to allow us to go out on the net again...
  2218. //
  2219. I_NetLogonControl2(NULL,
  2220. NETLOGON_CONTROL_TRANSPORT_NOTIFY,
  2221. 1, (LPBYTE) &Dummy, &Dummy );
  2222. Sleep ((DWORD) ReadWinlogonBoolValue(TEXT("RASSleepTime"), 3000));
  2223. RefreshPolicy(TRUE);
  2224. }
  2225. //
  2226. // Process arguments before kicking off the thread
  2227. //
  2228. pGlobals->hwndLogon = hDlg;
  2229. RtlEnterCriticalSection( &pGlobals->csGlobals );
  2230. pGlobals->LogonInProgress = TRUE ;
  2231. RtlLeaveCriticalSection( &pGlobals->csGlobals );
  2232. GetClientRect(hDlg, &rc);
  2233. pGlobals->cxBand = rc.right-rc.left;
  2234. SetTimer(hDlg, 0, 20, NULL); // setup the progress timer
  2235. //
  2236. // Kick off real logon thread
  2237. //
  2238. // Set timeout to infinite while attempting to logon
  2239. pWlxFuncs->WlxSetTimeout( pGlobals->hGlobalWlx, TIMEOUT_NONE );
  2240. hThread = CreateThread( NULL, 0,
  2241. AttemptLogonThread,
  2242. pGlobals,
  2243. 0, &tid );
  2244. if (hThread)
  2245. {
  2246. CloseHandle( hThread );
  2247. }
  2248. else
  2249. {
  2250. //
  2251. // CreateThread failed, likely because of low memory.
  2252. // Inform the user.
  2253. //
  2254. PostFailedLogonMessage(pGlobals->hwndLogon,
  2255. pGlobals,
  2256. GetLastError(),
  2257. 0,
  2258. NULL,
  2259. NULL);
  2260. RtlEnterCriticalSection( &pGlobals->csGlobals );
  2261. pGlobals->LogonInProgress = FALSE ;
  2262. RtlLeaveCriticalSection( &pGlobals->csGlobals );
  2263. return MSGINA_DLG_FAILURE ;
  2264. }
  2265. AttemptLogonSetControls(pGlobals, hDlg);
  2266. return MSGINA_DLG_SUCCESS;
  2267. }
  2268. BOOL ReplacedPossibleDisplayName (WCHAR *pszUsername)
  2269. {
  2270. BOOL fReplaced;
  2271. DWORD dwIndex, dwReturnedEntryCount;
  2272. NET_API_STATUS nasCode;
  2273. NET_DISPLAY_USER *pNDU;
  2274. fReplaced = FALSE;
  2275. dwIndex = 0;
  2276. nasCode = NetQueryDisplayInformation(NULL,
  2277. 1,
  2278. dwIndex,
  2279. 1,
  2280. sizeof(NET_DISPLAY_USER),
  2281. &dwReturnedEntryCount,
  2282. (void**)&pNDU);
  2283. while (!fReplaced &&
  2284. (dwReturnedEntryCount > 0) &&
  2285. (NERR_Success == nasCode) || (ERROR_MORE_DATA == nasCode))
  2286. {
  2287. fReplaced = (lstrcmpiW(pNDU->usri1_full_name, pszUsername) == 0);
  2288. if (fReplaced)
  2289. {
  2290. lstrcpyW(pszUsername, pNDU->usri1_name);
  2291. }
  2292. nasCode = NetApiBufferFree(pNDU);
  2293. if (!fReplaced)
  2294. {
  2295. nasCode = NetQueryDisplayInformation(NULL,
  2296. 1,
  2297. ++dwIndex,
  2298. 1,
  2299. sizeof(NET_DISPLAY_USER),
  2300. &dwReturnedEntryCount,
  2301. (void**)&pNDU);
  2302. }
  2303. }
  2304. return(fReplaced);
  2305. }
  2306. BOOL ReplacedLogonName (PGLOBALS pGlobals)
  2307. {
  2308. BOOL fReplaced;
  2309. fReplaced = ReplacedPossibleDisplayName(pGlobals->UserName);
  2310. if (fReplaced)
  2311. {
  2312. RtlInitUnicodeString(&pGlobals->UserNameString, pGlobals->UserName);
  2313. }
  2314. return(fReplaced);
  2315. }
  2316. DWORD
  2317. AttemptLogonThread(
  2318. PGLOBALS pGlobals
  2319. )
  2320. {
  2321. STRING PackageName;
  2322. PSID LogonSid;
  2323. LUID LogonId = { 0, 0 };
  2324. HANDLE UserToken = NULL;
  2325. HANDLE RestrictedToken;
  2326. BOOL PasswordExpired, ChangedLogonName;
  2327. NTSTATUS FinalStatus;
  2328. NTSTATUS Status = STATUS_SUCCESS;
  2329. NTSTATUS SubStatus = STATUS_SUCCESS;
  2330. INT_PTR Result = MSGINA_DLG_FAILURE;
  2331. ULONG LogonPackage;
  2332. BYTE GroupsBuffer[sizeof(TOKEN_GROUPS)+sizeof(SID_AND_ATTRIBUTES)];
  2333. PTOKEN_GROUPS TokenGroups = (PTOKEN_GROUPS) GroupsBuffer;
  2334. PVOID AuthInfo ;
  2335. ULONG AuthInfoSize ;
  2336. UCHAR UserBuffer[ SID_MAX_SUB_AUTHORITIES * sizeof( DWORD ) + 8 + sizeof( TOKEN_USER ) ];
  2337. PTOKEN_USER pTokenUser ;
  2338. ULONG TokenInfoSize ;
  2339. PUCHAR SmartCardInfo ;
  2340. SECURITY_LOGON_TYPE logonType;
  2341. PWLX_SC_NOTIFICATION_INFO ScInfo = NULL ;
  2342. #ifdef SMARTCARD_DOGFOOD
  2343. DWORD StartTime = 0, EndTime = 0;
  2344. #endif
  2345. //
  2346. // Store the logon time
  2347. // Do this before calling Lsa so we know if logon is successful that
  2348. // the password-must-change time will be greater than this time.
  2349. // If we grabbed this time after calling the lsa, this might not be true.
  2350. //
  2351. if ( IsActiveConsoleSession() )
  2352. {
  2353. // this is the console logon;
  2354. logonType = Interactive;
  2355. }
  2356. else
  2357. {
  2358. // remote sessions user must have the SeRemoteInteractiveLogonRight right which
  2359. // is granted to a user due to their membership in the new Remote-Desktop Users group.
  2360. logonType = RemoteInteractive;
  2361. }
  2362. GetSystemTimeAsFileTime( (LPFILETIME) &pGlobals->LogonTime );
  2363. DebugLog((DEB_TRACE, "In Attempt Logon!\n"));
  2364. if ( pGlobals->RasUsed )
  2365. {
  2366. if ( DCacheGetCacheState( pGlobals->Cache ) < DomainCacheRegistryCache )
  2367. {
  2368. //
  2369. // We are using really stale data. Poke the cache to get it to use the
  2370. // now made RAS connection
  2371. //
  2372. DCacheUpdateMinimal( pGlobals->Cache, NULL, TRUE );
  2373. }
  2374. }
  2375. //
  2376. // Generate a unique sid for this logon
  2377. //
  2378. LogonSid = pGlobals->LogonSid;
  2379. SetupCursor( TRUE );
  2380. FinalStatus = STATUS_SUCCESS;
  2381. if ( wcschr( pGlobals->UserName, L'\\' ) ||
  2382. wcschr( pGlobals->UserName, L'/' ) )
  2383. {
  2384. FinalStatus = STATUS_LOGON_FAILURE ;
  2385. Status = FinalStatus ;
  2386. }
  2387. // clear card and reader name
  2388. pGlobals->Smartcard[0] = TEXT('\0');
  2389. pGlobals->SmartcardReader[0] = TEXT('\0');
  2390. if ( NT_SUCCESS( FinalStatus ) )
  2391. {
  2392. if ( pGlobals->SmartCardLogon )
  2393. {
  2394. pGlobals->AuthenticationPackage = pGlobals->SmartCardLogonPackage ;
  2395. }
  2396. else
  2397. {
  2398. pGlobals->AuthenticationPackage = pGlobals->PasswordLogonPackage ;
  2399. }
  2400. if ( pGlobals->SmartCardLogon )
  2401. {
  2402. pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
  2403. WLX_OPTION_SMART_CARD_INFO,
  2404. (ULONG_PTR *) &ScInfo );
  2405. if ( !ScInfo )
  2406. {
  2407. goto exit;
  2408. }
  2409. SmartCardInfo = ScBuildLogonInfo(
  2410. ScInfo->pszCard,
  2411. ScInfo->pszReader,
  2412. ScInfo->pszContainer,
  2413. ScInfo->pszCryptoProvider );
  2414. if(ScInfo->pszCard && ScInfo->pszReader) {
  2415. wcsncpy(
  2416. pGlobals->Smartcard,
  2417. ScInfo->pszCard,
  2418. sizeof(pGlobals->Smartcard) / sizeof(TCHAR) - 1
  2419. );
  2420. wcsncpy(
  2421. pGlobals->SmartcardReader,
  2422. ScInfo->pszReader,
  2423. sizeof(pGlobals->SmartcardReader) / sizeof(TCHAR) - 1
  2424. );
  2425. }
  2426. #ifndef SMARTCARD_DOGFOOD
  2427. LocalFree( ScInfo );
  2428. #endif
  2429. AuthInfo = FormatSmartCardCredentials(
  2430. &pGlobals->PasswordString,
  2431. SmartCardInfo,
  2432. FALSE,
  2433. NULL,
  2434. &AuthInfoSize );
  2435. LocalFree( SmartCardInfo );
  2436. }
  2437. else
  2438. {
  2439. AuthInfo = FormatPasswordCredentials(
  2440. &pGlobals->UserNameString,
  2441. &pGlobals->DomainString,
  2442. &pGlobals->PasswordString,
  2443. FALSE,
  2444. NULL,
  2445. &AuthInfoSize );
  2446. }
  2447. //
  2448. // Actually try to logon the user
  2449. //
  2450. #ifdef SMARTCARD_DOGFOOD
  2451. StartTime = GetTickCount();
  2452. #endif
  2453. FinalStatus = WinLogonUser(
  2454. pGlobals->LsaHandle,
  2455. pGlobals->AuthenticationPackage,
  2456. logonType,
  2457. AuthInfo,
  2458. AuthInfoSize,
  2459. LogonSid,
  2460. &LogonId,
  2461. &UserToken,
  2462. &pGlobals->UserProcessData.Quotas,
  2463. (PVOID *)&pGlobals->Profile,
  2464. &pGlobals->ProfileLength,
  2465. &SubStatus,
  2466. &pGlobals->OptimizedLogonStatus);
  2467. #ifdef SMARTCARD_DOGFOOD
  2468. EndTime = GetTickCount();
  2469. #endif
  2470. Status = FinalStatus;
  2471. }
  2472. SetupCursor( FALSE );
  2473. RtlEnterCriticalSection( &pGlobals->csGlobals );
  2474. pGlobals->LogonInProgress = FALSE;
  2475. RtlLeaveCriticalSection( &pGlobals->csGlobals );
  2476. DebugLog((DEB_TRACE, "WinLogonUser returned %#x\n", Status));
  2477. PasswordExpired = (((Status == STATUS_ACCOUNT_RESTRICTION) && (SubStatus == STATUS_PASSWORD_EXPIRED)) ||
  2478. (Status == STATUS_PASSWORD_MUST_CHANGE));
  2479. //
  2480. // If the account has expired we let them change their password and
  2481. // automatically retry the logon with the new password.
  2482. //
  2483. if (PasswordExpired)
  2484. {
  2485. _Shell_LogonDialog_HideUIHost();
  2486. if (Status == STATUS_PASSWORD_MUST_CHANGE)
  2487. {
  2488. Result = TimeoutMessageBox(pGlobals->hwndLogon, pGlobals, IDS_PASSWORD_MUST_CHANGE,
  2489. IDS_LOGON_MESSAGE,
  2490. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND,
  2491. TIMEOUT_CURRENT);
  2492. }
  2493. else
  2494. {
  2495. Result = TimeoutMessageBox(pGlobals->hwndLogon, pGlobals, IDS_PASSWORD_EXPIRED,
  2496. IDS_LOGON_MESSAGE,
  2497. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND,
  2498. TIMEOUT_CURRENT);
  2499. }
  2500. if (DLG_INTERRUPTED(Result))
  2501. goto exit;
  2502. //
  2503. // Copy the old password for mpr notification later
  2504. //
  2505. RevealPassword( &pGlobals->PasswordString );
  2506. wcsncpy(pGlobals->OldPassword, pGlobals->Password, MAX_STRING_BYTES);
  2507. pGlobals->OldSeed = 0;
  2508. RtlInitUnicodeString(&pGlobals->OldPasswordString, pGlobals->OldPassword);
  2509. HidePassword( &pGlobals->OldSeed, &pGlobals->OldPasswordString);
  2510. pGlobals->OldPasswordPresent = 1;
  2511. //
  2512. // Let the user change their password
  2513. //
  2514. LogonPackage = pGlobals->AuthenticationPackage ;
  2515. RtlInitString(&PackageName, MSV1_0_PACKAGE_NAME );
  2516. Status = LsaLookupAuthenticationPackage (
  2517. pGlobals->LsaHandle,
  2518. &PackageName,
  2519. &pGlobals->AuthenticationPackage
  2520. );
  2521. if (!NT_SUCCESS(Status)) {
  2522. DebugLog((DEB_ERROR, "Failed to find %s authentication package, status = 0x%lx",
  2523. MSV1_0_PACKAGE_NAME, Status));
  2524. Result = MSGINA_DLG_FAILURE;
  2525. goto exit;
  2526. }
  2527. Result = ChangePasswordLogon(pGlobals->hwndLogon, pGlobals,
  2528. pGlobals->UserName,
  2529. pGlobals->Domain,
  2530. pGlobals->Password);
  2531. pGlobals->AuthenticationPackage = LogonPackage ;
  2532. if (DLG_INTERRUPTED(Result))
  2533. goto exit;
  2534. if (Result == MSGINA_DLG_FAILURE)
  2535. {
  2536. // The user doesn't want to, or failed to change their password.
  2537. goto exit;
  2538. }
  2539. }
  2540. // Special handling for failed logon on personal or professional
  2541. // machines that are NOT joined to a domain. In this case it's
  2542. // probably a user who disabled friendly UI and only knows of
  2543. // their "display name" not their real "logon name". This
  2544. // transparently maps one to the other to allow logons using
  2545. // the "display name".
  2546. ChangedLogonName = ((FinalStatus == STATUS_LOGON_FAILURE) &&
  2547. (IsOS(OS_PERSONAL) || IsOS(OS_PROFESSIONAL)) &&
  2548. !IsMachineDomainMember() &&
  2549. ReplacedLogonName(pGlobals));
  2550. if (PasswordExpired || ChangedLogonName)
  2551. {
  2552. //
  2553. // Retry the logon with the changed password
  2554. //
  2555. //
  2556. // Generate a unique sid for this logon
  2557. //
  2558. LogonSid = pGlobals->LogonSid;
  2559. AuthInfo = FormatPasswordCredentials(
  2560. &pGlobals->UserNameString,
  2561. &pGlobals->DomainString,
  2562. &pGlobals->PasswordString,
  2563. FALSE,
  2564. NULL,
  2565. &AuthInfoSize );
  2566. Status = WinLogonUser(
  2567. pGlobals->LsaHandle,
  2568. pGlobals->AuthenticationPackage,
  2569. logonType,
  2570. AuthInfo,
  2571. AuthInfoSize,
  2572. LogonSid,
  2573. &LogonId,
  2574. &UserToken,
  2575. &pGlobals->UserProcessData.Quotas,
  2576. (PVOID *)&pGlobals->Profile,
  2577. &pGlobals->ProfileLength,
  2578. &SubStatus,
  2579. &pGlobals->OptimizedLogonStatus);
  2580. }
  2581. //
  2582. // Deal with a terminally failed logon attempt
  2583. //
  2584. if (!NT_SUCCESS(Status))
  2585. {
  2586. //
  2587. // Do lockout processing
  2588. //
  2589. LockoutHandleFailedLogon(pGlobals);
  2590. Result = MSGINA_DLG_FAILEDMSGSENT;
  2591. PostFailedLogonMessage(pGlobals->hwndLogon, pGlobals, Status, SubStatus, pGlobals->UserName, pGlobals->Domain);
  2592. goto exit;
  2593. }
  2594. //
  2595. // The user logged on successfully
  2596. //
  2597. //
  2598. // Do lockout processing
  2599. //
  2600. LockoutHandleSuccessfulLogon(pGlobals);
  2601. //
  2602. // If the audit log is full, check they're an admin
  2603. //
  2604. if (pGlobals->AuditLogFull)
  2605. {
  2606. //
  2607. // The audit log is full, so only administrators are allowed to logon.
  2608. //
  2609. if (!UserToken || !TestTokenForAdmin(UserToken))
  2610. {
  2611. //
  2612. // The user is not an administrator, boot 'em.
  2613. //
  2614. LsaFreeReturnBuffer(pGlobals->Profile);
  2615. pGlobals->Profile = NULL;
  2616. NtClose(UserToken);
  2617. Result = MSGINA_DLG_FAILEDMSGSENT;
  2618. // Post a specific substatus so we can display a meaningful error message
  2619. PostFailedLogonMessage(pGlobals->hwndLogon, pGlobals, STATUS_LOGON_FAILURE, IDS_LOGON_LOG_FULL, pGlobals->UserName, pGlobals->Domain);
  2620. goto exit;
  2621. }
  2622. else
  2623. {
  2624. //
  2625. // If we are in a session, we didn't display the log full onfo on the welcome
  2626. // screen, so tell the admin
  2627. //
  2628. if (GetSystemMetrics(SM_REMOTESESSION))
  2629. {
  2630. TimeoutMessageBox(
  2631. pGlobals->hwndLogon,
  2632. pGlobals,
  2633. IDS_LOGON_LOG_FULL_ADMIN,
  2634. IDS_LOGON_MESSAGE,
  2635. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND,
  2636. TIMEOUT_CURRENT);
  2637. }
  2638. }
  2639. }
  2640. //
  2641. // Hide ourselves before letting other credential managers put
  2642. // up dialogs
  2643. //
  2644. #if 0
  2645. ShowWindow(hDlg, SW_HIDE);
  2646. #endif
  2647. //
  2648. // Create a filtered version of the token for running normal applications
  2649. // if so indicated by a registry setting
  2650. //
  2651. if (GetProfileInt( APPLICATION_NAME, RESTRICT_SHELL, 0) != 0) {
  2652. TokenGroups->Groups[0].Attributes = 0;
  2653. TokenGroups->Groups[0].Sid = gAdminSid;
  2654. TokenGroups->GroupCount = 1;
  2655. Status = NtFilterToken(
  2656. UserToken,
  2657. DISABLE_MAX_PRIVILEGE,
  2658. TokenGroups, // disable the administrators sid
  2659. NULL, // no privileges
  2660. NULL,
  2661. &RestrictedToken
  2662. );
  2663. if (!NT_SUCCESS(Status))
  2664. {
  2665. DebugLog((DEB_ERROR, "Failed to filter token: 0x%%x\n", Status));
  2666. RestrictedToken = NULL;
  2667. }
  2668. //
  2669. // Now set the default dacl for the token
  2670. //
  2671. {
  2672. PACL Dacl = NULL;
  2673. ULONG DaclLength = 0;
  2674. TOKEN_DEFAULT_DACL DefaultDacl;
  2675. DaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LogonSid);
  2676. Dacl = Alloc(DaclLength);
  2677. Status = RtlCreateAcl(Dacl,DaclLength, ACL_REVISION);
  2678. ASSERT(NT_SUCCESS(Status));
  2679. Status = RtlAddAccessAllowedAce(
  2680. Dacl,
  2681. ACL_REVISION,
  2682. GENERIC_ALL,
  2683. LogonSid
  2684. );
  2685. ASSERT(NT_SUCCESS(Status));
  2686. DefaultDacl.DefaultDacl = Dacl;
  2687. Status = NtSetInformationToken(
  2688. RestrictedToken,
  2689. TokenDefaultDacl,
  2690. &DefaultDacl,
  2691. sizeof(TOKEN_DEFAULT_DACL)
  2692. );
  2693. ASSERT(NT_SUCCESS(Status));
  2694. Free(Dacl);
  2695. }
  2696. } else {
  2697. RestrictedToken = NULL;
  2698. }
  2699. //
  2700. // Notify credential managers of the successful logon
  2701. //
  2702. pTokenUser = (PTOKEN_USER) UserBuffer ;
  2703. Status = NtQueryInformationToken( UserToken,
  2704. TokenUser,
  2705. pTokenUser,
  2706. sizeof( UserBuffer ),
  2707. &TokenInfoSize );
  2708. if ( NT_SUCCESS( Status ) )
  2709. {
  2710. pGlobals->UserProcessData.UserSid = LocalAlloc( LMEM_FIXED,
  2711. RtlLengthSid( pTokenUser->User.Sid ) );
  2712. if ( pGlobals->UserProcessData.UserSid )
  2713. {
  2714. RtlCopyMemory( pGlobals->UserProcessData.UserSid,
  2715. pTokenUser->User.Sid,
  2716. RtlLengthSid( pTokenUser->User.Sid ) );
  2717. }
  2718. else
  2719. {
  2720. Status = STATUS_NO_MEMORY ;
  2721. }
  2722. }
  2723. if ( !NT_SUCCESS( Status ) )
  2724. {
  2725. LsaFreeReturnBuffer(pGlobals->Profile);
  2726. pGlobals->Profile = NULL;
  2727. NtClose(UserToken);
  2728. Result = MSGINA_DLG_FAILEDMSGSENT;
  2729. PostFailedLogonMessage(pGlobals->hwndLogon, pGlobals, Status, 0, pGlobals->UserName, pGlobals->Domain);
  2730. goto exit;
  2731. }
  2732. pGlobals->UserProcessData.RestrictedToken = RestrictedToken;
  2733. pGlobals->UserProcessData.UserToken = UserToken;
  2734. pGlobals->UserProcessData.NewThreadTokenSD = CreateUserThreadTokenSD(LogonSid, pWinlogonSid);
  2735. pGlobals->MprLogonScripts = NULL;
  2736. pGlobals->ExtraApps = NULL ;
  2737. //
  2738. // If we get here, the system works well enough for the user to have
  2739. // actually logged on. Profile failures aren't fixable by last known
  2740. // good anyway. Therefore, declare the boot good.
  2741. //
  2742. ReportBootGood(pGlobals);
  2743. //
  2744. // Set up the system for the new user
  2745. //
  2746. pGlobals->LogonId = LogonId;
  2747. if ((pGlobals->Profile != NULL) && (pGlobals->Profile->FullName.Length > 0)) {
  2748. if (pGlobals->Profile->FullName.Length > MAX_STRING_LENGTH) {
  2749. wcsncpy(pGlobals->UserFullName, pGlobals->Profile->FullName.Buffer, MAX_STRING_LENGTH);
  2750. *(pGlobals->UserFullName + MAX_STRING_LENGTH) = UNICODE_NULL;
  2751. }
  2752. else {
  2753. lstrcpy(pGlobals->UserFullName, pGlobals->Profile->FullName.Buffer);
  2754. }
  2755. } else {
  2756. //
  2757. // No profile - set full name = NULL
  2758. pGlobals->UserFullName[0] = 0;
  2759. ASSERT( lstrlen(pGlobals->UserFullName) == 0);
  2760. }
  2761. if ( pGlobals->SmartCardLogon )
  2762. {
  2763. PCCERT_CONTEXT Cert ;
  2764. PKERB_SMART_CARD_PROFILE ScProfile ;
  2765. //
  2766. // Need to fix up the user name with the name (UPN) from the
  2767. // certificate, so that unlock, etc. work correctly.
  2768. //
  2769. ScProfile = (PKERB_SMART_CARD_PROFILE) pGlobals->Profile ;
  2770. pGlobals->UserName[0] = 0 ;
  2771. try
  2772. {
  2773. Cert = CertCreateCertificateContext( X509_ASN_ENCODING,
  2774. ScProfile->CertificateData,
  2775. ScProfile->CertificateSize );
  2776. if ( Cert )
  2777. {
  2778. // Even though the name is MAX_STRING_BYTES, the way it is used
  2779. // throughout the code, it is used as a character counter
  2780. // (Grrr, crappy gina code)
  2781. //
  2782. DWORD dwLen = MAX_STRING_BYTES;
  2783. if(STATUS_SUCCESS == UpnFromCert(Cert, &dwLen, pGlobals->UserName))
  2784. {
  2785. RtlInitUnicodeString( &pGlobals->UserNameString,
  2786. pGlobals->UserName );
  2787. }
  2788. CertFreeCertificateContext( Cert );
  2789. }
  2790. }
  2791. except( EXCEPTION_EXECUTE_HANDLER )
  2792. {
  2793. pGlobals->UserName[0] = L'\0';
  2794. }
  2795. //
  2796. // If this is still 0 on exit, the code that sets up the flat name
  2797. // will copy the flat name into UserName, so the failure case is
  2798. // easy.
  2799. //
  2800. }
  2801. pGlobals->SmartCardOption = GetProfileInt( APPLICATION_NAME, SC_REMOVE_OPTION, 0 );
  2802. //
  2803. // WE SHOULD NOT WRITE INTO THE REGISTRY.
  2804. // CLupu
  2805. //
  2806. //
  2807. // Update our default username and domain ready for the next logon
  2808. //
  2809. //
  2810. // Update the default username & domain only if on the console. Otherwise
  2811. // we'll break AutoAdminLogon by changing the user name.
  2812. //
  2813. if ( g_Console )
  2814. {
  2815. if ( (!pGlobals->AutoAdminLogon) &&
  2816. (SafeBootMode != SAFEBOOT_MINIMAL ) )
  2817. {
  2818. WriteProfileString(APPLICATION_NAME, DEFAULT_USER_NAME_KEY, pGlobals->UserName);
  2819. WriteProfileString(APPLICATION_NAME, DEFAULT_DOMAIN_NAME_KEY, pGlobals->Domain);
  2820. }
  2821. WriteProfileString(APPLICATION_NAME, TEMP_DEFAULT_USER_NAME_KEY, pGlobals->UserName);
  2822. WriteProfileString(APPLICATION_NAME, TEMP_DEFAULT_DOMAIN_NAME_KEY, pGlobals->Domain);
  2823. }
  2824. if ( pGlobals->Domain[0] )
  2825. {
  2826. DCacheSetDefaultEntry( pGlobals->Cache,
  2827. pGlobals->Domain,
  2828. NULL );
  2829. }
  2830. Result = MSGINA_DLG_SUCCESS;
  2831. exit:
  2832. #ifdef SMARTCARD_DOGFOOD
  2833. if (pGlobals->SmartCardLogon) {
  2834. switch (SubStatus)
  2835. {
  2836. case STATUS_SMARTCARD_WRONG_PIN:
  2837. case STATUS_SMARTCARD_CARD_BLOCKED:
  2838. case STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED:
  2839. case STATUS_SMARTCARD_NO_CARD:
  2840. case STATUS_SMARTCARD_NO_KEY_CONTAINER:
  2841. case STATUS_SMARTCARD_NO_CERTIFICATE:
  2842. case STATUS_SMARTCARD_NO_KEYSET:
  2843. case STATUS_SMARTCARD_IO_ERROR:
  2844. case STATUS_SMARTCARD_SUBSYSTEM_FAILURE:
  2845. case STATUS_SMARTCARD_CERT_EXPIRED:
  2846. case STATUS_SMARTCARD_CERT_REVOKED:
  2847. case STATUS_ISSUING_CA_UNTRUSTED:
  2848. case STATUS_REVOCATION_OFFLINE_C:
  2849. case STATUS_PKINIT_CLIENT_FAILURE:
  2850. FinalStatus = SubStatus;
  2851. break;
  2852. default:
  2853. break; // do NOTHING
  2854. }
  2855. // write logon data to database
  2856. AuthMonitor(
  2857. AuthOperLogon,
  2858. g_Console,
  2859. &pGlobals->UserNameString,
  2860. &pGlobals->DomainString,
  2861. (ScInfo ? ScInfo->pszCard : NULL),
  2862. (ScInfo ? ScInfo->pszReader : NULL),
  2863. (PKERB_SMART_CARD_PROFILE) pGlobals->Profile,
  2864. EndTime - StartTime,
  2865. FinalStatus
  2866. );
  2867. }
  2868. if (ScInfo)
  2869. {
  2870. LocalFree( ScInfo );
  2871. }
  2872. #endif
  2873. // Only send a logon complete message if we haven't sent a failed
  2874. // message. The failed message will send a logon complete message
  2875. // when its done.
  2876. if (Result != MSGINA_DLG_FAILEDMSGSENT)
  2877. {
  2878. PostMessage(pGlobals->hwndLogon, WM_LOGONCOMPLETE, 0, Result);
  2879. }
  2880. return 0L;
  2881. }
  2882. /****************************************************************************\
  2883. *
  2884. * FUNCTION: PostFailedLogonMessage
  2885. *
  2886. * PURPOSE: Posts a message to the UI thread telling it to display a dialog that
  2887. * tells the user why their logon attempt failed.
  2888. *
  2889. * The window on the UI thread must correctly handle WM_HANDLEFAILEDLOGON
  2890. * by calling HandleFailedLogon and the Free'ing the structure
  2891. *
  2892. * RETURNS: void
  2893. *
  2894. * HISTORY:
  2895. *
  2896. * 12-09-91 Davidc Created.
  2897. *
  2898. \****************************************************************************/
  2899. void PostFailedLogonMessage(HWND hDlg,
  2900. PGLOBALS pGlobals,
  2901. NTSTATUS Status,
  2902. NTSTATUS SubStatus,
  2903. PWCHAR UserName,
  2904. PWCHAR Domain
  2905. )
  2906. {
  2907. g_failinfo.pGlobals = pGlobals;
  2908. g_failinfo.Status = Status;
  2909. g_failinfo.SubStatus = SubStatus;
  2910. if ( UserName )
  2911. {
  2912. lstrcpyn(g_failinfo.UserName, UserName, ARRAYSIZE(g_failinfo.UserName));
  2913. }
  2914. else
  2915. {
  2916. g_failinfo.UserName[0] = L'\0';
  2917. }
  2918. if ( Domain )
  2919. {
  2920. lstrcpyn(g_failinfo.Domain, Domain, ARRAYSIZE(g_failinfo.Domain));
  2921. }
  2922. else
  2923. {
  2924. g_failinfo.Domain[0] = L'\0' ;
  2925. }
  2926. PostMessage(hDlg, WM_HANDLEFAILEDLOGON, 0 , 0);
  2927. }
  2928. INT_PTR
  2929. CALLBACK
  2930. FailDlgProc(
  2931. HWND hDlg,
  2932. UINT message,
  2933. WPARAM wParam,
  2934. LPARAM lParam
  2935. )
  2936. {
  2937. RUNDLLPROC fptr;
  2938. HMODULE hDll;
  2939. switch (message)
  2940. {
  2941. case WM_INITDIALOG:
  2942. {
  2943. CentreWindow(hDlg);
  2944. return( TRUE );
  2945. }
  2946. case WM_COMMAND:
  2947. {
  2948. if (LOWORD(wParam) == IDOK)
  2949. {
  2950. EndDialog(hDlg, IDOK);
  2951. }
  2952. if (LOWORD(wParam) == IDC_RECOVER)
  2953. {
  2954. // Will eventually supply username to the recover wizard
  2955. // We use a single export from KEYMGR.DLL for this operation. When this operation completes,
  2956. // we don't use the DLL again without unlikely user intervention. We could DELAYLOAD keymgr.dll,
  2957. // but explicitly loading and unloading this DLL permits us to minimize the memory footprint of msgina.
  2958. hDll = LoadLibraryW(L"keymgr.dll");
  2959. if (hDll)
  2960. {
  2961. fptr = (RUNDLLPROC) GetProcAddress(hDll,(LPCSTR)"PRShowRestoreFromMsginaW");
  2962. // next stmt will be removed eventually when we pass the username
  2963. if (fptr)
  2964. {
  2965. fptr(hDlg,NULL,g_failinfo.UserName,0);
  2966. }
  2967. FreeLibrary(hDll);
  2968. EndDialog(hDlg,IDOK);
  2969. }
  2970. }
  2971. }
  2972. break;
  2973. }
  2974. return FALSE;
  2975. }
  2976. /****************************************************************************\
  2977. *
  2978. * FUNCTION: HandleFailedLogon
  2979. *
  2980. * PURPOSE: Tells the user why their logon attempt failed.
  2981. *
  2982. * RETURNS: MSGINA_DLG_FAILURE - we told them what the problem was successfully.
  2983. * DLG_INTERRUPTED() - a set of return values - see winlogon.h
  2984. *
  2985. * HISTORY:
  2986. *
  2987. * 12-09-91 Davidc Created.
  2988. *
  2989. \****************************************************************************/
  2990. INT_PTR
  2991. HandleFailedLogon(
  2992. HWND hDlg
  2993. )
  2994. {
  2995. INT_PTR Result = 0xffffffff;
  2996. DWORD Win32Error ;
  2997. TCHAR *Buffer1 = NULL;
  2998. TCHAR *Buffer2 = NULL;
  2999. TCHAR *Buffer3 = NULL;
  3000. PGLOBALS pGlobals = g_failinfo.pGlobals;
  3001. NTSTATUS Status = g_failinfo.Status;
  3002. NTSTATUS SubStatus = g_failinfo.SubStatus;
  3003. PWCHAR Domain = g_failinfo.Domain;
  3004. DWORD BUStatus = 0xffffffff;
  3005. UINT uiMsgId = 0xabab; // abab is out of range value for default handler at the bottom of this
  3006. // routine. 0 indicates that the user has a psw reset disk
  3007. // -1 means that Buffer1 & 2 contain the message
  3008. // otherwise there is a corresponding resource message
  3009. //
  3010. // for remote sessions, we must set finite timeout value for messagebox.
  3011. // so that the session does not remain there forever
  3012. //
  3013. DWORD TimeOut = IsActiveConsoleSession() ? TIMEOUT_CURRENT : 20;
  3014. switch (Status)
  3015. {
  3016. case STATUS_LOGON_FAILURE:
  3017. case STATUS_NAME_TOO_LONG: // Returned if username is too long
  3018. if (SubStatus == IDS_LOGON_LOG_FULL)
  3019. {
  3020. uiMsgId = IDS_LOGON_LOG_FULL;
  3021. }
  3022. else if (pGlobals->SmartCardLogon)
  3023. {
  3024. switch(SubStatus)
  3025. {
  3026. case STATUS_SMARTCARD_WRONG_PIN:
  3027. uiMsgId = IDS_STATUS_SMARTCARD_WRONG_PIN;
  3028. break;
  3029. case STATUS_SMARTCARD_CARD_BLOCKED:
  3030. uiMsgId = IDS_STATUS_SMARTCARD_CARD_BLOCKED;
  3031. break;
  3032. case STATUS_SMARTCARD_NO_CARD:
  3033. uiMsgId = IDS_STATUS_SMARTCARD_NO_CARD;
  3034. break;
  3035. case STATUS_SMARTCARD_NO_KEY_CONTAINER:
  3036. uiMsgId = IDS_STATUS_SMARTCARD_NO_KEY_CONTAINER;
  3037. break;
  3038. case STATUS_SMARTCARD_NO_CERTIFICATE:
  3039. uiMsgId = IDS_STATUS_SMARTCARD_NO_CERTIFICATE;
  3040. break;
  3041. case STATUS_SMARTCARD_NO_KEYSET:
  3042. uiMsgId = IDS_STATUS_SMARTCARD_NO_KEYSET;
  3043. break;
  3044. case STATUS_SMARTCARD_IO_ERROR:
  3045. uiMsgId = IDS_STATUS_SMARTCARD_IO_ERROR;
  3046. break;
  3047. case STATUS_SMARTCARD_SUBSYSTEM_FAILURE:
  3048. uiMsgId = IDS_STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  3049. break;
  3050. case STATUS_SMARTCARD_CERT_REVOKED:
  3051. uiMsgId = IDS_STATUS_SMARTCARD_CERT_REVOKED;
  3052. break;
  3053. case STATUS_ISSUING_CA_UNTRUSTED:
  3054. uiMsgId = IDS_STATUS_ISSUING_CA_UNTRUSTED;
  3055. break;
  3056. case STATUS_REVOCATION_OFFLINE_C:
  3057. uiMsgId = IDS_STATUS_REVOCATION_OFFLINE_C;
  3058. break;
  3059. case STATUS_PKINIT_CLIENT_FAILURE:
  3060. uiMsgId = IDS_STATUS_PKINIT_CLIENT_FAILURE;
  3061. break;
  3062. case STATUS_SMARTCARD_CERT_EXPIRED:
  3063. uiMsgId = IDS_STATUS_SMARTCARD_CERT_EXPIRED;
  3064. break;
  3065. default:
  3066. uiMsgId = IDS_INCORRECT_NAME_OR_PWD_SC;
  3067. }
  3068. }
  3069. else
  3070. {
  3071. // Non-smartcard logon case:
  3072. // Find out if the user who attempted logon has a password backup disk
  3073. // that could be used to reset the password. If so, present a dialog that
  3074. // offers that possibility. Else simple message box. (see passrec.h)
  3075. if ((0 == PRQueryStatus(NULL,g_failinfo.UserName,&BUStatus)) && (0 == GetSystemMetrics(SM_REMOTESESSION)))
  3076. {
  3077. if (BUStatus == 0)
  3078. {
  3079. uiMsgId = 0;
  3080. break;
  3081. }
  3082. }
  3083. // Else UI message is generic one
  3084. uiMsgId = IDS_INCORRECT_NAME_OR_PWD;
  3085. }
  3086. break;
  3087. case STATUS_NOT_SUPPORTED:
  3088. case STATUS_PKINIT_NAME_MISMATCH:
  3089. case STATUS_PKINIT_FAILURE:
  3090. Buffer1 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3091. Buffer2 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3092. if ((Buffer1 == NULL) || (Buffer2 == NULL))
  3093. {
  3094. uiMsgId = IDS_STATUS_SERVER_SIDE_ERROR_NOINSERT;
  3095. }
  3096. else
  3097. {
  3098. LoadString(hDllInstance,
  3099. IDS_STATUS_SERVER_SIDE_ERROR,
  3100. Buffer1,
  3101. MAX_STRING_BYTES);
  3102. _snwprintf(Buffer2, MAX_STRING_BYTES, Buffer1, Status );
  3103. LoadString(hDllInstance,
  3104. IDS_LOGON_MESSAGE,
  3105. Buffer1,
  3106. MAX_STRING_BYTES);
  3107. uiMsgId = (DWORD)-1;
  3108. }
  3109. break;
  3110. case STATUS_ACCOUNT_RESTRICTION:
  3111. switch (SubStatus)
  3112. {
  3113. case STATUS_INVALID_LOGON_HOURS:
  3114. uiMsgId = IDS_INVALID_LOGON_HOURS;
  3115. break;
  3116. case STATUS_INVALID_WORKSTATION:
  3117. uiMsgId = IDS_INVALID_WORKSTATION;
  3118. break;
  3119. case STATUS_ACCOUNT_DISABLED:
  3120. uiMsgId = IDS_ACCOUNT_DISABLED;
  3121. break;
  3122. case STATUS_ACCOUNT_EXPIRED:
  3123. uiMsgId = IDS_ACCOUNT_EXPIRED2;
  3124. break;
  3125. case STATUS_SMARTCARD_LOGON_REQUIRED:
  3126. uiMsgId = IDS_SMARTCARD_REQUIRED;
  3127. break;
  3128. default:
  3129. uiMsgId = IDS_ACCOUNT_RESTRICTION;
  3130. break;
  3131. }
  3132. break;
  3133. case STATUS_NO_LOGON_SERVERS:
  3134. Buffer1 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3135. Buffer2 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3136. if ((Buffer1 == NULL) || (Buffer2 == NULL))
  3137. {
  3138. uiMsgId = IDS_LOGON_NO_DOMAIN_NOINSERT;
  3139. }
  3140. else
  3141. {
  3142. LoadString(hDllInstance, IDS_LOGON_NO_DOMAIN, Buffer1, MAX_STRING_BYTES);
  3143. _snwprintf(Buffer2, MAX_STRING_BYTES, Buffer1, Domain);
  3144. LoadString(hDllInstance, IDS_LOGON_MESSAGE, Buffer1, MAX_STRING_BYTES);
  3145. uiMsgId = (DWORD)-1;
  3146. }
  3147. break;
  3148. case STATUS_LOGON_TYPE_NOT_GRANTED:
  3149. uiMsgId = IDS_LOGON_TYPE_NOT_GRANTED;
  3150. break;
  3151. case STATUS_NO_TRUST_LSA_SECRET:
  3152. uiMsgId = IDS_NO_TRUST_LSA_SECRET;
  3153. break;
  3154. case STATUS_TRUSTED_DOMAIN_FAILURE:
  3155. uiMsgId = IDS_TRUSTED_DOMAIN_FAILURE;
  3156. break;
  3157. case STATUS_TRUSTED_RELATIONSHIP_FAILURE:
  3158. uiMsgId = IDS_TRUSTED_RELATIONSHIP_FAILURE;
  3159. break;
  3160. case STATUS_ACCOUNT_EXPIRED:
  3161. uiMsgId = IDS_ACCOUNT_EXPIRED;
  3162. break;
  3163. case STATUS_NETLOGON_NOT_STARTED:
  3164. uiMsgId = IDS_NETLOGON_NOT_STARTED;
  3165. break;
  3166. case STATUS_ACCOUNT_LOCKED_OUT:
  3167. uiMsgId = IDS_ACCOUNT_LOCKED;
  3168. break;
  3169. case ERROR_CTX_LOGON_DISABLED:
  3170. uiMsgId = IDS_MULTIUSER_LOGON_DISABLED;
  3171. break;
  3172. case ERROR_CTX_WINSTATION_ACCESS_DENIED:
  3173. uiMsgId = IDS_MULTIUSER_WINSTATION_ACCESS_DENIED;
  3174. break;
  3175. case SCARD_E_NO_SMARTCARD:
  3176. case SCARD_E_UNKNOWN_CARD:
  3177. //
  3178. // Card not recognized (although we should never get this far)
  3179. //
  3180. uiMsgId = IDS_CARD_NOT_RECOGNIZED;
  3181. break;
  3182. case NTE_PROV_DLL_NOT_FOUND:
  3183. //
  3184. // Card's CSP not found (although we should never get this far)
  3185. //
  3186. uiMsgId = IDS_CARD_CSP_NOT_RECOGNIZED;
  3187. break;
  3188. case STATUS_TIME_DIFFERENCE_AT_DC:
  3189. uiMsgId = IDS_TIME_DIFFERENCE_AT_DC;
  3190. break;
  3191. default:
  3192. WLPrint(("Logon failure status = 0x%lx, sub-status = 0x%lx", Status, SubStatus));
  3193. Buffer1 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3194. Buffer2 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3195. Buffer3 = LocalAlloc(LPTR, MAX_STRING_BYTES * sizeof(TCHAR));
  3196. if ((Buffer1 == NULL) || (Buffer2 == NULL) || (Buffer3 == NULL))
  3197. {
  3198. uiMsgId = IDS_UNKNOWN_LOGON_FAILURE_NOINSERT;
  3199. }
  3200. else
  3201. {
  3202. LoadString(hDllInstance,
  3203. IDS_UNKNOWN_LOGON_FAILURE,
  3204. Buffer1,
  3205. MAX_STRING_BYTES);
  3206. if ( NT_ERROR( Status ) )
  3207. {
  3208. Win32Error = RtlNtStatusToDosError( Status );
  3209. }
  3210. else
  3211. {
  3212. //
  3213. // Probably an HRESULT:
  3214. //
  3215. Win32Error = Status ;
  3216. }
  3217. GetErrorDescription( Win32Error, Buffer3, MAX_STRING_BYTES);
  3218. _snwprintf(Buffer2, MAX_STRING_BYTES, Buffer1, Buffer3 );
  3219. LoadString(hDllInstance,
  3220. IDS_LOGON_MESSAGE,
  3221. Buffer1,
  3222. MAX_STRING_BYTES);
  3223. uiMsgId = (DWORD)-1;
  3224. }
  3225. break;
  3226. }
  3227. _Shell_LogonDialog_HideUIHost();
  3228. switch (uiMsgId)
  3229. {
  3230. case 0:
  3231. // User has a password reset disk - present the option to use it along with the usual
  3232. // help message
  3233. pWlxFuncs->WlxSetTimeout(pGlobals->hGlobalWlx,LOGON_TIMEOUT);
  3234. Result = pWlxFuncs->WlxDialogBoxParam(pGlobals->hGlobalWlx,
  3235. hDllInstance,
  3236. (LPTSTR) IDD_FAILLOGONHELP_DIALOG,
  3237. hDlg,
  3238. FailDlgProc,
  3239. 0);
  3240. break;
  3241. case (DWORD)-1:
  3242. Result = TimeoutMessageBoxlpstr(hDlg, pGlobals,
  3243. Buffer2,
  3244. Buffer1,
  3245. MB_OK | MB_ICONEXCLAMATION,
  3246. TimeOut);
  3247. break;
  3248. default:
  3249. Result = TimeoutMessageBox(hDlg, pGlobals,
  3250. uiMsgId,
  3251. IDS_LOGON_MESSAGE,
  3252. MB_OK | MB_ICONEXCLAMATION,
  3253. TimeOut);
  3254. }
  3255. if (Buffer1 != NULL)
  3256. LocalFree(Buffer1);
  3257. if (Buffer2 != NULL)
  3258. LocalFree(Buffer2);
  3259. if (Buffer3 != NULL)
  3260. LocalFree(Buffer3);
  3261. if (!DLG_INTERRUPTED(Result))
  3262. {
  3263. Result = MSGINA_DLG_FAILURE;
  3264. }
  3265. return(Result);
  3266. }
  3267. VOID
  3268. ReportBootGoodThread (LPVOID lpDummy)
  3269. {
  3270. HANDLE hInstDll;
  3271. // PGLOBALS pGlobals = (PGLOBALS)lpDummy;
  3272. // SetThreadDesktop(pGlobals->hdeskParent);
  3273. hInstDll = LoadLibrary (TEXT("msgina.dll"));
  3274. NotifyBootConfigStatus(TRUE);
  3275. if (hInstDll) {
  3276. FreeLibraryAndExitThread(hInstDll, TRUE);
  3277. } else {
  3278. ExitThread (TRUE);
  3279. }
  3280. }
  3281. /****************************************************************************\
  3282. *
  3283. * FUNCTION: ReportBootGood
  3284. *
  3285. * PURPOSE: Discover if reporting boot success is responsibility of
  3286. * winlogon or not.
  3287. * If it is, report boot success.
  3288. * Otherwise, do nothing.
  3289. *
  3290. * RETURNS: Nothing
  3291. *
  3292. * HISTORY:
  3293. *
  3294. * 02-Feb-1993 bryanwi - created
  3295. *
  3296. \****************************************************************************/
  3297. VOID
  3298. ReportBootGood(PGLOBALS pGlobals)
  3299. {
  3300. static DWORD fDoIt = (DWORD) -1; // -1 == uninited
  3301. // 0 == don't do it, or done
  3302. // 1 == do it
  3303. PWCH pchData;
  3304. DWORD cb, cbCopied;
  3305. HANDLE hThread;
  3306. DWORD dwThreadID;
  3307. if (fDoIt == -1) {
  3308. if ((pchData = Alloc(cb = sizeof(TCHAR)*128)) == NULL) {
  3309. return;
  3310. }
  3311. pchData[0] = TEXT('0');
  3312. cbCopied = GetProfileString(APPLICATION_NAME, REPORT_BOOT_OK_KEY, TEXT("0"),
  3313. (LPTSTR)pchData, 128);
  3314. fDoIt = 0;
  3315. if (pchData[0] != TEXT('0')) {
  3316. //
  3317. // "ReportBootGood" is present, and has some value other than
  3318. // '0', so report success.
  3319. //
  3320. fDoIt = 1;
  3321. }
  3322. Free((TCHAR *)pchData);
  3323. }
  3324. if (fDoIt == 1) {
  3325. hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)ReportBootGoodThread,
  3326. pGlobals, CREATE_SUSPENDED, &dwThreadID);
  3327. if (hThread) {
  3328. SetThreadPriority (hThread, THREAD_PRIORITY_LOWEST);
  3329. ResumeThread (hThread);
  3330. CloseHandle (hThread);
  3331. } else {
  3332. NotifyBootConfigStatus(TRUE);
  3333. }
  3334. fDoIt = 0;
  3335. }
  3336. return;
  3337. }
  3338. //+---------------------------------------------------------------------------
  3339. //
  3340. // Function: UpnFromCert
  3341. //
  3342. // Notes:
  3343. //
  3344. //----------------------------------------------------------------------------
  3345. NTSTATUS
  3346. UpnFromCert(
  3347. IN PCCERT_CONTEXT pCert,
  3348. IN OUT DWORD *pcUpn,
  3349. IN OUT LPWSTR pUPN
  3350. )
  3351. {
  3352. NTSTATUS Status = STATUS_SUCCESS;
  3353. ULONG ExtensionIndex = 0;
  3354. PCERT_ALT_NAME_INFO AltName=NULL;
  3355. PCERT_NAME_VALUE PrincipalNameBlob = NULL;
  3356. //
  3357. // Get the client name from the cert
  3358. //
  3359. // See if cert has UPN in AltSubjectName->otherName
  3360. for(ExtensionIndex = 0;
  3361. ExtensionIndex < pCert->pCertInfo->cExtension;
  3362. ExtensionIndex++)
  3363. {
  3364. if(strcmp(pCert->pCertInfo->rgExtension[ExtensionIndex].pszObjId,
  3365. szOID_SUBJECT_ALT_NAME2) == 0)
  3366. {
  3367. DWORD AltNameStructSize = 0;
  3368. ULONG CertAltNameIndex = 0;
  3369. if(CryptDecodeObjectEx(pCert->dwCertEncodingType,
  3370. X509_ALTERNATE_NAME,
  3371. pCert->pCertInfo->rgExtension[ExtensionIndex].Value.pbData,
  3372. pCert->pCertInfo->rgExtension[ExtensionIndex].Value.cbData,
  3373. CRYPT_DECODE_ALLOC_FLAG,
  3374. NULL,
  3375. (PVOID)&AltName,
  3376. &AltNameStructSize))
  3377. {
  3378. for(CertAltNameIndex = 0; CertAltNameIndex < AltName->cAltEntry; CertAltNameIndex++)
  3379. {
  3380. PCERT_ALT_NAME_ENTRY AltNameEntry = &AltName->rgAltEntry[CertAltNameIndex];
  3381. if((CERT_ALT_NAME_OTHER_NAME == AltNameEntry->dwAltNameChoice) &&
  3382. (NULL != AltNameEntry->pOtherName) &&
  3383. (0 == strcmp(szOID_NT_PRINCIPAL_NAME, AltNameEntry->pOtherName->pszObjId)))
  3384. {
  3385. DWORD PrincipalNameBlobSize = 0;
  3386. // We found a UPN!
  3387. if(CryptDecodeObjectEx(pCert->dwCertEncodingType,
  3388. X509_UNICODE_ANY_STRING,
  3389. AltNameEntry->pOtherName->Value.pbData,
  3390. AltNameEntry->pOtherName->Value.cbData,
  3391. CRYPT_DECODE_ALLOC_FLAG,
  3392. NULL,
  3393. (PVOID)&PrincipalNameBlob,
  3394. &PrincipalNameBlobSize))
  3395. {
  3396. if(PrincipalNameBlob->Value.cbData + sizeof(WCHAR) > *pcUpn)
  3397. {
  3398. Status = STATUS_BUFFER_OVERFLOW;
  3399. }
  3400. else
  3401. {
  3402. *pcUpn = PrincipalNameBlob->Value.cbData + sizeof(WCHAR);
  3403. CopyMemory(pUPN, PrincipalNameBlob->Value.pbData, PrincipalNameBlob->Value.cbData);
  3404. *(WCHAR *)((PBYTE)pUPN+PrincipalNameBlob->Value.cbData) = 0;
  3405. }
  3406. LocalFree(PrincipalNameBlob);
  3407. PrincipalNameBlob = NULL;
  3408. LocalFree(AltName);
  3409. AltName = NULL;
  3410. goto Finished;
  3411. }
  3412. }
  3413. }
  3414. LocalFree(AltName);
  3415. AltName = NULL;
  3416. }
  3417. }
  3418. }
  3419. //
  3420. // If the name was not found in the UPN, then
  3421. // we grab it the old way.
  3422. if ( !CertGetNameString( pCert,
  3423. CERT_NAME_ATTR_TYPE,
  3424. 0,
  3425. szOID_COMMON_NAME,
  3426. pUPN,
  3427. *pcUpn ) )
  3428. {
  3429. Status = GetLastError();
  3430. }
  3431. Finished:
  3432. return Status ;
  3433. }
  3434. //+---------------------------------------------------------------------------
  3435. //
  3436. // Function:TSAuthenticatedLogon
  3437. //
  3438. // Notes: This routine gets called in response to WLX_SAS_TYPE_AUTHENTICATED
  3439. // in the context of the console session (sessionid 0) winlogon.
  3440. // This type of logon is for Single Session Terminal Server. When a user
  3441. // logs on from a remote TS session, we pass the credentials from the remote session
  3442. // to the console session and do an auto-logon. This routine queries the credentials
  3443. // logs on the user on the console sesion
  3444. //
  3445. //
  3446. //----------------------------------------------------------------------------
  3447. INT_PTR TSAuthenticatedLogon(PGLOBALS pGlobals)
  3448. {
  3449. PSID LogonSid;
  3450. LUID LogonId;
  3451. HANDLE UserToken;
  3452. HANDLE RestrictedToken;
  3453. INT_PTR Result = MSGINA_DLG_SUCCESS;
  3454. UCHAR UserBuffer[ SID_MAX_SUB_AUTHORITIES * sizeof( DWORD ) + 8 + sizeof( TOKEN_USER ) ];
  3455. PTOKEN_USER pTokenUser ;
  3456. ULONG TokenInfoSize ;
  3457. NTSTATUS Status;
  3458. BYTE GroupsBuffer[sizeof(TOKEN_GROUPS)+sizeof(SID_AND_ATTRIBUTES)];
  3459. PTOKEN_GROUPS TokenGroups = (PTOKEN_GROUPS) GroupsBuffer;
  3460. if (!QuerySwitchConsoleCredentials(pGlobals,&UserToken,&LogonId)) {
  3461. Result = MSGINA_DLG_FAILEDMSGSENT;
  3462. goto exit;
  3463. }
  3464. if (pGlobals->SmartCardLogon) {
  3465. wcscpy(pGlobals->Password,L"");
  3466. wcscpy(pGlobals->OldPassword,L"");
  3467. }
  3468. else
  3469. {
  3470. wcscpy(pGlobals->Password,L"");
  3471. RtlInitUnicodeString(&pGlobals->PasswordString,pGlobals->Password);
  3472. wcscpy(pGlobals->OldPassword,L"");
  3473. RtlInitUnicodeString(&pGlobals->OldPasswordString,pGlobals->OldPassword);
  3474. }
  3475. RtlInitUnicodeString(&pGlobals->UserNameString, pGlobals->UserName);
  3476. RtlInitUnicodeString(&pGlobals->DomainString, pGlobals->Domain);
  3477. pGlobals->RasUsed = FALSE;
  3478. pGlobals->hwndLogon = NULL;
  3479. //
  3480. // Generate a unique sid for this logon
  3481. //
  3482. if (!GetAndAllocateLogonSid(UserToken,&(pGlobals->LogonSid))) {
  3483. Result = MSGINA_DLG_FAILEDMSGSENT;
  3484. if (pGlobals->Profile) {
  3485. VirtualFree(pGlobals->Profile, 0, MEM_RELEASE);
  3486. pGlobals->Profile = NULL;
  3487. pGlobals->ProfileLength = 0;
  3488. }
  3489. goto exit;
  3490. }
  3491. LogonSid = pGlobals->LogonSid;
  3492. //
  3493. // The user logged on successfully
  3494. //
  3495. //
  3496. // Create a filtered version of the token for running normal applications
  3497. // if so indicated by a registry setting
  3498. //
  3499. if (GetProfileInt( APPLICATION_NAME, RESTRICT_SHELL, 0) != 0) {
  3500. TokenGroups->Groups[0].Attributes = 0;
  3501. TokenGroups->Groups[0].Sid = gAdminSid;
  3502. TokenGroups->GroupCount = 1;
  3503. Status = NtFilterToken(
  3504. UserToken,
  3505. DISABLE_MAX_PRIVILEGE,
  3506. TokenGroups, // disable the administrators sid
  3507. NULL, // no privileges
  3508. NULL,
  3509. &RestrictedToken
  3510. );
  3511. if (!NT_SUCCESS(Status))
  3512. {
  3513. DebugLog((DEB_ERROR, "Failed to filter token: 0x%%x\n", Status));
  3514. RestrictedToken = NULL;
  3515. }
  3516. //
  3517. // Now set the default dacl for the token
  3518. //
  3519. {
  3520. PACL Dacl = NULL;
  3521. ULONG DaclLength = 0;
  3522. TOKEN_DEFAULT_DACL DefaultDacl;
  3523. DaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LogonSid);
  3524. Dacl = Alloc(DaclLength);
  3525. Status = RtlCreateAcl(Dacl,DaclLength, ACL_REVISION);
  3526. ASSERT(NT_SUCCESS(Status));
  3527. Status = RtlAddAccessAllowedAce(
  3528. Dacl,
  3529. ACL_REVISION,
  3530. GENERIC_ALL,
  3531. LogonSid
  3532. );
  3533. ASSERT(NT_SUCCESS(Status));
  3534. DefaultDacl.DefaultDacl = Dacl;
  3535. Status = NtSetInformationToken(
  3536. RestrictedToken,
  3537. TokenDefaultDacl,
  3538. &DefaultDacl,
  3539. sizeof(TOKEN_DEFAULT_DACL)
  3540. );
  3541. ASSERT(NT_SUCCESS(Status));
  3542. Free(Dacl);
  3543. }
  3544. } else {
  3545. RestrictedToken = NULL;
  3546. }
  3547. //
  3548. // Notify credential managers of the successful logon
  3549. //
  3550. pTokenUser = (PTOKEN_USER) UserBuffer ;
  3551. Status = NtQueryInformationToken( UserToken,
  3552. TokenUser,
  3553. pTokenUser,
  3554. sizeof( UserBuffer ),
  3555. &TokenInfoSize );
  3556. if ( NT_SUCCESS( Status ) )
  3557. {
  3558. pGlobals->UserProcessData.UserSid = LocalAlloc( LMEM_FIXED,
  3559. RtlLengthSid( pTokenUser->User.Sid ) );
  3560. if ( pGlobals->UserProcessData.UserSid )
  3561. {
  3562. RtlCopyMemory( pGlobals->UserProcessData.UserSid,
  3563. pTokenUser->User.Sid,
  3564. RtlLengthSid( pTokenUser->User.Sid ) );
  3565. }
  3566. else
  3567. {
  3568. Status = STATUS_NO_MEMORY ;
  3569. }
  3570. }
  3571. if ( !NT_SUCCESS( Status ) )
  3572. {
  3573. if (pGlobals->Profile) {
  3574. VirtualFree(pGlobals->Profile, 0, MEM_RELEASE);
  3575. pGlobals->Profile = NULL;
  3576. pGlobals->ProfileLength = 0;
  3577. }
  3578. NtClose(UserToken);
  3579. Result = MSGINA_DLG_FAILEDMSGSENT;
  3580. goto exit;
  3581. }
  3582. pGlobals->UserProcessData.RestrictedToken = RestrictedToken;
  3583. pGlobals->UserProcessData.UserToken = UserToken;
  3584. pGlobals->UserProcessData.NewThreadTokenSD = CreateUserThreadTokenSD(LogonSid, pWinlogonSid);
  3585. pGlobals->MprLogonScripts = NULL;
  3586. pGlobals->ExtraApps = NULL ;
  3587. //
  3588. // If we get here, the system works well enough for the user to have
  3589. // actually logged on. Profile failures aren't fixable by last known
  3590. // good anyway. Therefore, declare the boot good.
  3591. //
  3592. ReportBootGood(pGlobals);
  3593. //
  3594. // Set up the system for the new user
  3595. //
  3596. pGlobals->LogonId = LogonId;
  3597. if ((pGlobals->Profile != NULL) && (pGlobals->Profile->FullName.Length > 0)) {
  3598. if (pGlobals->Profile->FullName.Length > MAX_STRING_LENGTH) {
  3599. wcsncpy(pGlobals->UserFullName, pGlobals->Profile->FullName.Buffer, MAX_STRING_LENGTH);
  3600. *(pGlobals->UserFullName + MAX_STRING_LENGTH) = UNICODE_NULL;
  3601. }
  3602. else {
  3603. lstrcpy(pGlobals->UserFullName, pGlobals->Profile->FullName.Buffer);
  3604. }
  3605. } else {
  3606. //
  3607. // No profile - set full name = NULL
  3608. pGlobals->UserFullName[0] = 0;
  3609. ASSERT( lstrlen(pGlobals->UserFullName) == 0);
  3610. }
  3611. //
  3612. // Update our default username and domain ready for the next logon
  3613. //
  3614. //
  3615. // Update the default username & domain only if on the console. Otherwise
  3616. // we'll break AutoAdminLogon by changing the user name.
  3617. //
  3618. if ( g_Console )
  3619. {
  3620. if ( (!pGlobals->AutoAdminLogon) &&
  3621. (SafeBootMode != SAFEBOOT_MINIMAL ) )
  3622. {
  3623. WriteProfileString(APPLICATION_NAME, DEFAULT_USER_NAME_KEY, pGlobals->UserName);
  3624. WriteProfileString(APPLICATION_NAME, DEFAULT_DOMAIN_NAME_KEY, pGlobals->Domain);
  3625. }
  3626. WriteProfileString(APPLICATION_NAME, TEMP_DEFAULT_USER_NAME_KEY, pGlobals->UserName);
  3627. WriteProfileString(APPLICATION_NAME, TEMP_DEFAULT_DOMAIN_NAME_KEY, pGlobals->Domain);
  3628. }
  3629. if ( pGlobals->Domain[0] == '\0' )
  3630. {
  3631. GetProfileString( APPLICATION_NAME,
  3632. DEFAULT_DOMAIN_NAME_KEY,
  3633. TEXT(""),
  3634. pGlobals->Domain,
  3635. MAX_STRING_BYTES );
  3636. }
  3637. if ( !DCacheValidateCache( pGlobals->Cache ) )
  3638. {
  3639. ASSERT( pGlobals->ActiveArray == NULL );
  3640. DCacheUpdateMinimal( pGlobals->Cache, pGlobals->Domain, TRUE );
  3641. }
  3642. else
  3643. {
  3644. //
  3645. // Set the current default:
  3646. //
  3647. DCacheSetDefaultEntry( pGlobals->Cache,
  3648. pGlobals->Domain,
  3649. NULL );
  3650. }
  3651. Result = MSGINA_DLG_SUCCESS;
  3652. exit:
  3653. return Result;
  3654. }
  3655. PWSTR
  3656. AllocAndDuplicateString(
  3657. PWSTR pszString,
  3658. int len)
  3659. {
  3660. PWSTR pszNewString;
  3661. if (!pszString || !len)
  3662. {
  3663. return(NULL);
  3664. }
  3665. pszNewString = LocalAlloc(LMEM_FIXED, (len + 2)*sizeof(WCHAR));
  3666. if (pszNewString)
  3667. {
  3668. wcsncpy(pszNewString, pszString, len);
  3669. pszNewString[len] = UNICODE_NULL;
  3670. }
  3671. return(pszNewString);
  3672. }
  3673. BOOL
  3674. WINAPI
  3675. WlxGetConsoleSwitchCredentials (
  3676. PVOID pWlxContext,
  3677. PVOID pInfo
  3678. )
  3679. {
  3680. PGLOBALS pGlobals = (PGLOBALS) pWlxContext;
  3681. PWLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0 pReq = (PWLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0)pInfo;
  3682. BOOL bReturn = FALSE;
  3683. if (pReq->dwType != WLX_CONSOLESWITCHCREDENTIAL_TYPE_V1_0) {
  3684. return FALSE;
  3685. }
  3686. //
  3687. // Initialize allocated pointers.
  3688. //
  3689. pReq->UserName = NULL;
  3690. pReq->Domain = NULL;
  3691. pReq->LogonScript = NULL;
  3692. pReq->HomeDirectory = NULL;
  3693. pReq->FullName = NULL;
  3694. pReq->ProfilePath = NULL;
  3695. pReq->HomeDirectoryDrive = NULL;
  3696. pReq->LogonServer = NULL;
  3697. pReq->PrivateData = NULL;
  3698. pReq->LogonId = pGlobals->LogonId;
  3699. pReq->UserToken = pGlobals->UserProcessData.UserToken;
  3700. pReq->LogonTime = pGlobals->LogonTime;
  3701. pReq->SmartCardLogon = pGlobals->SmartCardLogon;
  3702. pReq->UserName = AllocAndDuplicateString(pGlobals->UserName,
  3703. (DWORD) wcslen(pGlobals->UserName));
  3704. pReq->Domain = AllocAndDuplicateString(pGlobals->Domain,
  3705. (DWORD) wcslen(pGlobals->Domain));
  3706. //
  3707. // Quota Information
  3708. //
  3709. pReq->Quotas.PagedPoolLimit = pGlobals->UserProcessData.Quotas.PagedPoolLimit;
  3710. pReq->Quotas.NonPagedPoolLimit = pGlobals->UserProcessData.Quotas.NonPagedPoolLimit;
  3711. pReq->Quotas.MinimumWorkingSetSize = pGlobals->UserProcessData.Quotas.MinimumWorkingSetSize;
  3712. pReq->Quotas.MaximumWorkingSetSize = pGlobals->UserProcessData.Quotas.MaximumWorkingSetSize;
  3713. pReq->Quotas.PagefileLimit = pGlobals->UserProcessData.Quotas.PagefileLimit;
  3714. pReq->Quotas.TimeLimit = pGlobals->UserProcessData.Quotas.TimeLimit;
  3715. //
  3716. // Profile Information
  3717. //
  3718. pReq->ProfileLength = pGlobals->ProfileLength;
  3719. pReq->UserFlags = pGlobals->Profile->UserFlags;
  3720. pReq->MessageType = pGlobals->Profile->MessageType;
  3721. pReq->LogonCount = pGlobals->Profile->LogonCount;
  3722. pReq->BadPasswordCount = pGlobals->Profile->BadPasswordCount;
  3723. pReq->ProfileLogonTime = pGlobals->Profile->LogonTime;
  3724. pReq->LogoffTime = pGlobals->Profile->LogoffTime;
  3725. pReq->KickOffTime = pGlobals->Profile->KickOffTime;
  3726. pReq->PasswordLastSet = pGlobals->Profile->PasswordLastSet;
  3727. pReq->PasswordCanChange = pGlobals->Profile->PasswordCanChange;
  3728. pReq->PasswordMustChange = pGlobals->Profile->PasswordMustChange;
  3729. pReq->LogonScript = AllocAndDuplicateString(pGlobals->Profile->LogonScript.Buffer, pGlobals->Profile->LogonScript.Length/sizeof(WCHAR));
  3730. pReq->HomeDirectory = AllocAndDuplicateString(pGlobals->Profile->HomeDirectory.Buffer, pGlobals->Profile->HomeDirectory.Length/sizeof(WCHAR));
  3731. pReq->FullName = AllocAndDuplicateString(pGlobals->Profile->FullName.Buffer, pGlobals->Profile->FullName.Length/sizeof(WCHAR));
  3732. pReq->ProfilePath = AllocAndDuplicateString(pGlobals->Profile->ProfilePath.Buffer, pGlobals->Profile->ProfilePath.Length/sizeof(WCHAR));
  3733. pReq->HomeDirectoryDrive = AllocAndDuplicateString(pGlobals->Profile->HomeDirectoryDrive.Buffer, pGlobals->Profile->HomeDirectoryDrive.Length/sizeof(WCHAR));
  3734. pReq->LogonServer = AllocAndDuplicateString(pGlobals->Profile->LogonServer.Buffer, pGlobals->Profile->LogonServer.Length/sizeof(WCHAR));
  3735. pReq->PrivateDataLen = PASSWORD_HASH_SIZE;
  3736. pReq->PrivateData = (PBYTE)AllocAndDuplicateString((PWSTR)pGlobals->PasswordHash, PASSWORD_HASH_SIZE );
  3737. if (pReq->PrivateData == NULL) {
  3738. goto done;
  3739. }
  3740. memcpy(pReq->PrivateData, pGlobals->PasswordHash, PASSWORD_HASH_SIZE );
  3741. bReturn = TRUE;
  3742. done:
  3743. if (!bReturn) {
  3744. if (pReq->UserName != NULL) {
  3745. LocalFree(pReq->UserName);
  3746. }
  3747. if (pReq->Domain != NULL) {
  3748. LocalFree(pReq->Domain);
  3749. }
  3750. if (pReq->LogonScript != NULL) {
  3751. LocalFree(pReq->LogonScript);
  3752. }
  3753. if (pReq->HomeDirectory != NULL) {
  3754. LocalFree(pReq->HomeDirectory);
  3755. }
  3756. if (pReq->FullName != NULL) {
  3757. LocalFree(pReq->FullName);
  3758. }
  3759. if (pReq->ProfilePath != NULL) {
  3760. LocalFree(pReq->ProfilePath);
  3761. }
  3762. if (pReq->HomeDirectoryDrive != NULL) {
  3763. LocalFree(pReq->HomeDirectoryDrive);
  3764. }
  3765. if (pReq->LogonServer != NULL) {
  3766. LocalFree(pReq->LogonServer);
  3767. }
  3768. if (pReq->PrivateData != NULL) {
  3769. LocalFree(pReq->PrivateData);
  3770. }
  3771. }
  3772. return bReturn;
  3773. }
  3774. //+---------------------------------------------------------------------------
  3775. //
  3776. // Function: QuerySwitchConsoleCredentials
  3777. //
  3778. // Notes:
  3779. //
  3780. // Query credentials from session connecting to console to do switch console
  3781. // This routine gets called in response to WLX_SAS_TYPE_AUTHENTICATED
  3782. // in the context of the console session (sessionid 0) winlogon.
  3783. // This type of logon is for Single Session Terminal Server. When a user
  3784. // logs on from a remote TS session, we pass the credentials from the remote session
  3785. // to the console session and do an auto-logon. This routine queries the credentials,
  3786. // logs on the user on the console sesion
  3787. //
  3788. //
  3789. //----------------------------------------------------------------------------
  3790. BOOL
  3791. WINAPI
  3792. QuerySwitchConsoleCredentials(PGLOBALS pGlobals, HANDLE * phUserToken, PLUID pLogonId)
  3793. {
  3794. WLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0 CredInfo;
  3795. RtlZeroMemory(&CredInfo,sizeof(CredInfo));
  3796. CredInfo.dwType = WLX_CONSOLESWITCHCREDENTIAL_TYPE_V1_0;
  3797. if (!pWlxFuncs->WlxQueryConsoleSwitchCredentials(&CredInfo)){
  3798. return FALSE;
  3799. }
  3800. if (!CredInfo.UserToken || !CredInfo.UserName) {
  3801. //return false if any of the critical information is missing
  3802. return FALSE;
  3803. }
  3804. pGlobals->Profile = (PMSV1_0_INTERACTIVE_PROFILE) VirtualAlloc(NULL,
  3805. sizeof(MSV1_0_INTERACTIVE_PROFILE),
  3806. MEM_COMMIT,
  3807. PAGE_READWRITE);
  3808. if (pGlobals->Profile == NULL) {
  3809. goto returnerror;
  3810. }
  3811. //
  3812. // Token, LUID
  3813. //
  3814. *pLogonId = CredInfo.LogonId;
  3815. *phUserToken = CredInfo.UserToken;
  3816. pGlobals->LogonTime = CredInfo.LogonTime;
  3817. pGlobals->SmartCardLogon = CredInfo.SmartCardLogon;
  3818. pGlobals->SmartCardOption = GetProfileInt( APPLICATION_NAME, SC_REMOVE_OPTION, 0 );
  3819. //
  3820. // Quota Information
  3821. //
  3822. pGlobals->UserProcessData.Quotas.PagedPoolLimit = CredInfo.Quotas.PagedPoolLimit ;
  3823. pGlobals->UserProcessData.Quotas.NonPagedPoolLimit = CredInfo.Quotas.NonPagedPoolLimit;
  3824. pGlobals->UserProcessData.Quotas.MinimumWorkingSetSize = CredInfo.Quotas.MinimumWorkingSetSize;
  3825. pGlobals->UserProcessData.Quotas.MaximumWorkingSetSize = CredInfo.Quotas.MaximumWorkingSetSize;
  3826. pGlobals->UserProcessData.Quotas.PagefileLimit = CredInfo.Quotas.PagefileLimit;
  3827. pGlobals->UserProcessData.Quotas.TimeLimit = CredInfo.Quotas.TimeLimit;
  3828. //
  3829. // Profile Information
  3830. //
  3831. pGlobals->ProfileLength = CredInfo.ProfileLength;
  3832. pGlobals->Profile->UserFlags = CredInfo.UserFlags;
  3833. pGlobals->Profile->MessageType = CredInfo.MessageType;
  3834. pGlobals->Profile->LogonCount = CredInfo.LogonCount;
  3835. pGlobals->Profile->BadPasswordCount = CredInfo.BadPasswordCount;
  3836. pGlobals->Profile->LogonTime = CredInfo.ProfileLogonTime;
  3837. pGlobals->Profile->LogoffTime = CredInfo.LogoffTime;
  3838. pGlobals->Profile->KickOffTime = CredInfo.KickOffTime;
  3839. pGlobals->Profile->PasswordLastSet = CredInfo.PasswordLastSet;
  3840. pGlobals->Profile->PasswordCanChange = CredInfo.PasswordCanChange;
  3841. pGlobals->Profile->PasswordMustChange = CredInfo.PasswordMustChange;
  3842. RtlInitUnicodeString(&pGlobals->Profile->LogonScript, CredInfo.LogonScript);
  3843. RtlInitUnicodeString(&pGlobals->Profile->HomeDirectory, CredInfo.HomeDirectory);
  3844. RtlInitUnicodeString(&pGlobals->Profile->FullName, CredInfo.FullName);
  3845. RtlInitUnicodeString(&pGlobals->Profile->ProfilePath, CredInfo.ProfilePath);
  3846. RtlInitUnicodeString(&pGlobals->Profile->HomeDirectoryDrive, CredInfo.HomeDirectoryDrive);
  3847. RtlInitUnicodeString(&pGlobals->Profile->LogonServer, CredInfo.LogonServer);
  3848. if (CredInfo.UserName) {
  3849. wcscpy(pGlobals->UserName,CredInfo.UserName);
  3850. LocalFree(CredInfo.UserName);
  3851. } else {
  3852. wcscpy(pGlobals->UserName,L"");
  3853. }
  3854. if (CredInfo.Domain) {
  3855. wcscpy(pGlobals->Domain,CredInfo.Domain);
  3856. LocalFree(CredInfo.Domain);
  3857. } else {
  3858. wcscpy(pGlobals->Domain,L"");
  3859. }
  3860. if (CredInfo.PrivateDataLen) {
  3861. RtlCopyMemory(pGlobals->PasswordHash,CredInfo.PrivateData, CredInfo.PrivateDataLen );
  3862. LocalFree(CredInfo.PrivateData);
  3863. } else {
  3864. RtlZeroMemory(pGlobals->PasswordHash,PASSWORD_HASH_SIZE);
  3865. }
  3866. pGlobals->TransderedCredentials = TRUE;
  3867. return TRUE;
  3868. returnerror:
  3869. if (CredInfo.UserName) {
  3870. LocalFree(CredInfo.UserName);
  3871. }
  3872. if (CredInfo.Domain) {
  3873. LocalFree(CredInfo.Domain);
  3874. }
  3875. if (CredInfo.LogonScript) {
  3876. LocalFree(CredInfo.LogonScript);
  3877. }
  3878. if (CredInfo.HomeDirectory) {
  3879. LocalFree(CredInfo.HomeDirectory);
  3880. }
  3881. if (CredInfo.FullName) {
  3882. LocalFree(CredInfo.FullName);
  3883. }
  3884. if (CredInfo.ProfilePath) {
  3885. LocalFree(CredInfo.ProfilePath);
  3886. }
  3887. if (CredInfo.HomeDirectoryDrive) {
  3888. LocalFree(CredInfo.HomeDirectoryDrive);
  3889. }
  3890. if (CredInfo.LogonServer) {
  3891. LocalFree(CredInfo.LogonServer);
  3892. }
  3893. if (CredInfo.UserToken) {
  3894. CloseHandle(CredInfo.UserToken);
  3895. }
  3896. if (pGlobals->Profile) {
  3897. VirtualFree(pGlobals->Profile, 0, MEM_RELEASE);
  3898. pGlobals->Profile = NULL;
  3899. pGlobals->ProfileLength = 0;
  3900. }
  3901. return FALSE;
  3902. }
  3903. BOOL
  3904. GetAndAllocateLogonSid(
  3905. HANDLE hToken,
  3906. PSID *pLogonSid
  3907. )
  3908. {
  3909. PTOKEN_GROUPS ptgGroups = NULL;
  3910. DWORD cbBuffer = 512; // allocation size
  3911. DWORD dwSidLength; // required size to hold Sid
  3912. UINT i; // Sid index counter
  3913. BOOL bSuccess = FALSE; // assume this function will fail
  3914. *pLogonSid = NULL; // invalidate pointer
  3915. //
  3916. // initial allocation attempts
  3917. //
  3918. ptgGroups=(PTOKEN_GROUPS)Alloc(cbBuffer);
  3919. if(ptgGroups == NULL) return FALSE;
  3920. __try {
  3921. //
  3922. // obtain token information. reallocate memory if necessary
  3923. //
  3924. while(!GetTokenInformation(
  3925. hToken, TokenGroups, ptgGroups, cbBuffer, &cbBuffer)) {
  3926. //
  3927. // if appropriate, reallocate memory, otherwise bail
  3928. //
  3929. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  3930. //
  3931. // attempt to reallocate buffer
  3932. //
  3933. if((ptgGroups=(PTOKEN_GROUPS)ReAlloc(
  3934. ptgGroups, cbBuffer)) == NULL) __leave;
  3935. }
  3936. else __leave;
  3937. }
  3938. //
  3939. // Get the logon Sid by looping through the Sids in the token
  3940. //
  3941. for(i = 0 ; i < ptgGroups->GroupCount ; i++) {
  3942. if(ptgGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) {
  3943. //
  3944. // insure we are dealing with a valid Sid
  3945. //
  3946. if(!IsValidSid(ptgGroups->Groups[i].Sid)) __leave;
  3947. //
  3948. // get required allocation size to copy the Sid
  3949. //
  3950. dwSidLength=GetLengthSid(ptgGroups->Groups[i].Sid);
  3951. //
  3952. // allocate storage for the Logon Sid
  3953. //
  3954. if((*pLogonSid=(PSID *)Alloc(
  3955. dwSidLength)) == NULL) __leave;
  3956. //
  3957. // copy the Logon Sid to the storage we just allocated
  3958. //
  3959. if(!CopySid(dwSidLength, *pLogonSid, ptgGroups->Groups[i].Sid)) __leave;
  3960. bSuccess=TRUE; // indicate success...
  3961. break; // ...and get out
  3962. }
  3963. }
  3964. } // try
  3965. __finally {
  3966. //
  3967. // free allocated resources
  3968. //
  3969. if(ptgGroups != NULL) Free(ptgGroups);
  3970. if(!bSuccess) {
  3971. if(*pLogonSid != NULL) {
  3972. Free(*pLogonSid);
  3973. *pLogonSid = NULL;
  3974. }
  3975. }
  3976. } // finally
  3977. return bSuccess;
  3978. }