Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2468 lines
72 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: msgina.c
  7. //
  8. // Contents: Microsoft Logon GUI DLL
  9. //
  10. // History: 7-14-94 RichardW Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "msgina.h"
  14. // Link Window
  15. #include "shlobj.h"
  16. #include "shlobjp.h"
  17. #include <accctrl.h>
  18. #include <aclapi.h>
  19. #include "tsperf.h"
  20. HINSTANCE hDllInstance; // My instance, for resource loading
  21. HINSTANCE hAppInstance; // App instance, for dialogs, etc.
  22. PWLX_DISPATCH_VERSION_1_4 pWlxFuncs; // Ptr to table of functions
  23. PWLX_DISPATCH_VERSION_1_4 pTrueTable ; // Ptr to table in winlogon
  24. DWORD SafeBootMode;
  25. BOOL g_IsTerminalServer;
  26. BOOL g_Console = TRUE;
  27. BOOL VersionMismatch ;
  28. DWORD InterfaceVersion ;
  29. HKEY WinlogonKey ;
  30. int TSAuthenticatedLogon(PGLOBALS pGlobals);
  31. BOOL
  32. WINAPI
  33. DllMain(
  34. HINSTANCE hInstance,
  35. DWORD dwReason,
  36. LPVOID lpReserved)
  37. {
  38. switch (dwReason)
  39. {
  40. case DLL_PROCESS_ATTACH:
  41. DisableThreadLibraryCalls ( hInstance );
  42. hDllInstance = hInstance;
  43. g_IsTerminalServer = !!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer));
  44. #if DBG
  45. InitDebugSupport();
  46. #endif
  47. InitializeSecurityGlobals();
  48. _Shell_DllMain(hInstance, dwReason);
  49. return(TRUE);
  50. case DLL_PROCESS_DETACH:
  51. _Shell_DllMain(hInstance, dwReason);
  52. FreeSecurityGlobals();
  53. return(TRUE);
  54. default:
  55. return(TRUE);
  56. }
  57. }
  58. BOOL
  59. WINAPI
  60. WlxNegotiate(
  61. DWORD dwWinlogonVersion,
  62. DWORD *pdwDllVersion
  63. )
  64. {
  65. InterfaceVersion = dwWinlogonVersion ;
  66. if (dwWinlogonVersion < WLX_CURRENT_VERSION)
  67. {
  68. DebugLog(( DEB_WARN, "Old WLX interface (%x)\n", dwWinlogonVersion ));
  69. if ( dwWinlogonVersion < WLX_VERSION_1_1 )
  70. {
  71. return FALSE ;
  72. }
  73. VersionMismatch = TRUE ;
  74. }
  75. *pdwDllVersion = WLX_CURRENT_VERSION;
  76. DebugLog((DEB_TRACE, "Negotiate: successful!\n"));
  77. return(TRUE);
  78. }
  79. BOOL GetDefaultCADSetting(void)
  80. {
  81. BOOL bDisableCad = FALSE;
  82. NT_PRODUCT_TYPE NtProductType;
  83. //
  84. // Servers and workstations in a domain will default to requiring CAD.
  85. // Workstations in a workgroup won't require CAD (by default). Note,
  86. // the default CAD setting can be overwritten by either a machine
  87. // preference or machine policy.
  88. //
  89. RtlGetNtProductType(&NtProductType);
  90. if ( IsWorkstation(NtProductType) )
  91. {
  92. if ( !IsMachineDomainMember() ) // This function is doing some caching
  93. { // so we don't need to be brighter here
  94. bDisableCad = TRUE;
  95. }
  96. }
  97. return bDisableCad;
  98. }
  99. #define MSGINA_ANIM_FAST_TIME 20
  100. #define MSGINA_ANIM_REMOTE_TIME 100
  101. #define MSGINA_ANIM_SLOW_TIME 500
  102. //
  103. // GetAnimationTimeInterval
  104. // Purpose:
  105. // Retreive animation time interval in ms. There are different settings depending
  106. // on w/not we are remote
  107. //
  108. //
  109. // Params:
  110. // pGlobals - IN global settings
  111. //
  112. // Returns:
  113. // Animation timeslice in milliseconds.
  114. //
  115. DWORD GetAnimationTimeInterval(PGLOBALS pGlobals)
  116. {
  117. DWORD dwAnimationTimeSlice;
  118. if (IsActiveConsoleSession()) {
  119. //Console defaults
  120. dwAnimationTimeSlice = MSGINA_ANIM_FAST_TIME;
  121. }
  122. else if (pGlobals->MuGlobals.fSlowAnimationRate) {
  123. //Remote but reduced animation
  124. dwAnimationTimeSlice = MSGINA_ANIM_SLOW_TIME;
  125. }
  126. else {
  127. //Remote but with anim
  128. dwAnimationTimeSlice = MSGINA_ANIM_REMOTE_TIME;
  129. }
  130. return dwAnimationTimeSlice;
  131. }
  132. BOOL GetDisableCad(PGLOBALS pGlobals)
  133. // Returns whether or not the user should be required to press C-A-D before
  134. // logging on. TRUE == Disable CAD, FALSE == Require CAD
  135. {
  136. DWORD dwSize;
  137. DWORD dwType;
  138. HKEY hKey;
  139. BOOL fDisableCad = GetDefaultCADSetting();
  140. dwSize = sizeof(fDisableCad);
  141. RegQueryValueEx (WinlogonKey, DISABLE_CAD, NULL, &dwType,
  142. (LPBYTE) &fDisableCad , &dwSize);
  143. //
  144. // Check if C+A+D is disabled via policy
  145. //
  146. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINLOGON_POLICY_KEY, 0, KEY_READ,
  147. &hKey) == ERROR_SUCCESS)
  148. {
  149. dwSize = sizeof(fDisableCad);
  150. RegQueryValueEx (hKey, DISABLE_CAD, NULL, &dwType,
  151. (LPBYTE) &fDisableCad , &dwSize);
  152. RegCloseKey (hKey);
  153. }
  154. //
  155. // By default do a fast animation for the progress band
  156. //
  157. pGlobals->MuGlobals.fSlowAnimationRate = FALSE;
  158. //
  159. // Check if C+A+D is disabled for remote Hydra clients and copy the client name
  160. //
  161. if (g_IsTerminalServer ) {
  162. HANDLE dllHandle;
  163. //
  164. // Load winsta.dll
  165. //
  166. dllHandle = LoadLibraryW(L"winsta.dll");
  167. if (dllHandle) {
  168. PWINSTATION_QUERY_INFORMATION pfnWinstationQueryInformation;
  169. pfnWinstationQueryInformation = (PWINSTATION_QUERY_INFORMATION) GetProcAddress(
  170. dllHandle,
  171. "WinStationQueryInformationW"
  172. );
  173. if (pfnWinstationQueryInformation) {
  174. WINSTATIONCLIENT ClientData;
  175. ULONG Length;
  176. //
  177. // Get the CAD disable data from the client
  178. //
  179. if ( pfnWinstationQueryInformation( SERVERNAME_CURRENT,
  180. LOGONID_CURRENT,
  181. WinStationClient,
  182. &ClientData,
  183. sizeof(ClientData),
  184. &Length ) ) {
  185. //
  186. // Take the client settings only if the CAD is not globally disabled for the server,
  187. // and, if this is not the console active session.
  188. //
  189. if (!fDisableCad && !IsActiveConsoleSession() )
  190. {
  191. fDisableCad = ClientData.fDisableCtrlAltDel;
  192. }
  193. //
  194. // Copy the Client Name, even console has a client name now, due to PTS and console disconnect features.
  195. //
  196. //
  197. lstrcpyn(pGlobals->MuGlobals.ClientName, ClientData.ClientName, CLIENTNAME_LENGTH);
  198. if (ClientData.PerformanceFlags &
  199. TS_PERF_DISABLE_MENUANIMATIONS) {
  200. pGlobals->MuGlobals.fSlowAnimationRate = TRUE;
  201. }
  202. }
  203. else
  204. {
  205. if (!IsActiveConsoleSession()) {
  206. fDisableCad = TRUE;
  207. }
  208. // TS start could have been delayed until 60seconds post first console login.
  209. // Hence, it is safe to assume that this is the console session, besides,
  210. // we are initing some benign env var.
  211. lstrcpyn(pGlobals->MuGlobals.ClientName,L"Console", CLIENTNAME_LENGTH );
  212. }
  213. }
  214. FreeLibrary(dllHandle);
  215. }
  216. }
  217. // Friendly UI on -> ALWAYS disable CAD.
  218. if (ShellIsFriendlyUIActive())
  219. {
  220. fDisableCad = TRUE;
  221. }
  222. return fDisableCad;
  223. }
  224. BOOL GetSCForceOption()
  225. // Returns whether or not the user should be required to use a SC to logon
  226. // TRUE == ForceSCLogon, FALSE == Non ForceSCLogon
  227. {
  228. DWORD dwSize;
  229. DWORD dwType;
  230. HKEY hKey;
  231. BOOL fForceSCLogon = FALSE;
  232. if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINLOGON_POLICY_KEY, 0, KEY_READ,
  233. &hKey) == ERROR_SUCCESS )
  234. {
  235. dwSize = sizeof(fForceSCLogon);
  236. RegQueryValueEx(hKey, FORCE_SC_LOGON, NULL, &dwType,
  237. (LPBYTE) &fForceSCLogon , &dwSize);
  238. RegCloseKey (hKey);
  239. }
  240. return fForceSCLogon;
  241. }
  242. BOOL
  243. MsGinaSetOption(
  244. HANDLE hWlx,
  245. DWORD Option,
  246. ULONG_PTR Value,
  247. ULONG_PTR * OldValue
  248. )
  249. {
  250. return FALSE ;
  251. }
  252. BOOL
  253. MsGinaGetOption(
  254. HANDLE hWlx,
  255. DWORD Option,
  256. ULONG_PTR * Value
  257. )
  258. {
  259. return FALSE ;
  260. }
  261. PWLX_DISPATCH_VERSION_1_4
  262. GetFixedUpTable(
  263. PVOID FakeTable
  264. )
  265. {
  266. int err ;
  267. PVOID p ;
  268. PWLX_DISPATCH_VERSION_1_4 pNewTable ;
  269. DWORD dwSize ;
  270. DWORD dwType ;
  271. pNewTable = LocalAlloc( LMEM_FIXED, sizeof( WLX_DISPATCH_VERSION_1_4 ) );
  272. if ( !pNewTable )
  273. {
  274. return NULL ;
  275. }
  276. dwSize = sizeof( PVOID );
  277. err = RegQueryValueEx(
  278. WinlogonKey,
  279. TEXT("Key"),
  280. NULL,
  281. &dwType,
  282. (PUCHAR) &p,
  283. &dwSize );
  284. if ( (err == 0) &&
  285. (dwType == REG_BINARY) &&
  286. (dwSize == sizeof( PVOID ) ) )
  287. {
  288. pTrueTable = p ;
  289. switch ( InterfaceVersion )
  290. {
  291. case WLX_VERSION_1_1:
  292. dwSize = sizeof( WLX_DISPATCH_VERSION_1_1 );
  293. break;
  294. case WLX_VERSION_1_2:
  295. case WLX_VERSION_1_3:
  296. case WLX_VERSION_1_4:
  297. dwSize = sizeof( WLX_DISPATCH_VERSION_1_2 );
  298. break;
  299. }
  300. RtlCopyMemory(
  301. pNewTable,
  302. FakeTable,
  303. dwSize );
  304. pNewTable->WlxGetOption = MsGinaGetOption ;
  305. pNewTable->WlxSetOption = MsGinaSetOption ;
  306. pNewTable->WlxCloseUserDesktop = pTrueTable->WlxCloseUserDesktop ;
  307. pNewTable->WlxWin31Migrate = pTrueTable->WlxWin31Migrate ;
  308. pNewTable->WlxQueryClientCredentials = pTrueTable->WlxQueryClientCredentials ;
  309. pNewTable->WlxQueryInetConnectorCredentials = pTrueTable->WlxQueryInetConnectorCredentials ;
  310. pNewTable->WlxDisconnect = pTrueTable->WlxDisconnect ;
  311. pNewTable->WlxQueryTerminalServicesData = pTrueTable->WlxQueryTerminalServicesData ;
  312. pNewTable->WlxQueryConsoleSwitchCredentials = pTrueTable->WlxQueryConsoleSwitchCredentials ;
  313. pNewTable->WlxQueryTsLogonCredentials = pTrueTable->WlxQueryTsLogonCredentials;
  314. }
  315. else
  316. {
  317. LocalFree( pNewTable );
  318. pNewTable = NULL ;
  319. }
  320. return pNewTable ;
  321. }
  322. extern DWORD g_dwMainThreadId; // declared in status.c (used to "fix" a thread safety issue)
  323. BOOL
  324. WINAPI
  325. WlxInitialize(
  326. LPWSTR lpWinsta,
  327. HANDLE hWlx,
  328. PVOID pvReserved,
  329. PVOID pWinlogonFunctions,
  330. PVOID *pWlxContext
  331. )
  332. {
  333. PGLOBALS pGlobals;
  334. HKEY hKey;
  335. DWORD dwSize, dwType;
  336. DWORD dwStringMemory;
  337. DWORD dwAutoLogonCount ;
  338. DWORD dwNoLockWksta ;
  339. // Upon which bitmaps should our text be painted.
  340. BOOL fTextOnLarge;
  341. BOOL fTextOnSmall;
  342. ULONG_PTR ProbeValue ;
  343. PWLX_GET_OPTION GetOptCall ;
  344. BOOL DoFixup ;
  345. BOOL DidFixup ;
  346. int err ;
  347. err = RegOpenKeyEx(
  348. HKEY_LOCAL_MACHINE,
  349. WINLOGON_KEY,
  350. 0,
  351. KEY_READ | KEY_WRITE,
  352. &WinlogonKey );
  353. if ( err != 0 )
  354. {
  355. return FALSE ;
  356. }
  357. DoFixup = TRUE ;
  358. DidFixup = FALSE ;
  359. if ( VersionMismatch )
  360. {
  361. pWlxFuncs = GetFixedUpTable( pWinlogonFunctions );
  362. if ( pWlxFuncs )
  363. {
  364. DidFixup = TRUE ;
  365. }
  366. else
  367. {
  368. pWlxFuncs = (PWLX_DISPATCH_VERSION_1_4) pWinlogonFunctions ;
  369. DidFixup = FALSE ;
  370. }
  371. }
  372. else
  373. {
  374. pWlxFuncs = (PWLX_DISPATCH_VERSION_1_4) pWinlogonFunctions ;
  375. }
  376. //
  377. // Probe the callback table to make sure we're ok:
  378. //
  379. try
  380. {
  381. GetOptCall = pWlxFuncs->WlxGetOption ;
  382. if ( GetOptCall( hWlx,
  383. WLX_OPTION_DISPATCH_TABLE_SIZE,
  384. &ProbeValue ) )
  385. {
  386. if ( ProbeValue == sizeof( WLX_DISPATCH_VERSION_1_4 ) )
  387. {
  388. DoFixup = FALSE ;
  389. }
  390. }
  391. }
  392. except ( EXCEPTION_EXECUTE_HANDLER )
  393. {
  394. NOTHING ;
  395. }
  396. if ( DoFixup && !DidFixup )
  397. {
  398. pWlxFuncs = GetFixedUpTable( pWinlogonFunctions );
  399. }
  400. if ( !pWlxFuncs )
  401. {
  402. return FALSE ;
  403. }
  404. pGlobals = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GLOBALS));
  405. if ( !pGlobals )
  406. {
  407. return FALSE ;
  408. }
  409. if ( !NT_SUCCESS ( RtlInitializeCriticalSection( &pGlobals->csGlobals ) ) )
  410. {
  411. LocalFree( pGlobals );
  412. return FALSE ;
  413. }
  414. if ( !InitHKeyCurrentUserSupport() )
  415. {
  416. RtlDeleteCriticalSection( &pGlobals->csGlobals );
  417. LocalFree( pGlobals );
  418. return FALSE ;
  419. }
  420. // Reserve enough memory for 4 strings of length MAX_STRING_BYTES
  421. dwStringMemory = (MAX_STRING_BYTES * sizeof (WCHAR)) * 4;
  422. pGlobals->LockedMemory = VirtualAlloc(
  423. NULL,
  424. dwStringMemory,
  425. MEM_COMMIT,
  426. PAGE_READWRITE);
  427. if ( pGlobals->LockedMemory == NULL )
  428. {
  429. CleanupHKeyCurrentUserSupport();
  430. RtlDeleteCriticalSection( &pGlobals->csGlobals );
  431. LocalFree( pGlobals );
  432. return FALSE ;
  433. }
  434. VirtualLock( pGlobals->LockedMemory, dwStringMemory);
  435. memset( pGlobals->LockedMemory, 0, dwStringMemory );
  436. pGlobals->UserName = pGlobals->LockedMemory ;
  437. pGlobals->Domain = pGlobals->UserName + MAX_STRING_BYTES ;
  438. pGlobals->Password = pGlobals->Domain + MAX_STRING_BYTES ;
  439. pGlobals->OldPassword = pGlobals->Password + MAX_STRING_BYTES ;
  440. *pWlxContext = (PVOID) pGlobals;
  441. pGlobals->hGlobalWlx = hWlx;
  442. pWlxFuncs->WlxUseCtrlAltDel(hWlx);
  443. if ( DCacheInitialize() )
  444. {
  445. pGlobals->Cache = DCacheCreate();
  446. }
  447. else
  448. {
  449. pGlobals->Cache = NULL ;
  450. }
  451. if ( pGlobals->Cache == NULL )
  452. {
  453. CleanupHKeyCurrentUserSupport();
  454. RtlDeleteCriticalSection(&pGlobals->csGlobals);
  455. VirtualFree( pGlobals->LockedMemory, 0, MEM_RELEASE );
  456. LocalFree (pGlobals);
  457. DebugLog((DEB_ERROR, "Failed to init domain cache!\n"));
  458. return(FALSE);
  459. }
  460. dwSize = sizeof( dwNoLockWksta );
  461. if ( RegQueryValueEx(
  462. WinlogonKey,
  463. DISABLE_LOCK_WKSTA,
  464. 0,
  465. &dwType,
  466. (PUCHAR) &dwNoLockWksta,
  467. &dwSize ) == 0 )
  468. {
  469. if ( dwNoLockWksta == 2 )
  470. {
  471. dwNoLockWksta = 0 ;
  472. RegSetValueEx(
  473. WinlogonKey,
  474. DISABLE_LOCK_WKSTA,
  475. 0,
  476. REG_DWORD,
  477. (PUCHAR) &dwNoLockWksta,
  478. sizeof( DWORD ) );
  479. }
  480. }
  481. if (!InitializeAuthentication(pGlobals))
  482. {
  483. *pWlxContext = NULL;
  484. CleanupHKeyCurrentUserSupport();
  485. RtlDeleteCriticalSection(&pGlobals->csGlobals);
  486. VirtualFree( pGlobals->LockedMemory, 0, MEM_RELEASE );
  487. LocalFree (pGlobals);
  488. DebugLog((DEB_ERROR, "Failed to init authentication!\n"));
  489. return(FALSE);
  490. }
  491. //
  492. // Start by clearing the entire Multi-User Globals
  493. //
  494. RtlZeroMemory( &pGlobals->MuGlobals, sizeof(pGlobals->MuGlobals) );
  495. //
  496. // Get our SessionId and save in globals
  497. //
  498. pGlobals->MuGlobals.SessionId = NtCurrentPeb()->SessionId;
  499. if (pGlobals->MuGlobals.SessionId != 0) {
  500. g_Console = FALSE;
  501. }
  502. //
  503. // if this is a TS session, we can't run if there is a version
  504. // mismatch. Fail out now.
  505. //
  506. if ( (!g_Console) &&
  507. (VersionMismatch ) )
  508. {
  509. *pWlxContext = NULL;
  510. CleanupHKeyCurrentUserSupport();
  511. RtlDeleteCriticalSection(&pGlobals->csGlobals);
  512. LocalFree (pGlobals);
  513. DebugLog((DEB_ERROR, "Failed to init authentication!\n"));
  514. return(FALSE);
  515. }
  516. //
  517. // this actually starts the s/c thread.
  518. //
  519. if( g_Console )
  520. {
  521. ULONG_PTR Value ;
  522. pWlxFuncs->WlxGetOption(pGlobals->hGlobalWlx,
  523. WLX_OPTION_SMART_CARD_PRESENT,
  524. &Value);
  525. }
  526. //
  527. // If this is auto admin logon, or ctrl+alt+del is disabled,
  528. // generate a fake SAS right now. Don't attempt AutoLogon unless on Console
  529. //
  530. if ((g_Console && GetProfileInt( APPLICATION_NAME, TEXT("AutoAdminLogon"), 0) ) ||
  531. GetDisableCad(pGlobals))
  532. {
  533. dwSize = sizeof( DWORD );
  534. if ( RegQueryValueEx( WinlogonKey, AUTOLOGONCOUNT_KEY, NULL,
  535. &dwType, (LPBYTE) &dwAutoLogonCount,
  536. &dwSize ) == 0 )
  537. {
  538. //
  539. // AutoLogonCount value was present. Check the value:
  540. //
  541. if ( dwAutoLogonCount == 0 )
  542. {
  543. //
  544. // Went to zero. Reset everything:
  545. //
  546. RegDeleteValue( WinlogonKey, AUTOLOGONCOUNT_KEY );
  547. RegDeleteValue( WinlogonKey, DEFAULT_PASSWORD_KEY );
  548. RegSetValueEx( WinlogonKey, AUTOADMINLOGON_KEY, 0,
  549. REG_SZ, (LPBYTE) TEXT("0"), 2 * sizeof(WCHAR) );
  550. }
  551. else
  552. {
  553. //
  554. // Decrement the count, and try the logon:
  555. //
  556. dwAutoLogonCount-- ;
  557. RegSetValueEx( WinlogonKey, AUTOLOGONCOUNT_KEY,
  558. 0, REG_DWORD, (LPBYTE) &dwAutoLogonCount,
  559. sizeof( DWORD ) );
  560. KdPrint(( "AutoAdminLogon = 1\n" ));
  561. pWlxFuncs->WlxSasNotify(pGlobals->hGlobalWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
  562. }
  563. }
  564. else
  565. {
  566. //
  567. // AutoLogonCount not present
  568. //
  569. KdPrint(( "AutoAdminLogon = 1\n" ));
  570. pWlxFuncs->WlxSasNotify( pGlobals->hGlobalWlx, WLX_SAS_TYPE_CTRL_ALT_DEL );
  571. }
  572. }
  573. //
  574. // get the safeboot mode
  575. //
  576. if (RegOpenKeyEx(
  577. HKEY_LOCAL_MACHINE,
  578. TEXT("system\\currentcontrolset\\control\\safeboot\\option"),
  579. 0,
  580. KEY_READ,
  581. & hKey
  582. ) == ERROR_SUCCESS)
  583. {
  584. dwSize = sizeof(DWORD);
  585. RegQueryValueEx (
  586. hKey,
  587. TEXT("OptionValue"),
  588. NULL,
  589. &dwType,
  590. (LPBYTE) &SafeBootMode,
  591. &dwSize
  592. );
  593. RegCloseKey( hKey );
  594. }
  595. //
  596. // Load branding images
  597. //
  598. LoadBrandingImages(FALSE, &fTextOnLarge, &fTextOnSmall);
  599. //
  600. // Create fonts
  601. //
  602. CreateFonts(&pGlobals->GinaFonts);
  603. //
  604. // Draw localized text on branding images
  605. //
  606. PaintBitmapText(&pGlobals->GinaFonts, fTextOnLarge, fTextOnSmall);
  607. //
  608. // Initialize consumer windows changes
  609. //
  610. _Shell_Initialize(pGlobals);
  611. //
  612. // Initialize this global that's used in status.c. We know that WlxInitialize is called
  613. // on the main thread of winlogon.
  614. //
  615. g_dwMainThreadId = GetCurrentThreadId();
  616. return(TRUE);
  617. }
  618. VOID
  619. WINAPI
  620. WlxDisplaySASNotice(PVOID pContext)
  621. {
  622. PGLOBALS pGlobals = (PGLOBALS)pContext;
  623. INITCOMMONCONTROLSEX icce;
  624. icce.dwSize = sizeof (icce);
  625. icce.dwICC = ICC_ANIMATE_CLASS;
  626. InitCommonControlsEx(&icce);
  627. // Need to register the link window
  628. LinkWindow_RegisterClass();
  629. pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  630. hDllInstance,
  631. (LPTSTR) IDD_WELCOME_DIALOG,
  632. NULL,
  633. WelcomeDlgProc,
  634. (LPARAM) pContext );
  635. }
  636. PWSTR
  637. AllocAndExpandProfilePath(
  638. PGLOBALS pGlobals,
  639. LPWSTR lpUserName)
  640. {
  641. WCHAR szPath[MAX_PATH];
  642. WCHAR szFullPath[MAX_PATH];
  643. WCHAR szServerName[UNCLEN+1];
  644. WCHAR szUserName[100];
  645. DWORD cFullPath;
  646. PWSTR pszFullPath;
  647. DWORD dwPathLen=0;
  648. //
  649. // Set up the logon server environment variable:
  650. //
  651. dwPathLen = pGlobals->Profile->LogonServer.Length;
  652. // Truncation would be bad but should never happen (all machine names less
  653. // UNCLEN chars). But LogonServer.Buffer might not be NULL terminated.
  654. ASSERT(sizeof(szServerName) >= 2*sizeof(WCHAR) + dwPathLen + sizeof(WCHAR));
  655. if (sizeof(szServerName) < 2*sizeof(WCHAR) + dwPathLen + sizeof(WCHAR)) // all lengths in bytes
  656. {
  657. dwPathLen = sizeof(szServerName) - 3*sizeof(WCHAR); // Won't overflow now
  658. }
  659. szServerName[0] = L'\\';
  660. szServerName[1] = L'\\';
  661. CopyMemory( &szServerName[2],
  662. pGlobals->Profile->LogonServer.Buffer,
  663. dwPathLen );
  664. szServerName[dwPathLen / sizeof(WCHAR) + 2] = L'\0';
  665. SetEnvironmentVariable(LOGONSERVER_VARIABLE, szServerName);
  666. dwPathLen = lstrlen(pGlobals->MuGlobals.TSData.ProfilePath);
  667. if (!g_Console && (dwPathLen > 0)) {
  668. //
  669. // See if the user specified a Terminal Server profile path.
  670. // If so, we override the regular profile path
  671. //
  672. if (dwPathLen < MAX_PATH)
  673. {
  674. lstrcpy(szPath, pGlobals->MuGlobals.TSData.ProfilePath);
  675. }
  676. else
  677. {
  678. lstrcpy(szPath, NULL_STRING);
  679. }
  680. } else {
  681. dwPathLen = pGlobals->Profile->ProfilePath.Length;
  682. if (dwPathLen == 0)
  683. {
  684. return(NULL);
  685. }
  686. //
  687. // Copy the profile path locally
  688. //
  689. if (dwPathLen <= (MAX_PATH-1)*sizeof(WCHAR))
  690. {
  691. CopyMemory( szPath,
  692. pGlobals->Profile->ProfilePath.Buffer,
  693. dwPathLen);
  694. szPath[dwPathLen / sizeof(WCHAR)] = L'\0';
  695. }
  696. else
  697. {
  698. lstrcpy(szPath, NULL_STRING);
  699. }
  700. }
  701. if (lpUserName && *lpUserName) {
  702. szUserName[0] = TEXT('\0');
  703. GetEnvironmentVariableW (USERNAME_VARIABLE, szUserName, 100);
  704. SetEnvironmentVariableW (USERNAME_VARIABLE, lpUserName);
  705. }
  706. //
  707. // Expand the profile path using current settings:
  708. //
  709. cFullPath = ExpandEnvironmentStrings(szPath, szFullPath, MAX_PATH);
  710. if ((cFullPath) && (cFullPath <= MAX_PATH))
  711. {
  712. pszFullPath = LocalAlloc(LMEM_FIXED, cFullPath * sizeof(WCHAR));
  713. if (pszFullPath)
  714. {
  715. CopyMemory( pszFullPath, szFullPath, cFullPath * sizeof(WCHAR));
  716. }
  717. }
  718. else
  719. {
  720. pszFullPath = NULL;
  721. }
  722. if (lpUserName && *lpUserName) {
  723. if (szUserName[0] != TEXT('\0'))
  724. SetEnvironmentVariableW (USERNAME_VARIABLE, szUserName);
  725. else
  726. SetEnvironmentVariableW (USERNAME_VARIABLE, NULL);
  727. }
  728. return(pszFullPath);
  729. }
  730. PWSTR
  731. AllocPolicyPath(
  732. PGLOBALS pGlobals)
  733. {
  734. LPWSTR pszPath = NULL;
  735. if (2 * sizeof(WCHAR) + pGlobals->Profile->LogonServer.Length + sizeof(L"\\netlogon\\ntconfig.pol") <= MAX_PATH * sizeof(WCHAR))
  736. {
  737. pszPath = LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
  738. if ( pszPath )
  739. {
  740. pszPath[0] = L'\\';
  741. pszPath[1] = L'\\';
  742. CopyMemory( &pszPath[2],
  743. pGlobals->Profile->LogonServer.Buffer,
  744. pGlobals->Profile->LogonServer.Length );
  745. wcscpy( &pszPath[ pGlobals->Profile->LogonServer.Length / sizeof(WCHAR) + 2],
  746. L"\\netlogon\\ntconfig.pol" );
  747. }
  748. }
  749. return(pszPath);
  750. }
  751. PWSTR
  752. AllocNetDefUserProfilePath(
  753. PGLOBALS pGlobals)
  754. {
  755. LPWSTR pszPath = NULL;
  756. if (2 * sizeof(WCHAR) + pGlobals->Profile->LogonServer.Length + sizeof(L"\\netlogon\\Default User") <= MAX_PATH * sizeof(WCHAR))
  757. {
  758. pszPath = LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
  759. if ( pszPath )
  760. {
  761. //
  762. // Set up the logon server environment variable:
  763. //
  764. pszPath[0] = L'\\';
  765. pszPath[1] = L'\\';
  766. CopyMemory( &pszPath[2],
  767. pGlobals->Profile->LogonServer.Buffer,
  768. pGlobals->Profile->LogonServer.Length );
  769. wcscpy( &pszPath[ pGlobals->Profile->LogonServer.Length / sizeof(WCHAR) + 2],
  770. L"\\netlogon\\Default User" );
  771. }
  772. }
  773. return(pszPath);
  774. }
  775. PWSTR
  776. AllocServerName(
  777. PGLOBALS pGlobals)
  778. {
  779. LPWSTR pszPath = NULL;
  780. if (2 * sizeof(WCHAR) + pGlobals->Profile->LogonServer.Length + 1 <= MAX_PATH * sizeof(WCHAR))
  781. {
  782. pszPath = LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
  783. if ( pszPath )
  784. {
  785. //
  786. // Set up the logon server environment variable:
  787. //
  788. pszPath[0] = L'\\';
  789. pszPath[1] = L'\\';
  790. CopyMemory( &pszPath[2],
  791. pGlobals->Profile->LogonServer.Buffer,
  792. pGlobals->Profile->LogonServer.Length );
  793. pszPath[pGlobals->Profile->LogonServer.Length / sizeof(WCHAR) + 2] = L'\0';
  794. }
  795. }
  796. return(pszPath);
  797. }
  798. VOID
  799. DetermineDnsDomain(
  800. PGLOBALS pGlobals
  801. )
  802. {
  803. DWORD dwError = ERROR_SUCCESS;
  804. LPTSTR lpUserName = NULL, lpTemp;
  805. ULONG ulUserNameSize;
  806. pGlobals->DnsDomain = NULL;
  807. if ( ImpersonateLoggedOnUser( pGlobals->UserProcessData.UserToken ) )
  808. {
  809. ulUserNameSize = 75; // Pick a default size. We'll expand if necessary
  810. lpUserName = LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
  811. if (!lpUserName)
  812. {
  813. dwError = GetLastError();
  814. if( dwError == ERROR_SUCCESS )
  815. {
  816. ASSERT(FALSE && "LocalAlloc failed w/out setting last error");
  817. dwError = ERROR_NOT_ENOUGH_MEMORY;
  818. }
  819. }
  820. else
  821. {
  822. DWORD dwCount = 0;
  823. while (TRUE)
  824. {
  825. if (GetUserNameEx (NameDnsDomain, lpUserName, &ulUserNameSize))
  826. {
  827. dwError = ERROR_SUCCESS;
  828. break;
  829. }
  830. else
  831. {
  832. dwError = GetLastError();
  833. //
  834. // If the call failed due to insufficient memory, realloc
  835. // the buffer and try again.
  836. //
  837. if ((dwError == ERROR_INSUFFICIENT_BUFFER) || (dwError == ERROR_MORE_DATA))
  838. {
  839. LocalFree(lpUserName);
  840. lpUserName = LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
  841. if (!lpUserName) {
  842. dwError = GetLastError();
  843. if( dwError == ERROR_SUCCESS )
  844. {
  845. ASSERT(FALSE && "LocalAlloc failed w/out setting last error");
  846. dwError = ERROR_NOT_ENOUGH_MEMORY;
  847. }
  848. break; // Can't recover
  849. }
  850. }
  851. else if (dwError == ERROR_NO_SUCH_DOMAIN)
  852. {
  853. // We just logged on so we know that the domain exists
  854. // This is what happens with NT4 domain though since we try
  855. // to query the DNS domain name and it doesn't exists
  856. // Let's fall back to our old logic
  857. break;
  858. }
  859. else if (dwError == ERROR_NONE_MAPPED)
  860. {
  861. // That's what's returned for local users.
  862. break;
  863. }
  864. else
  865. {
  866. dwCount++;
  867. if (dwCount > 3)
  868. {
  869. break;
  870. }
  871. }
  872. }
  873. }
  874. }
  875. RevertToSelf();
  876. }
  877. else
  878. {
  879. dwError = GetLastError();
  880. }
  881. if (dwError == ERROR_SUCCESS)
  882. {
  883. //
  884. // At this point lpUserName contains something like domain.company.com\someuser
  885. // We are only interested in the dns domain name
  886. lpTemp = lpUserName;
  887. while (*lpTemp && ((*lpTemp) != TEXT('\\')))
  888. lpTemp++;
  889. if (*lpTemp != TEXT('\\'))
  890. {
  891. DebugLog((DEB_ERROR, "DetermineDnsDomain: Failed to find slash in DNS style name\n"));
  892. dwError = ERROR_INVALID_DATA;
  893. }
  894. else
  895. {
  896. *lpTemp = TEXT('\0');
  897. pGlobals->DnsDomain = DupString(lpUserName);
  898. }
  899. }
  900. if (dwError != ERROR_SUCCESS)
  901. {
  902. //
  903. // If GetUserNameEx didn't yield a DNS name, fall back on the old code.
  904. //
  905. PDOMAIN_CACHE_ENTRY Entry ;
  906. Entry = DCacheLocateEntry(
  907. pGlobals->Cache,
  908. pGlobals->FlatDomain.Buffer );
  909. if ( Entry )
  910. {
  911. if ( Entry->Type == DomainNt5 )
  912. {
  913. pGlobals->DnsDomain = DupString( Entry->DnsName.Buffer );
  914. }
  915. else
  916. {
  917. //
  918. // For all intended purposes, this is good enough.
  919. // winlogon needs to know for sure for policy (419926)
  920. //
  921. pGlobals->DnsDomain = DupString( L"\\NT4" );
  922. }
  923. DCacheDereferenceEntry( Entry );
  924. }
  925. else
  926. {
  927. //
  928. // winlogon needs to know this as well. errors and not-found
  929. // were assumed NT5
  930. //
  931. pGlobals->DnsDomain = DupString( L"\\XFOREST" );
  932. }
  933. }
  934. if (lpUserName)
  935. {
  936. LocalFree(lpUserName);
  937. }
  938. //
  939. // Don't leave with pGlobals->DnsDomain set to NULL
  940. //
  941. if ( pGlobals->DnsDomain == NULL)
  942. {
  943. pGlobals->DnsDomain = DupString( L"" );
  944. }
  945. }
  946. PWSTR
  947. AllocVolatileEnvironment(
  948. PGLOBALS pGlobals)
  949. {
  950. BOOL DeepShare;
  951. LPWSTR pszEnv;
  952. DWORD dwSize;
  953. TCHAR lpHomeShare[MAX_PATH] = TEXT("");
  954. TCHAR lpHomePath[MAX_PATH] = TEXT("");
  955. TCHAR lpHomeDrive[4] = TEXT("");
  956. TCHAR lpHomeDirectory[MAX_PATH] = TEXT("");
  957. BOOL TSHomeDir = FALSE;
  958. PVOID lpEnvironment = NULL; // Dummy environment
  959. BOOL bUserHasHomedir = TRUE;
  960. //
  961. // Set the home directory environment variables
  962. // in a dummy environment block
  963. //
  964. if ( !g_Console ) {
  965. // See if the user specified a TerminalServer Home Directory.
  966. // If so, we override the regular directory
  967. if (lstrlen(pGlobals->MuGlobals.TSData.HomeDir) > 0) {
  968. ASSERT(sizeof(lpHomeDirectory) >= sizeof(pGlobals->MuGlobals.TSData.HomeDir));
  969. lstrcpy(lpHomeDirectory, pGlobals->MuGlobals.TSData.HomeDir);
  970. TSHomeDir = TRUE;
  971. }
  972. if (lstrlen(pGlobals->MuGlobals.TSData.HomeDirDrive) > 0) {
  973. ASSERT(sizeof(lpHomeDrive) >= sizeof(pGlobals->MuGlobals.TSData.HomeDirDrive));
  974. lstrcpy(lpHomeDrive, pGlobals->MuGlobals.TSData.HomeDirDrive);
  975. TSHomeDir = TRUE;
  976. }
  977. }
  978. if (!TSHomeDir) {
  979. if (pGlobals->Profile->HomeDirectoryDrive.Length &&
  980. (pGlobals->Profile->HomeDirectoryDrive.Length + sizeof(TCHAR)) <= sizeof(lpHomeDrive)) {
  981. memcpy(lpHomeDrive, pGlobals->Profile->HomeDirectoryDrive.Buffer,
  982. pGlobals->Profile->HomeDirectoryDrive.Length);
  983. lpHomeDrive[pGlobals->Profile->HomeDirectoryDrive.Length / sizeof(TCHAR)] = 0;
  984. }
  985. if (pGlobals->Profile->HomeDirectory.Length &&
  986. (pGlobals->Profile->HomeDirectory.Length + sizeof(TCHAR)) <= (MAX_PATH*sizeof(TCHAR))) {
  987. memcpy(lpHomeDirectory, pGlobals->Profile->HomeDirectory.Buffer,
  988. pGlobals->Profile->HomeDirectory.Length);
  989. lpHomeDirectory[pGlobals->Profile->HomeDirectory.Length / sizeof(TCHAR)] = 0;
  990. }
  991. }
  992. //
  993. // Note : we are passing in a null environment because here we are only
  994. // interested in parsing the homedirectory and set it in the volatile
  995. // environment. We are not interested in setting it in the
  996. // environment block here.
  997. //
  998. // Also over here, we are only interested in setting up the
  999. // HOMESHARE and HOMEPATH variables in such a way that
  1000. // %HOMESHARE%%HOMEPATH% points to the homedir. This is done
  1001. // so that when folder redirection calls SHGetFolderPath, it will be
  1002. // able to expand the paths properly. Therefore, at this point
  1003. // it is not really necessary to pay attention to the
  1004. // ConnectHomeDirToRoot policy because that policy might get changed
  1005. // during policy processing anyway and will be picked up when the
  1006. // shell starts up. Note: the values of HOMESHARE, HOMEPATH and
  1007. // HOMEDRIVE will be updated correctly when the shell starts up
  1008. //
  1009. // At this point we do not map the home directory for 2 reasons:
  1010. // (a) We are not aware of the ConnectHomeDirToRoot setting here.
  1011. // (b) We do not want to do the network mapping twice : once here
  1012. // and once when the shell starts up.
  1013. //
  1014. // Also, we do not want to set the home directory variables in the
  1015. // volatile environment if it is not specified in the user object.
  1016. // This prevents us from stomping over logon scripts that might
  1017. // be setting the homedirectory variables themselves rather than
  1018. // relying on the values set on the user object.
  1019. //
  1020. if (!lpHomeDirectory[0])
  1021. bUserHasHomedir = FALSE;
  1022. if (bUserHasHomedir)
  1023. SetHomeDirectoryEnvVars(&lpEnvironment,
  1024. lpHomeDirectory,
  1025. lpHomeDrive,
  1026. lpHomeShare,
  1027. lpHomePath,
  1028. &DeepShare);
  1029. if ( pGlobals->DnsDomain == NULL )
  1030. {
  1031. DetermineDnsDomain( pGlobals );
  1032. }
  1033. dwSize = lstrlen (LOGONSERVER_VARIABLE) + 3
  1034. + lstrlen (pGlobals->Profile->LogonServer.Buffer) + 3;
  1035. if (bUserHasHomedir)
  1036. {
  1037. if (L'\0' == lpHomeShare[0])
  1038. {
  1039. // Set the homedrive variable only if the home directory is not
  1040. // a UNC path
  1041. dwSize += lstrlen (HOMEDRIVE_VARIABLE) + 1 + lstrlen (lpHomeDrive) + 3;
  1042. }
  1043. else
  1044. {
  1045. // Set the homeshare variable only if the home directory is a UNC path
  1046. dwSize += lstrlen (HOMESHARE_VARIABLE) + 1 + lstrlen (lpHomeShare) + 3;
  1047. }
  1048. dwSize += lstrlen (HOMEPATH_VARIABLE) + 1 + lstrlen (lpHomePath) + 3;
  1049. }
  1050. if ( pGlobals->DnsDomain )
  1051. {
  1052. dwSize += (lstrlen( USERDNSDOMAIN_VARIABLE ) + 3 +
  1053. lstrlen( pGlobals->DnsDomain ) + 3 );
  1054. }
  1055. if (g_IsTerminalServer) {
  1056. dwSize += lstrlen (CLIENTNAME_VARIABLE) + 1 + lstrlen (pGlobals->MuGlobals.ClientName) + 3;
  1057. }
  1058. pszEnv = LocalAlloc(LPTR, dwSize * sizeof(WCHAR));
  1059. if ( pszEnv )
  1060. {
  1061. LPWSTR pszEnvTmp;
  1062. lstrcpy (pszEnv, LOGONSERVER_VARIABLE);
  1063. lstrcat (pszEnv, L"=\\\\");
  1064. lstrcat (pszEnv, pGlobals->Profile->LogonServer.Buffer);
  1065. pszEnvTmp = pszEnv + (lstrlen( pszEnv ) + 1);
  1066. if (bUserHasHomedir)
  1067. {
  1068. if (L'\0' == lpHomeShare[0])
  1069. {
  1070. // Set the homedrive variable only if it is not a UNC path
  1071. lstrcpy (pszEnvTmp, HOMEDRIVE_VARIABLE);
  1072. lstrcat (pszEnvTmp, L"=");
  1073. lstrcat (pszEnvTmp, lpHomeDrive);
  1074. pszEnvTmp += (lstrlen(pszEnvTmp) + 1);
  1075. }
  1076. else
  1077. {
  1078. // Set the homeshare variable only if it is a UNC path
  1079. lstrcpy (pszEnvTmp, HOMESHARE_VARIABLE);
  1080. lstrcat (pszEnvTmp, L"=");
  1081. lstrcat (pszEnvTmp, lpHomeShare);
  1082. pszEnvTmp += (lstrlen(pszEnvTmp) + 1);
  1083. }
  1084. // Set the homepath variable
  1085. lstrcpy (pszEnvTmp, HOMEPATH_VARIABLE);
  1086. lstrcat (pszEnvTmp, L"=");
  1087. lstrcat (pszEnvTmp, lpHomePath);
  1088. pszEnvTmp += (lstrlen(pszEnvTmp) + 1);
  1089. }
  1090. // This check doesn't match the check above
  1091. // It is safe though.
  1092. if (( pGlobals->DnsDomain ) && (*(pGlobals->DnsDomain)))
  1093. {
  1094. lstrcpy( pszEnvTmp, USERDNSDOMAIN_VARIABLE );
  1095. lstrcat( pszEnvTmp, L"=" );
  1096. lstrcat( pszEnvTmp, pGlobals->DnsDomain );
  1097. pszEnvTmp += (lstrlen( pszEnvTmp ) + 1 );
  1098. }
  1099. if (g_IsTerminalServer) {
  1100. lstrcpy (pszEnvTmp, CLIENTNAME_VARIABLE);
  1101. lstrcat (pszEnvTmp, L"=");
  1102. lstrcat (pszEnvTmp, pGlobals->MuGlobals.ClientName);
  1103. pszEnvTmp += (lstrlen( pszEnvTmp ) + 1 );
  1104. }
  1105. *pszEnvTmp++ = L'\0';
  1106. }
  1107. return(pszEnv);
  1108. }
  1109. BOOL
  1110. ForceAutoLogon(
  1111. VOID
  1112. )
  1113. {
  1114. HKEY hkey;
  1115. BOOL fForceKeySet = FALSE;
  1116. BOOL fHaveAutoLogonCount = FALSE;
  1117. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ, &hkey))
  1118. {
  1119. DWORD dwValue;
  1120. DWORD dwType;
  1121. DWORD dwSize = sizeof (dwValue);
  1122. if (ERROR_SUCCESS == RegQueryValueEx(hkey,
  1123. AUTOLOGONCOUNT_KEY,
  1124. NULL,
  1125. &dwType,
  1126. (LPBYTE) &dwValue,
  1127. &dwSize ))
  1128. {
  1129. fHaveAutoLogonCount = TRUE;
  1130. }
  1131. dwSize = sizeof (dwValue);
  1132. if (ERROR_SUCCESS == RegQueryValueEx(hkey,
  1133. FORCEAUTOLOGON_KEY,
  1134. NULL,
  1135. &dwType,
  1136. (LPBYTE) &dwValue,
  1137. &dwSize ))
  1138. {
  1139. //
  1140. // Check the value as a REG_SZ since all the other autologon values
  1141. // are stored as REG_SZs. Check it as a REG_DWORD for back-compat.
  1142. //
  1143. if (dwType == REG_DWORD)
  1144. {
  1145. if (0 != dwValue)
  1146. {
  1147. fForceKeySet = TRUE;
  1148. }
  1149. }
  1150. else if (dwType == REG_SZ)
  1151. {
  1152. //
  1153. // Reread the value for consistency with the way other
  1154. // autologon values are read/checked.
  1155. //
  1156. if (GetProfileInt(APPLICATION_NAME, FORCEAUTOLOGON_KEY, 0) != 0)
  1157. {
  1158. fForceKeySet = TRUE;
  1159. }
  1160. }
  1161. }
  1162. RegCloseKey(hkey);
  1163. }
  1164. return (fHaveAutoLogonCount || fForceKeySet);
  1165. }
  1166. /****************************************************************************\
  1167. *
  1168. * FUNCTION: CreateFolderAndACLit_Worker
  1169. *
  1170. * PURPOSE: Create a home-dir folder for the user, and set the proper security
  1171. * such that only the user and the admin have access to the folder.
  1172. *
  1173. * PARAMS: [in ] szPath the full path, could be UNC or local
  1174. * [in ] pUserSID user SID
  1175. * [out] pdwErr error code if anything fails.
  1176. *
  1177. * RETURNS: TRUE if all went ok
  1178. * FALSE if a bad home dir path was specified.
  1179. *
  1180. * HISTORY:
  1181. * TsUserEX ( Alhen's code which was based on EricB's DSPROP_CreateHomeDirectory )
  1182. *
  1183. *
  1184. \****************************************************************************/
  1185. #define ACE_COUNT 2
  1186. BOOLEAN CreateFolderAndACLit_Worker ( PWCHAR szPath , PSID pUserSID, PDWORD pdwErr , BOOLEAN pathIsLocal )
  1187. {
  1188. SECURITY_ATTRIBUTES securityAttributes;
  1189. BOOLEAN rc;
  1190. PSID psidAdmins = NULL;
  1191. *pdwErr = 0;
  1192. ZeroMemory( &securityAttributes , sizeof( SECURITY_ATTRIBUTES ) );
  1193. //
  1194. // Apply ACL on the TS Home Dir irrespective of whether its a local or UNC Path
  1195. // Add the ACE for the owner and administrators only
  1196. //
  1197. {
  1198. // build a DACL
  1199. PSID pAceSid[ACE_COUNT];
  1200. PACL pDacl;
  1201. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
  1202. SECURITY_DESCRIPTOR securityDescriptor;
  1203. PSECURITY_DESCRIPTOR pSecurityDescriptor = &securityDescriptor;
  1204. int i;
  1205. EXPLICIT_ACCESS rgAccessEntry[ACE_COUNT] = {0};
  1206. OBJECTS_AND_SID rgObjectsAndSid[ACE_COUNT] = {0};
  1207. if (!AllocateAndInitializeSid(&NtAuth,
  1208. 2,
  1209. SECURITY_BUILTIN_DOMAIN_RID,
  1210. DOMAIN_ALIAS_RID_ADMINS,
  1211. 0, 0, 0, 0, 0, 0,
  1212. &psidAdmins ) )
  1213. {
  1214. DebugLog(( DEB_ERROR, "AllocateAndInitializeSid failed\n" ));
  1215. *pdwErr = GetLastError( );
  1216. rc=FALSE;
  1217. goto done;
  1218. }
  1219. pAceSid[0] = pUserSID;
  1220. pAceSid[1] = psidAdmins;
  1221. for ( i = 0 ; i < ACE_COUNT; i++)
  1222. {
  1223. rgAccessEntry[i].grfAccessPermissions = GENERIC_ALL;
  1224. rgAccessEntry[i].grfAccessMode = GRANT_ACCESS;
  1225. rgAccessEntry[i].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1226. // build the trustee structs
  1227. //
  1228. BuildTrusteeWithObjectsAndSid(&(rgAccessEntry[i].Trustee),
  1229. &(rgObjectsAndSid[i]),
  1230. NULL,
  1231. NULL,
  1232. pAceSid[i]);
  1233. }
  1234. // add the entries to the ACL
  1235. //
  1236. *pdwErr = SetEntriesInAcl( ACE_COUNT, rgAccessEntry, NULL, &pDacl );
  1237. if( *pdwErr != 0 )
  1238. {
  1239. DebugLog(( DEB_ERROR, "SetEntriesInAcl() failed\n" ));
  1240. rc = FALSE;
  1241. goto done;
  1242. }
  1243. // build a security descriptor and initialize it
  1244. // in absolute format
  1245. if( !InitializeSecurityDescriptor( pSecurityDescriptor , SECURITY_DESCRIPTOR_REVISION ) )
  1246. {
  1247. DebugLog(( DEB_ERROR, "InitializeSecurityDescriptor() failed\n" ) );
  1248. *pdwErr = GetLastError( );
  1249. rc=FALSE;
  1250. goto done;
  1251. }
  1252. // add DACL to security descriptor (must be in absolute format)
  1253. if( !SetSecurityDescriptorDacl( pSecurityDescriptor,
  1254. TRUE, // bDaclPresent
  1255. pDacl,
  1256. FALSE // bDaclDefaulted
  1257. ) )
  1258. {
  1259. DebugLog(( DEB_ERROR, "SetSecurityDescriptorDacl() failed\n" ));
  1260. *pdwErr = GetLastError( );
  1261. rc=FALSE;
  1262. goto done;
  1263. }
  1264. // set the owner of the directory
  1265. if( !SetSecurityDescriptorOwner( pSecurityDescriptor ,
  1266. pUserSID ,
  1267. FALSE // bOwnerDefaulted
  1268. ) )
  1269. {
  1270. DebugLog(( DEB_ERROR, "SetSecurityDescriptorOwner() failed\n" ));
  1271. *pdwErr = GetLastError( );
  1272. rc= FALSE;
  1273. goto done;
  1274. }
  1275. if ( ! IsValidSecurityDescriptor( pSecurityDescriptor ) )
  1276. {
  1277. DebugLog(( DEB_ERROR , "BAD security desc\n") );
  1278. }
  1279. // build a SECURITY_ATTRIBUTES struct as argument for
  1280. // CreateDirectory()
  1281. securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  1282. securityAttributes.lpSecurityDescriptor = pSecurityDescriptor;
  1283. securityAttributes.bInheritHandle = FALSE;
  1284. if( !CreateDirectory( szPath , &securityAttributes ) )
  1285. {
  1286. *pdwErr = GetLastError( );
  1287. rc = FALSE;
  1288. goto done;
  1289. }
  1290. else
  1291. {
  1292. rc = TRUE;
  1293. }
  1294. }
  1295. done:
  1296. if( psidAdmins != NULL )
  1297. {
  1298. FreeSid( psidAdmins );
  1299. }
  1300. return rc;
  1301. }
  1302. /****************************************************************************\
  1303. *
  1304. * FUNCTION: TermServ_CreateHomePathAndACLit
  1305. *
  1306. * PURPOSE: create the TS specific user home folder and ACL it such that only
  1307. * user and Admins have access to it.
  1308. *
  1309. * PARAMS: PGLOABLS, from which TSData and userSid are used
  1310. *
  1311. * RETURNS: TRUE if all went ok
  1312. * FALSE if a bad home dir path was specified.
  1313. *
  1314. * HISTORY:
  1315. *
  1316. *
  1317. \****************************************************************************/
  1318. BOOLEAN TermServ_CreateHomePathAndACLit( PGLOBALS pG )
  1319. {
  1320. BOOLEAN rc;
  1321. DWORD dwErr = NO_ERROR;
  1322. BOOLEAN pathIsLocal;
  1323. DWORD dwFileAttribs;
  1324. WLX_TERMINAL_SERVICES_DATA *pTSData;
  1325. pTSData = & pG->MuGlobals.TSData;
  1326. DebugLog((DEB_ERROR, "pTSData->HomeDir = %ws \n", pTSData->HomeDir ));
  1327. if (pTSData->HomeDir[0] == L'\0')
  1328. {
  1329. // no TS specific path, we are done.
  1330. return TRUE;
  1331. }
  1332. // check for empty strings, which means no TS specific path.
  1333. // decide if this is a UNC path to home dir or a local path
  1334. if( pTSData->HomeDir[1] == TEXT( ':' ) && pTSData->HomeDir[2] == TEXT( '\\' ) )
  1335. {
  1336. pathIsLocal = TRUE; // we have a string starting with something like "D:\"
  1337. }
  1338. else if ( pTSData->HomeDir[0] == TEXT( '\\' ) && pTSData->HomeDir[1] == TEXT( '\\' ) )
  1339. {
  1340. pathIsLocal = FALSE; // we have a string like "\\", which means a UNC path
  1341. }
  1342. else
  1343. {
  1344. // we seem to have a bad path, set it to empty so that
  1345. // the default paths will be used by userenv's code for settin up
  1346. // stuff
  1347. pTSData->HomeDirDrive[0] = pTSData->HomeDir[0] = TEXT('\0');
  1348. DebugLog((DEB_ERROR, "Bad path for Terminal Services home folder" ));
  1349. return FALSE;
  1350. }
  1351. dwFileAttribs = GetFileAttributes( pTSData->HomeDir );
  1352. if (dwFileAttribs == - 1)
  1353. {
  1354. dwErr = GetLastError();
  1355. if (dwErr == ERROR_FILE_NOT_FOUND)
  1356. {
  1357. // We need to create the home DIR here, userenv does not create home folders.
  1358. rc = CreateFolderAndACLit_Worker( pTSData->HomeDir , pG->UserProcessData.UserSid , &dwErr , pathIsLocal );
  1359. }
  1360. else
  1361. {
  1362. rc = FALSE;
  1363. }
  1364. }
  1365. else if ( dwFileAttribs & FILE_ATTRIBUTE_DIRECTORY )
  1366. {
  1367. DebugLog((DEB_WARN , ("Homedir folder already exists\n")));
  1368. rc = TRUE;
  1369. }
  1370. else
  1371. {
  1372. // there is a file there, so we can't create a dir...
  1373. DebugLog((DEB_ERROR , "File with the same name already exists: %s\n", pTSData->HomeDir ));
  1374. rc = FALSE;
  1375. }
  1376. if (!rc)
  1377. {
  1378. DebugLog((DEB_ERROR, "TerminalServerCreatedirWorker() returned error = %d\n",dwErr ));
  1379. // we seem to have a bad path, set it to empty so that
  1380. // the default paths will be used by userenv's code for settin up
  1381. // stuff
  1382. pTSData->HomeDirDrive[0] = pTSData->HomeDir[0] = TEXT('\0');
  1383. }
  1384. return rc;
  1385. }
  1386. int
  1387. WINAPI
  1388. WlxLoggedOutSAS(
  1389. PVOID pWlxContext,
  1390. DWORD dwSasType,
  1391. PLUID pAuthenticationId,
  1392. PSID pLogonSid,
  1393. PDWORD pdwOptions,
  1394. PHANDLE phToken,
  1395. PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
  1396. PVOID * pProfile
  1397. )
  1398. {
  1399. PGLOBALS pGlobals;
  1400. INT_PTR result = 0;
  1401. PWLX_PROFILE_V2_0 pWlxProfile;
  1402. PUNICODE_STRING FlatUser ;
  1403. PUNICODE_STRING FlatDomain ;
  1404. NTSTATUS Status ;
  1405. DWORD dwNewSasType;
  1406. pGlobals = (PGLOBALS) pWlxContext;
  1407. pGlobals->LogonSid = pLogonSid;
  1408. if (ForceAutoLogon())
  1409. {
  1410. pGlobals->IgnoreAutoAdminLogon = FALSE;
  1411. }
  1412. else
  1413. {
  1414. pGlobals->IgnoreAutoAdminLogon = (*pdwOptions) & WLX_OPTION_IGNORE_AUTO_LOGON;
  1415. }
  1416. // Clear out user process information
  1417. ZeroMemory(&pGlobals->UserProcessData, sizeof(pGlobals->UserProcessData));
  1418. if (dwSasType == WLX_SAS_TYPE_AUTHENTICATED) {
  1419. pGlobals->IgnoreAutoAdminLogon = TRUE;
  1420. result = TSAuthenticatedLogon(pGlobals);
  1421. } else {
  1422. ULONG_PTR ulOption;
  1423. do {
  1424. if (result == MSGINA_DLG_SMARTCARD_INSERTED) {
  1425. dwNewSasType = WLX_SAS_TYPE_SC_INSERT;
  1426. } else {
  1427. dwNewSasType = dwSasType;
  1428. }
  1429. // Make sure we monitor SC events
  1430. ulOption = 1;
  1431. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  1432. WLX_OPTION_USE_SMART_CARD,
  1433. ulOption,
  1434. NULL );
  1435. result = Logon(pGlobals, dwNewSasType );
  1436. if ( result == MSGINA_DLG_SUCCESS )
  1437. {
  1438. if ( (pGlobals->SmartCardOption == 0) || (!pGlobals->SmartCardLogon) )
  1439. {
  1440. // As no action will be taken on SC removal, we can filter these events
  1441. ulOption = 0;
  1442. }
  1443. else
  1444. {
  1445. //
  1446. // Continue to monitor the s/c device
  1447. //
  1448. NOTHING ;
  1449. }
  1450. }
  1451. else
  1452. {
  1453. if (result != MSGINA_DLG_SMARTCARD_INSERTED)
  1454. {
  1455. // This will force winlogon to forget the last sc event
  1456. ulOption = 0;
  1457. }
  1458. }
  1459. if (ulOption == 0)
  1460. {
  1461. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  1462. WLX_OPTION_USE_SMART_CARD,
  1463. 0,
  1464. NULL );
  1465. }
  1466. } while (result == MSGINA_DLG_SMARTCARD_INSERTED || result == MSGINA_DLG_SMARTCARD_REMOVED);
  1467. }
  1468. if (result == MSGINA_DLG_SUCCESS)
  1469. {
  1470. DebugLog((DEB_TRACE, "Successful Logon of %ws\\%ws\n", pGlobals->Domain, pGlobals->UserName));
  1471. *phToken = pGlobals->UserProcessData.UserToken;
  1472. *pAuthenticationId = pGlobals->LogonId;
  1473. *pdwOptions = 0;
  1474. //
  1475. // Set up the flat/UPN stuff:
  1476. //
  1477. pGlobals->FlatUserName = pGlobals->UserNameString ;
  1478. pGlobals->FlatDomain = pGlobals->DomainString ;
  1479. //
  1480. // Since win2k domains and later support multiple language sets, and map
  1481. // similar names to the same account for accessibility from non-nls
  1482. // systems (e.g., a user account named "User" can be used to log on
  1483. // as both "User" and "U-with-an-umlaut-ser", we need to always do
  1484. // this lookup to get the "real" name
  1485. //
  1486. if ( ImpersonateLoggedOnUser( pGlobals->UserProcessData.UserToken ) )
  1487. {
  1488. Status = LsaGetUserName( &FlatUser, &FlatDomain );
  1489. if ( NT_SUCCESS( Status ) )
  1490. {
  1491. //
  1492. // Initialize the TS Profile path and Home dir globals. Also get
  1493. // all TS specific user-config data which is used in winlogon
  1494. //
  1495. //For WlxQueryTerminalServicesData() we need NT type names rather than
  1496. //UPN names, if we pass a UPN name it will try to resolve it
  1497. //(through ADS API) to NT name anyway. Besides, ADS API cannot
  1498. //resolve some UPN names and takes a long time to execute.
  1499. //So let's pass in an NT user and domain names.
  1500. //
  1501. LPWSTR wszFlatUserName, wszFlatDomainName;
  1502. wszFlatUserName = (LPWSTR)LocalAlloc(LPTR,
  1503. FlatUser->Length+sizeof(WCHAR));
  1504. wszFlatDomainName = (LPWSTR)LocalAlloc(LPTR,
  1505. FlatDomain->Length+sizeof(WCHAR));
  1506. if(wszFlatUserName && wszFlatDomainName)
  1507. {
  1508. // Sizes are OK given allocation.
  1509. // Zero term'ed since LPTR was used.
  1510. memcpy(wszFlatUserName, FlatUser->Buffer,
  1511. FlatUser->Length);
  1512. memcpy(wszFlatDomainName, FlatDomain->Buffer,
  1513. FlatDomain->Length);
  1514. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1515. &pGlobals->MuGlobals.TSData, wszFlatUserName, wszFlatDomainName);
  1516. }
  1517. else
  1518. {
  1519. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1520. &pGlobals->MuGlobals.TSData,pGlobals->UserName , pGlobals->Domain);
  1521. }
  1522. if(wszFlatUserName)
  1523. {
  1524. LocalFree(wszFlatUserName);
  1525. }
  1526. if(wszFlatDomainName)
  1527. {
  1528. LocalFree(wszFlatDomainName);
  1529. }
  1530. //
  1531. // if duplication fails revert back to the original string
  1532. //
  1533. if( !DuplicateUnicodeString(&pGlobals->FlatUserName,
  1534. FlatUser ) )
  1535. {
  1536. pGlobals->FlatUserName = pGlobals->UserNameString ;
  1537. }
  1538. if ( !DuplicateUnicodeString(&pGlobals->FlatDomain,
  1539. FlatDomain ) )
  1540. {
  1541. pGlobals->FlatDomain = pGlobals->DomainString ;
  1542. }
  1543. if ( pGlobals->UserName[0] == L'\0' )
  1544. {
  1545. //
  1546. // Weird case of UPN/SC, no UPN could be found. Use
  1547. // the flat name
  1548. //
  1549. dwNewSasType = FlatUser->Length;
  1550. if (MAX_STRING_BYTES*sizeof(WCHAR) <= dwNewSasType + sizeof(WCHAR))
  1551. {
  1552. dwNewSasType = MAX_STRING_BYTES * sizeof(WCHAR) - sizeof(WCHAR);
  1553. }
  1554. memcpy( pGlobals->UserName, FlatUser->Buffer, dwNewSasType);
  1555. pGlobals->UserName[dwNewSasType / sizeof(WCHAR)] = 0;
  1556. RtlInitUnicodeString( &pGlobals->UserNameString,
  1557. pGlobals->UserName );
  1558. }
  1559. LsaFreeMemory( FlatUser->Buffer );
  1560. LsaFreeMemory( FlatUser );
  1561. LsaFreeMemory( FlatDomain->Buffer );
  1562. LsaFreeMemory( FlatDomain );
  1563. }
  1564. else
  1565. {
  1566. pWlxFuncs->WlxQueryTerminalServicesData(pGlobals->hGlobalWlx,
  1567. &pGlobals->MuGlobals.TSData,pGlobals->UserName , pGlobals->Domain);
  1568. }
  1569. RevertToSelf();
  1570. }
  1571. // TS Specific - Send the credentials used for logging on and smartcard info to TermSrv
  1572. // These credentials are used by TermSrv to send back notification to the client
  1573. // Do this only for remote sessions as this is not relevant for sessions logged on from active console
  1574. if (!IsActiveConsoleSession()) {
  1575. _WinStationUpdateClientCachedCredentials( pGlobals->Domain, pGlobals->UserName, (BOOLEAN) pGlobals->SmartCardLogon );
  1576. }
  1577. DisplayPostShellLogonMessages(pGlobals);
  1578. pMprNotifyInfo->pszUserName = DupString( pGlobals->FlatUserName.Buffer );
  1579. pMprNotifyInfo->pszDomain = DupString(pGlobals->FlatDomain.Buffer );
  1580. RevealPassword( &pGlobals->PasswordString );
  1581. pMprNotifyInfo->pszPassword = DupString(pGlobals->Password);
  1582. HidePassword( &pGlobals->Seed, &pGlobals->PasswordString);
  1583. if (pGlobals->OldPasswordPresent)
  1584. {
  1585. RevealPassword( &pGlobals->OldPasswordString );
  1586. pMprNotifyInfo->pszOldPassword = DupString(pGlobals->OldPassword);
  1587. HidePassword( &pGlobals->OldSeed, &pGlobals->OldPasswordString);
  1588. }
  1589. else
  1590. {
  1591. pMprNotifyInfo->pszOldPassword = NULL;
  1592. }
  1593. PostShellPasswordErase(pGlobals);
  1594. if ( !g_Console )
  1595. {
  1596. if ( ImpersonateLoggedOnUser( pGlobals->UserProcessData.UserToken ) )
  1597. {
  1598. TermServ_CreateHomePathAndACLit( pGlobals );
  1599. RevertToSelf();
  1600. }
  1601. }
  1602. pWlxProfile = (PWLX_PROFILE_V2_0) LocalAlloc(LMEM_FIXED,
  1603. sizeof(WLX_PROFILE_V2_0));
  1604. if (pWlxProfile)
  1605. {
  1606. DWORD dwSize;
  1607. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  1608. BOOL bDomainLogon = TRUE;
  1609. //
  1610. // See if we logged on locally vs domain (vs cached)
  1611. // Optimized logon uses cached logon, but it should be treated
  1612. // as an ordinary domain logon.
  1613. //
  1614. if ((pGlobals->Profile->UserFlags & LOGON_CACHED_ACCOUNT) &&
  1615. (pGlobals->OptimizedLogonStatus != OLS_LogonIsCached)) {
  1616. bDomainLogon = FALSE;
  1617. } else {
  1618. dwSize = MAX_COMPUTERNAME_LENGTH+1;
  1619. if (GetComputerName (szComputerName, &dwSize)) {
  1620. if (!lstrcmpi (pGlobals->Domain, szComputerName)) {
  1621. DebugLog((DEB_TRACE, "WlxLoggedOutSAS: User logged on locally.\n"));
  1622. bDomainLogon = FALSE;
  1623. }
  1624. }
  1625. }
  1626. pWlxProfile->dwType = WLX_PROFILE_TYPE_V2_0;
  1627. pWlxProfile->pszProfile = AllocAndExpandProfilePath(pGlobals, pMprNotifyInfo->pszUserName);
  1628. pWlxProfile->pszPolicy = (bDomainLogon ? AllocPolicyPath(pGlobals) : NULL);
  1629. pWlxProfile->pszNetworkDefaultUserProfile =
  1630. (bDomainLogon ? AllocNetDefUserProfilePath(pGlobals) : NULL);
  1631. pWlxProfile->pszServerName = (bDomainLogon ? AllocServerName(pGlobals) : NULL);
  1632. pWlxProfile->pszEnvironment = AllocVolatileEnvironment(pGlobals);
  1633. }
  1634. *pProfile = (PVOID) pWlxProfile;
  1635. return(WLX_SAS_ACTION_LOGON);
  1636. }
  1637. else if (DLG_SHUTDOWN(result))
  1638. {
  1639. if (result & MSGINA_DLG_REBOOT_FLAG)
  1640. {
  1641. return(WLX_SAS_ACTION_SHUTDOWN_REBOOT);
  1642. }
  1643. else if (result & MSGINA_DLG_POWEROFF_FLAG)
  1644. {
  1645. return(WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
  1646. }
  1647. else if (result & MSGINA_DLG_SLEEP_FLAG)
  1648. {
  1649. return(WLX_SAS_ACTION_SHUTDOWN_SLEEP);
  1650. }
  1651. else if (result & MSGINA_DLG_SLEEP2_FLAG)
  1652. {
  1653. return(WLX_SAS_ACTION_SHUTDOWN_SLEEP2);
  1654. }
  1655. else if (result & MSGINA_DLG_HIBERNATE_FLAG)
  1656. {
  1657. return(WLX_SAS_ACTION_SHUTDOWN_HIBERNATE);
  1658. }
  1659. else
  1660. return(WLX_SAS_ACTION_SHUTDOWN);
  1661. }
  1662. else if ( result == MSGINA_DLG_USER_LOGOFF ) {
  1663. return( WLX_SAS_ACTION_LOGOFF );
  1664. }
  1665. else if (result == MSGINA_DLG_SWITCH_CONSOLE)
  1666. {
  1667. return (WLX_SAS_ACTION_SWITCH_CONSOLE);
  1668. }
  1669. else
  1670. {
  1671. if ( pGlobals->RasUsed )
  1672. {
  1673. //
  1674. // Shut down RAS connections on auth failure.
  1675. //
  1676. HangupRasConnections( pGlobals );
  1677. }
  1678. return(WLX_SAS_ACTION_NONE);
  1679. }
  1680. }
  1681. int
  1682. WINAPI
  1683. WlxLoggedOnSAS(
  1684. PVOID pWlxContext,
  1685. DWORD dwSasType,
  1686. PVOID pReserved
  1687. )
  1688. {
  1689. PGLOBALS pGlobals;
  1690. INT_PTR Result;
  1691. DWORD dwType ;
  1692. DWORD cbData ;
  1693. DWORD dwValue ;
  1694. BOOL OkToLock = TRUE ;
  1695. HKEY hkeyPolicy ;
  1696. pGlobals = (PGLOBALS) pWlxContext;
  1697. if ( pGlobals->SmartCardOption &&
  1698. dwSasType == WLX_SAS_TYPE_SC_REMOVE &&
  1699. pGlobals->SmartCardLogon )
  1700. {
  1701. if ( pGlobals->SmartCardOption == 1 )
  1702. {
  1703. dwValue = 0;
  1704. cbData = sizeof(dwValue);
  1705. RegQueryValueEx(
  1706. WinlogonKey, DISABLE_LOCK_WKSTA,
  1707. 0, &dwType, (LPBYTE)&dwValue, &cbData);
  1708. if (dwValue)
  1709. {
  1710. OkToLock = FALSE ;
  1711. }
  1712. if (OpenHKeyCurrentUser(pGlobals)) {
  1713. if (RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser,
  1714. WINLOGON_POLICY_KEY,
  1715. 0, KEY_READ, &hkeyPolicy) == ERROR_SUCCESS)
  1716. {
  1717. dwValue = 0;
  1718. cbData = sizeof(dwValue);
  1719. if ((ERROR_SUCCESS != RegQueryValueEx(hkeyPolicy, DISABLE_LOCK_WKSTA,
  1720. 0, &dwType, (LPBYTE)&dwValue, &cbData)) ||
  1721. (dwType != REG_DWORD))
  1722. {
  1723. dwValue = 0;
  1724. }
  1725. if (dwValue)
  1726. {
  1727. OkToLock = FALSE ;
  1728. }
  1729. RegCloseKey( hkeyPolicy );
  1730. }
  1731. CloseHKeyCurrentUser(pGlobals);
  1732. }
  1733. if ( OkToLock)
  1734. {
  1735. return WLX_SAS_ACTION_LOCK_WKSTA ;
  1736. }
  1737. }
  1738. else if ( pGlobals->SmartCardOption == 2 )
  1739. {
  1740. if (OpenHKeyCurrentUser(pGlobals)) {
  1741. if (RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser, EXPLORER_POLICY_KEY,
  1742. 0, KEY_READ, &hkeyPolicy) == ERROR_SUCCESS)
  1743. {
  1744. dwValue = 0;
  1745. cbData = sizeof(dwValue);
  1746. if ((ERROR_SUCCESS != RegQueryValueEx(hkeyPolicy, NOLOGOFF,
  1747. 0, &dwType, (LPBYTE)&dwValue, &cbData)) ||
  1748. (dwType != REG_DWORD))
  1749. {
  1750. dwValue = 0;
  1751. }
  1752. if (dwValue)
  1753. {
  1754. OkToLock = FALSE ;
  1755. }
  1756. RegCloseKey( hkeyPolicy );
  1757. }
  1758. CloseHKeyCurrentUser(pGlobals);
  1759. }
  1760. if ( OkToLock)
  1761. {
  1762. return WLX_SAS_ACTION_FORCE_LOGOFF ;
  1763. }
  1764. }
  1765. return WLX_SAS_ACTION_NONE ;
  1766. }
  1767. if ( dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL ) {
  1768. return( WLX_SAS_ACTION_NONE );
  1769. }
  1770. Result = SecurityOptions(pGlobals);
  1771. DebugLog((DEB_TRACE, "Result from SecurityOptions is %d (%#x)\n", Result, Result));
  1772. switch (Result & ~MSGINA_DLG_FLAG_MASK)
  1773. {
  1774. case MSGINA_DLG_SUCCESS:
  1775. case MSGINA_DLG_FAILURE:
  1776. default:
  1777. return(WLX_SAS_ACTION_NONE);
  1778. case MSGINA_DLG_LOCK_WORKSTATION:
  1779. return(WLX_SAS_ACTION_LOCK_WKSTA);
  1780. case MSGINA_DLG_TASKLIST:
  1781. return(WLX_SAS_ACTION_TASKLIST);
  1782. case MSGINA_DLG_USER_LOGOFF:
  1783. return(WLX_SAS_ACTION_LOGOFF);
  1784. case MSGINA_DLG_FORCE_LOGOFF:
  1785. return(WLX_SAS_ACTION_FORCE_LOGOFF);
  1786. case MSGINA_DLG_SHUTDOWN:
  1787. if (Result & MSGINA_DLG_REBOOT_FLAG)
  1788. {
  1789. return(WLX_SAS_ACTION_SHUTDOWN_REBOOT);
  1790. }
  1791. else if (Result & MSGINA_DLG_POWEROFF_FLAG)
  1792. {
  1793. return(WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
  1794. }
  1795. else if (Result & MSGINA_DLG_SLEEP_FLAG)
  1796. {
  1797. return(WLX_SAS_ACTION_SHUTDOWN_SLEEP);
  1798. }
  1799. else if (Result & MSGINA_DLG_SLEEP2_FLAG)
  1800. {
  1801. return(WLX_SAS_ACTION_SHUTDOWN_SLEEP2);
  1802. }
  1803. else if (Result & MSGINA_DLG_HIBERNATE_FLAG)
  1804. {
  1805. return(WLX_SAS_ACTION_SHUTDOWN_HIBERNATE);
  1806. }
  1807. else
  1808. return(WLX_SAS_ACTION_SHUTDOWN);
  1809. }
  1810. }
  1811. BOOL
  1812. WINAPI
  1813. WlxIsLockOk(
  1814. PVOID pWlxContext
  1815. )
  1816. {
  1817. PGLOBALS pGlobals = (PGLOBALS) pWlxContext ;
  1818. // Stop filtering SC events so SC unlock works
  1819. pWlxFuncs->WlxSetOption( pGlobals->hGlobalWlx,
  1820. WLX_OPTION_USE_SMART_CARD,
  1821. 1,
  1822. NULL
  1823. );
  1824. return(TRUE);
  1825. }
  1826. BOOL
  1827. WINAPI
  1828. WlxIsLogoffOk(
  1829. PVOID pWlxContext
  1830. )
  1831. {
  1832. return(TRUE);
  1833. }
  1834. VOID
  1835. WINAPI
  1836. WlxLogoff(
  1837. PVOID pWlxContext
  1838. )
  1839. {
  1840. PGLOBALS pGlobals;
  1841. pGlobals = (PGLOBALS) pWlxContext;
  1842. pGlobals->UserName[0] = L'\0';
  1843. pGlobals->UserProcessData.UserToken = NULL;
  1844. if (pGlobals->UserProcessData.RestrictedToken != NULL)
  1845. {
  1846. NtClose(pGlobals->UserProcessData.RestrictedToken);
  1847. pGlobals->UserProcessData.RestrictedToken = NULL;
  1848. }
  1849. if ( pGlobals->FlatUserName.Buffer != pGlobals->UserNameString.Buffer )
  1850. {
  1851. LocalFree( pGlobals->FlatUserName.Buffer );
  1852. }
  1853. if ( pGlobals->FlatDomain.Buffer != pGlobals->DomainString.Buffer )
  1854. {
  1855. LocalFree( pGlobals->FlatDomain.Buffer );
  1856. }
  1857. if (pGlobals->UserProcessData.UserSid != NULL)
  1858. {
  1859. LocalFree(pGlobals->UserProcessData.UserSid);
  1860. }
  1861. if( NULL != pGlobals->UserProcessData.NewThreadTokenSD )
  1862. {
  1863. FreeSecurityDescriptor(pGlobals->UserProcessData.NewThreadTokenSD);
  1864. pGlobals->UserProcessData.NewThreadTokenSD = NULL;
  1865. }
  1866. if (pGlobals->UserProcessData.pEnvironment) {
  1867. VirtualFree(pGlobals->UserProcessData.pEnvironment, 0, MEM_RELEASE);
  1868. pGlobals->UserProcessData.pEnvironment = NULL;
  1869. }
  1870. pGlobals->UserProcessData.Flags = 0 ;
  1871. if ( pGlobals->DnsDomain )
  1872. {
  1873. LocalFree( pGlobals->DnsDomain );
  1874. pGlobals->DnsDomain = NULL ;
  1875. }
  1876. if (pGlobals->Profile)
  1877. {
  1878. LsaFreeReturnBuffer(pGlobals->Profile);
  1879. pGlobals->Profile = NULL;
  1880. }
  1881. //
  1882. // No need to zero/NULL pGlobals->OldPassword since it's hashed
  1883. //
  1884. pGlobals->OldPasswordPresent = 0;
  1885. // reset transfered credentials flag.
  1886. pGlobals->TransderedCredentials = FALSE;
  1887. //
  1888. // Only handle AutoAdminLogon if on the console
  1889. //
  1890. if (!g_Console)
  1891. {
  1892. return;
  1893. }
  1894. if (GetProfileInt( APPLICATION_NAME, TEXT("AutoAdminLogon"), 0))
  1895. {
  1896. //
  1897. // If this is auto admin logon, generate a fake SAS right now.
  1898. //
  1899. pWlxFuncs->WlxSasNotify(pGlobals->hGlobalWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
  1900. }
  1901. return;
  1902. }
  1903. VOID
  1904. WINAPI
  1905. WlxShutdown(
  1906. PVOID pWlxContext,
  1907. DWORD ShutdownType
  1908. )
  1909. {
  1910. //
  1911. // Initialize consumer windows changes
  1912. //
  1913. _Shell_Terminate();
  1914. return;
  1915. }
  1916. BOOL
  1917. WINAPI
  1918. WlxScreenSaverNotify(
  1919. PVOID pWlxContext,
  1920. BOOL * fSecure)
  1921. {
  1922. if (*fSecure)
  1923. { // If it is a secure screen saver,
  1924. // this is equivalent to a lock
  1925. *fSecure = WlxIsLockOk(pWlxContext);
  1926. }
  1927. return( TRUE );
  1928. }
  1929. BOOL
  1930. WINAPI
  1931. WlxNetworkProviderLoad(
  1932. PVOID pWlxContext,
  1933. PWLX_MPR_NOTIFY_INFO pMprNotifyInfo
  1934. )
  1935. {
  1936. // Obsolete
  1937. return FALSE ;
  1938. }
  1939. VOID
  1940. WINAPI
  1941. WlxReconnectNotify(
  1942. PVOID pWlxContext)
  1943. {
  1944. _Shell_Reconnect();
  1945. }
  1946. VOID
  1947. WINAPI
  1948. WlxDisconnectNotify(
  1949. PVOID pWlxContext)
  1950. {
  1951. _Shell_Disconnect();
  1952. }
  1953. //+---------------------------------------------------------------------------
  1954. //
  1955. // Function: GetErrorDescription
  1956. //
  1957. // Synopsis: Returns the message from ntdll corresponding to the status
  1958. // code.
  1959. //
  1960. // Arguments: [ErrorCode] --
  1961. // [Description] --
  1962. // [DescriptionSize] --
  1963. //
  1964. // History: 5-02-97 RichardW Created
  1965. //
  1966. // Notes:
  1967. //
  1968. //----------------------------------------------------------------------------
  1969. BOOL
  1970. GetErrorDescription(
  1971. DWORD ErrorCode,
  1972. LPWSTR Description,
  1973. DWORD DescriptionSize
  1974. )
  1975. {
  1976. HMODULE Module ;
  1977. //
  1978. // First, try to determine what kind of error code it is:
  1979. //
  1980. //
  1981. // Some people disguise win32 error codes in HRESULTs. While
  1982. // this is annoying, it can be handled.
  1983. //
  1984. if ( ( ErrorCode & 0xFFFF0000 ) == 0x80070000 )
  1985. {
  1986. ErrorCode = ErrorCode & 0x0000FFFF ;
  1987. }
  1988. if ( (ErrorCode > 0) && (ErrorCode < 0x00010000) )
  1989. {
  1990. //
  1991. // Looks like a winerror:
  1992. //
  1993. Module = GetModuleHandle( TEXT("kernel32.dll") );
  1994. }
  1995. else if ( (0xC0000000 & ErrorCode ) == 0xC0000000 )
  1996. {
  1997. //
  1998. // Looks like an NT status
  1999. //
  2000. Module = GetModuleHandle( TEXT("ntdll.dll" ) );
  2001. }
  2002. else
  2003. {
  2004. Module = GetModuleHandle( TEXT("kernel32.dll" ) );
  2005. }
  2006. return FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS |
  2007. FORMAT_MESSAGE_FROM_HMODULE,
  2008. (LPCVOID) Module,
  2009. ErrorCode,
  2010. 0,
  2011. Description,
  2012. DescriptionSize,
  2013. NULL );
  2014. }
  2015. /*=============================================================================
  2016. == Local Procedures Defined
  2017. =============================================================================*/
  2018. /******************************************************************************
  2019. *
  2020. * FreeAutoLogonInfo
  2021. *
  2022. * Free WLX_CLIENT_CREDENTAILS_INFO and data strings returned
  2023. * from winlogon.
  2024. *
  2025. * ENTRY:
  2026. * pGlobals (input)
  2027. * pointer to GLOBALS struct
  2028. *
  2029. * EXIT:
  2030. * nothing
  2031. *
  2032. *****************************************************************************/
  2033. VOID
  2034. FreeAutoLogonInfo( PGLOBALS pGlobals )
  2035. {
  2036. PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pAutoLogon;
  2037. pAutoLogon = pGlobals->MuGlobals.pAutoLogon;
  2038. if( pAutoLogon == NULL ) {
  2039. return;
  2040. }
  2041. if ( pAutoLogon->pszUserName ) {
  2042. LocalFree( pAutoLogon->pszUserName );
  2043. }
  2044. if ( pAutoLogon->pszDomain ) {
  2045. LocalFree( pAutoLogon->pszDomain );
  2046. }
  2047. if ( pAutoLogon->pszPassword ) {
  2048. ZeroMemory(pAutoLogon->pszPassword, wcslen(pAutoLogon->pszPassword) * sizeof(WCHAR));
  2049. LocalFree( pAutoLogon->pszPassword );
  2050. }
  2051. LocalFree( pAutoLogon );
  2052. pGlobals->MuGlobals.pAutoLogon = NULL;
  2053. }