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.

1660 lines
45 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: shell.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 <stdio.h>
  16. #include <wchar.h>
  17. #include <regapi.h>
  18. #include <ginacomn.h>
  19. HICON hNoDCIcon;
  20. #if DBG
  21. DWORD DebugAllowNoShell = 1;
  22. #else
  23. DWORD DebugAllowNoShell = 0;
  24. #endif
  25. //
  26. // Parsing information for autoexec.bat
  27. //
  28. #define PARSE_AUTOEXEC_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
  29. #define PARSE_AUTOEXEC_ENTRY TEXT("ParseAutoexec")
  30. #define PARSE_AUTOEXEC_DEFAULT TEXT("1")
  31. #define MAX_PARSE_AUTOEXEC_BUFFER 2
  32. BOOL
  33. SetLogonScriptVariables(
  34. PGLOBALS pGlobals,
  35. PVOID * pEnvironment
  36. );
  37. BOOL
  38. SetAutoEnrollVariables(
  39. PGLOBALS pGlobals,
  40. PVOID * pEnvironment
  41. );
  42. VOID
  43. DeleteLogonScriptVariables(
  44. PGLOBALS pGlobals,
  45. PVOID * pEnvironment
  46. );
  47. void CtxCreateMigrateEnv( PVOID );
  48. void CtxDeleteMigrateEnv( VOID );
  49. BOOL
  50. DoAutoexecStuff(
  51. PGLOBALS pGlobals,
  52. PVOID * ppEnvironment,
  53. LPTSTR pszPathVar)
  54. {
  55. HKEY hKey;
  56. DWORD dwDisp, dwType, dwMaxBufferSize;
  57. TCHAR szParseAutoexec[MAX_PARSE_AUTOEXEC_BUFFER];
  58. //
  59. // Set the default case
  60. //
  61. lstrcpy (szParseAutoexec, PARSE_AUTOEXEC_DEFAULT);
  62. //
  63. // Impersonate the user, and check the registry
  64. //
  65. if (OpenHKeyCurrentUser(pGlobals)) {
  66. if (RegCreateKeyEx (pGlobals->UserProcessData.hCurrentUser, PARSE_AUTOEXEC_KEY, 0, 0,
  67. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  68. NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  69. //
  70. // Query the current value. If it doesn't exist, then add
  71. // the entry for next time.
  72. //
  73. dwMaxBufferSize = sizeof (TCHAR) * MAX_PARSE_AUTOEXEC_BUFFER;
  74. if (RegQueryValueEx (hKey, PARSE_AUTOEXEC_ENTRY, NULL, &dwType,
  75. (LPBYTE) szParseAutoexec, &dwMaxBufferSize)
  76. != ERROR_SUCCESS) {
  77. //
  78. // Set the default value
  79. //
  80. RegSetValueEx (hKey, PARSE_AUTOEXEC_ENTRY, 0, REG_SZ,
  81. (LPBYTE) szParseAutoexec,
  82. sizeof (TCHAR) * (lstrlen (szParseAutoexec) + 1));
  83. }
  84. //
  85. // Close key
  86. //
  87. RegCloseKey (hKey);
  88. }
  89. //
  90. // Close HKCU
  91. //
  92. CloseHKeyCurrentUser(pGlobals);
  93. }
  94. //
  95. // Process the autoexec if appropriate
  96. //
  97. if (szParseAutoexec[0] == TEXT('1')) {
  98. ProcessAutoexec(ppEnvironment, PATH_VARIABLE);
  99. }
  100. return(TRUE);
  101. }
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Function: UpdateUserEnvironment
  105. //
  106. // Synopsis:
  107. //
  108. // Arguments: [pGlobals] --
  109. // [ppEnvironment] --
  110. //
  111. // History: 11-01-94 RichardW Created
  112. //
  113. // Notes:
  114. //
  115. //----------------------------------------------------------------------------
  116. VOID
  117. UpdateUserEnvironment(
  118. PGLOBALS pGlobals,
  119. PVOID * ppEnvironment,
  120. PWSTR pszOldDir
  121. )
  122. {
  123. BOOL DeepShare;
  124. TCHAR lpHomeShare[MAX_PATH] = TEXT("");
  125. TCHAR lpHomePath[MAX_PATH] = TEXT("");
  126. TCHAR lpHomeDrive[4] = TEXT("");
  127. TCHAR lpHomeDirectory[MAX_PATH] = TEXT("");
  128. BOOL TSHomeDir = FALSE;
  129. TCHAR lpSmartcard[sizeof(pGlobals->Smartcard) + sizeof(pGlobals->SmartcardReader) + 1];
  130. /*
  131. * Initialize user's environment.
  132. */
  133. SetUserEnvironmentVariable(ppEnvironment, USERNAME_VARIABLE, (LPTSTR)pGlobals->FlatUserName.Buffer, TRUE);
  134. SetUserEnvironmentVariable(ppEnvironment, USERDOMAIN_VARIABLE, (LPTSTR)pGlobals->FlatDomain.Buffer, TRUE);
  135. if (pGlobals->Smartcard[0] && pGlobals->SmartcardReader[0]) {
  136. _snwprintf(
  137. lpSmartcard,
  138. sizeof(lpSmartcard) / sizeof(TCHAR),
  139. TEXT("%s;%s"),
  140. pGlobals->Smartcard,
  141. pGlobals->SmartcardReader
  142. );
  143. SetUserEnvironmentVariable(ppEnvironment, SMARTCARD_VARIABLE, lpSmartcard, TRUE);
  144. }
  145. if ( !g_Console ) {
  146. // See if the user specified a TerminalServer Home Directory.
  147. // If so, we override the regular directory
  148. if (lstrlen(pGlobals->MuGlobals.TSData.HomeDir) > 0) {
  149. lstrcpy(lpHomeDirectory, pGlobals->MuGlobals.TSData.HomeDir);
  150. TSHomeDir = TRUE;
  151. }
  152. if (lstrlen(pGlobals->MuGlobals.TSData.HomeDirDrive) > 0) {
  153. lstrcpy(lpHomeDrive, pGlobals->MuGlobals.TSData.HomeDirDrive);
  154. TSHomeDir = TRUE;
  155. }
  156. }
  157. if (!TSHomeDir && pGlobals->Profile) {
  158. if (pGlobals->Profile->HomeDirectoryDrive.Length &&
  159. (pGlobals->Profile->HomeDirectoryDrive.Length + 1) < (MAX_PATH*sizeof(TCHAR))) {
  160. lstrcpy(lpHomeDrive, pGlobals->Profile->HomeDirectoryDrive.Buffer);
  161. }
  162. if (pGlobals->Profile->HomeDirectory.Length &&
  163. (pGlobals->Profile->HomeDirectory.Length + 1) < (MAX_PATH*sizeof(TCHAR))) {
  164. lstrcpy(lpHomeDirectory, pGlobals->Profile->HomeDirectory.Buffer);
  165. }
  166. }
  167. SetHomeDirectoryEnvVars(ppEnvironment,
  168. lpHomeDirectory,
  169. lpHomeDrive,
  170. lpHomeShare,
  171. lpHomePath,
  172. &DeepShare);
  173. ChangeToHomeDirectory( pGlobals,
  174. ppEnvironment,
  175. lpHomeDirectory,
  176. lpHomeDrive,
  177. lpHomeShare,
  178. lpHomePath,
  179. pszOldDir,
  180. DeepShare
  181. );
  182. DoAutoexecStuff(pGlobals, ppEnvironment, PATH_VARIABLE);
  183. SetEnvironmentVariables(pGlobals, USER_ENV_SUBKEY, ppEnvironment);
  184. SetEnvironmentVariables(pGlobals, USER_VOLATILE_ENV_SUBKEY, ppEnvironment);
  185. AppendNTPathWithAutoexecPath(ppEnvironment,
  186. PATH_VARIABLE,
  187. AUTOEXECPATH_VARIABLE);
  188. if (!g_Console) {
  189. HKEY Handle;
  190. DWORD fPerSessionTempDir = 0;
  191. DWORD dwValueData;
  192. /*
  193. * Open registry value set thru TSCC
  194. */
  195. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  196. REG_CONTROL_TSERVER,
  197. 0,
  198. KEY_READ,
  199. &Handle ) == ERROR_SUCCESS )
  200. {
  201. DWORD ValueSize;
  202. DWORD ValueType;
  203. LONG rc;
  204. ValueSize = sizeof(fPerSessionTempDir);
  205. /*
  206. * Read registry value
  207. */
  208. rc = RegQueryValueExW( Handle,
  209. REG_TERMSRV_PERSESSIONTEMPDIR,
  210. NULL,
  211. &ValueType,
  212. (LPBYTE) &fPerSessionTempDir,
  213. &ValueSize );
  214. /*
  215. * Close registry and key handle
  216. */
  217. RegCloseKey( Handle );
  218. }
  219. /*
  220. * Check the machine wide policy set thru Group Policy
  221. */
  222. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  223. TS_POLICY_SUB_TREE,
  224. 0,
  225. KEY_READ,
  226. &Handle ) == ERROR_SUCCESS )
  227. {
  228. DWORD ValueSize;
  229. DWORD ValueType;
  230. LONG rc;
  231. ValueSize = sizeof(fPerSessionTempDir);
  232. /*
  233. * Read registry value
  234. */
  235. rc = RegQueryValueExW( Handle,
  236. REG_TERMSRV_PERSESSIONTEMPDIR,
  237. NULL,
  238. &ValueType,
  239. (LPBYTE) &dwValueData,
  240. &ValueSize );
  241. if (rc == ERROR_SUCCESS )
  242. {
  243. fPerSessionTempDir = dwValueData;
  244. }
  245. /*
  246. * Close registry and key handle
  247. */
  248. RegCloseKey( Handle );
  249. }
  250. if (fPerSessionTempDir) {
  251. PTERMSRVCREATETEMPDIR pfnTermsrvCreateTempDir;
  252. HANDLE dllHandle;
  253. dllHandle = LoadLibrary(TEXT("wlnotify.dll"));
  254. if (dllHandle) {
  255. pfnTermsrvCreateTempDir = (PTERMSRVCREATETEMPDIR) GetProcAddress(
  256. dllHandle,
  257. "TermsrvCreateTempDir"
  258. );
  259. if (pfnTermsrvCreateTempDir) {
  260. pfnTermsrvCreateTempDir( ppEnvironment,
  261. pGlobals->UserProcessData.UserToken,
  262. pGlobals->UserProcessData.NewThreadTokenSD);
  263. }
  264. FreeLibrary(dllHandle);
  265. }
  266. }
  267. }
  268. }
  269. BOOL
  270. ExecApplication(
  271. IN LPTSTR pch,
  272. IN LPTSTR Desktop,
  273. IN PGLOBALS pGlobals,
  274. IN PVOID pEnvironment,
  275. IN DWORD Flags,
  276. IN DWORD StartupFlags,
  277. IN BOOL RestrictProcess,
  278. OUT PPROCESS_INFORMATION ProcessInformation
  279. )
  280. {
  281. STARTUPINFO si;
  282. BOOL Result, IgnoreResult;
  283. HANDLE ImpersonationHandle;
  284. HANDLE ProcessToken;
  285. //
  286. // Initialize process startup info
  287. //
  288. si.cb = sizeof(STARTUPINFO);
  289. si.lpReserved = pch;
  290. si.lpTitle = pch;
  291. si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
  292. si.dwFlags = StartupFlags;
  293. si.wShowWindow = SW_SHOW; // at least let the guy see it
  294. si.lpReserved2 = NULL;
  295. si.cbReserved2 = 0;
  296. si.lpDesktop = Desktop;
  297. //
  298. // Impersonate the user so we get access checked correctly on
  299. // the file we're trying to execute
  300. //
  301. ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
  302. if (ImpersonationHandle == NULL) {
  303. WLPrint(("ExecApplication failed to impersonate user"));
  304. return(FALSE);
  305. }
  306. if (RestrictProcess &&
  307. (pGlobals->UserProcessData.RestrictedToken != NULL) )
  308. {
  309. ProcessToken = pGlobals->UserProcessData.RestrictedToken;
  310. }
  311. else
  312. {
  313. ProcessToken = pGlobals->UserProcessData.UserToken;
  314. }
  315. //
  316. // Create the app suspended
  317. //
  318. DebugLog((DEB_TRACE, "About to create process of %ws, on desktop %ws\n", pch, Desktop));
  319. Result = CreateProcessAsUser(
  320. ProcessToken,
  321. NULL,
  322. pch,
  323. NULL,
  324. NULL,
  325. FALSE,
  326. Flags | CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT,
  327. pEnvironment,
  328. NULL,
  329. &si,
  330. ProcessInformation);
  331. IgnoreResult = StopImpersonating(ImpersonationHandle);
  332. ASSERT(IgnoreResult);
  333. return(Result);
  334. }
  335. BOOL
  336. SetProcessQuotas(
  337. PGLOBALS pGlobals,
  338. PPROCESS_INFORMATION ProcessInformation,
  339. PUSER_PROCESS_DATA UserProcessData
  340. )
  341. {
  342. NTSTATUS Status = STATUS_SUCCESS;
  343. BOOL Result;
  344. QUOTA_LIMITS RequestedLimits;
  345. UINT MessageId ;
  346. RequestedLimits = UserProcessData->Quotas;
  347. RequestedLimits.MinimumWorkingSetSize = 0;
  348. RequestedLimits.MaximumWorkingSetSize = 0;
  349. if (UserProcessData->Quotas.PagedPoolLimit != 0) {
  350. Result = EnablePrivilege(SE_INCREASE_QUOTA_PRIVILEGE, TRUE);
  351. if (!Result) {
  352. WLPrint(("failed to enable increase_quota privilege"));
  353. return(FALSE);
  354. }
  355. Status = NtSetInformationProcess(
  356. ProcessInformation->hProcess,
  357. ProcessQuotaLimits,
  358. (PVOID)&RequestedLimits,
  359. (ULONG)sizeof(QUOTA_LIMITS)
  360. );
  361. Result = EnablePrivilege(SE_INCREASE_QUOTA_PRIVILEGE, FALSE);
  362. if (!Result) {
  363. WLPrint(("failed to disable increase_quota privilege"));
  364. }
  365. }
  366. if (STATUS_QUOTA_EXCEEDED == Status)
  367. {
  368. if ( TestTokenForAdmin( UserProcessData->UserToken ) )
  369. {
  370. MessageId = IDS_QUOTAEXHAUSTED ;
  371. Status = STATUS_SUCCESS ;
  372. }
  373. else
  374. {
  375. MessageId = IDS_COULDNTSETQUOTAS ;
  376. }
  377. // Display a warning in this case
  378. TimeoutMessageBox(pGlobals->hwndLogon,
  379. pGlobals,
  380. MessageId,
  381. IDS_LOGON_MESSAGE,
  382. MB_OK | MB_ICONERROR,
  383. TIMEOUT_NONE);
  384. }
  385. #if DBG
  386. if (!NT_SUCCESS(Status)) {
  387. WLPrint(("SetProcessQuotas failed. Status: 0x%lx", Status));
  388. }
  389. #endif //DBG
  390. return (NT_SUCCESS(Status));
  391. }
  392. DWORD
  393. ExecProcesses(
  394. PVOID pWlxContext,
  395. IN LPTSTR Desktop,
  396. IN PWSTR Processes,
  397. PVOID *ppEnvironment,
  398. DWORD Flags,
  399. DWORD StartupFlags
  400. )
  401. {
  402. PWCH pchData;
  403. PROCESS_INFORMATION ProcessInformation;
  404. DWORD dwExecuted = 0 ;
  405. PWSTR pszTok;
  406. PGLOBALS pGlobals = (PGLOBALS) pWlxContext;
  407. WCHAR szCurrentDir[MAX_PATH];
  408. pchData = Processes;
  409. szCurrentDir[0] = L'\0';
  410. if (*ppEnvironment) {
  411. UpdateUserEnvironment(pGlobals, ppEnvironment, szCurrentDir);
  412. }
  413. SetLogonScriptVariables(pGlobals, ppEnvironment);
  414. //we should not lauch autoenrollment in this case as it blocks the shell
  415. //SetAutoEnrollVariables( pGlobals, ppEnvironment );
  416. if (g_IsTerminalServer) {
  417. CtxCreateMigrateEnv( *ppEnvironment );
  418. pWlxFuncs->WlxWin31Migrate(pGlobals->hGlobalWlx);
  419. CtxDeleteMigrateEnv( );
  420. }
  421. pszTok = wcstok(pchData, TEXT(","));
  422. while (pszTok)
  423. {
  424. if (*pszTok == TEXT(' '))
  425. {
  426. while (*pszTok++ == TEXT(' '))
  427. ;
  428. }
  429. if (ExecApplication((LPTSTR)pszTok,
  430. Desktop,
  431. pGlobals,
  432. *ppEnvironment,
  433. Flags,
  434. StartupFlags,
  435. TRUE, // restrict application
  436. &ProcessInformation)) {
  437. dwExecuted++;
  438. if (SetProcessQuotas(pGlobals,
  439. &ProcessInformation,
  440. &pGlobals->UserProcessData))
  441. {
  442. ResumeThread(ProcessInformation.hThread);
  443. }
  444. else
  445. {
  446. TerminateProcess(ProcessInformation.hProcess,
  447. ERROR_ACCESS_DENIED);
  448. }
  449. CloseHandle(ProcessInformation.hThread);
  450. CloseHandle(ProcessInformation.hProcess);
  451. } else {
  452. DebugLog((DEB_WARN, "Cannot start %ws on %ws, error %d.", pszTok, Desktop, GetLastError()));
  453. }
  454. pszTok = wcstok(NULL, TEXT(","));
  455. }
  456. DeleteLogonScriptVariables(pGlobals, ppEnvironment);
  457. if ( szCurrentDir[0] )
  458. {
  459. SetCurrentDirectory(szCurrentDir);
  460. }
  461. return dwExecuted ;
  462. }
  463. INT_PTR
  464. NoDCDlgProc(
  465. HWND hDlg,
  466. UINT Message,
  467. WPARAM wParam,
  468. LPARAM lParam )
  469. {
  470. DWORD Button;
  471. HWND hwnd;
  472. switch (Message)
  473. {
  474. case WM_INITDIALOG:
  475. CentreWindow( hDlg );
  476. if ( !hNoDCIcon )
  477. {
  478. hNoDCIcon = LoadImage( hDllInstance,
  479. MAKEINTRESOURCE( IDI_NODC_ICON ),
  480. IMAGE_ICON,
  481. 64, 64,
  482. LR_DEFAULTCOLOR );
  483. }
  484. SendMessage( GetDlgItem( hDlg, IDD_NODC_FRAME ),
  485. STM_SETICON,
  486. (WPARAM) hNoDCIcon,
  487. 0 );
  488. if ( GetProfileInt( WINLOGON, TEXT("AllowDisableDCNotify"), 0 ) )
  489. {
  490. hwnd = GetDlgItem( hDlg, IDD_NODC_TEXT2 );
  491. ShowWindow( hwnd, SW_HIDE );
  492. EnableWindow( hwnd, FALSE );
  493. }
  494. else
  495. {
  496. hwnd = GetDlgItem( hDlg, IDD_NODC_CHECK );
  497. CheckDlgButton( hDlg, IDD_NODC_CHECK, BST_UNCHECKED );
  498. ShowWindow( hwnd, SW_HIDE );
  499. EnableWindow( hwnd, FALSE );
  500. }
  501. return( TRUE );
  502. case WM_COMMAND:
  503. if (LOWORD(wParam) == IDOK)
  504. {
  505. Button = IsDlgButtonChecked( hDlg, IDD_NODC_CHECK );
  506. EndDialog( hDlg, Button );
  507. return( TRUE );
  508. }
  509. }
  510. return( FALSE );
  511. }
  512. VOID
  513. DoNoDCDialog(
  514. PGLOBALS pGlobals )
  515. {
  516. HKEY hKey;
  517. int err;
  518. DWORD disp;
  519. DWORD Flag;
  520. DWORD dwType;
  521. DWORD cbData;
  522. BOOL MappedHKey;
  523. PWSTR ReportControllerMissing;
  524. Flag = 1;
  525. hKey = NULL ;
  526. if (OpenHKeyCurrentUser(pGlobals))
  527. {
  528. MappedHKey = TRUE;
  529. err = RegCreateKeyEx( pGlobals->UserProcessData.hCurrentUser,
  530. WINLOGON_USER_KEY,
  531. 0, NULL,
  532. REG_OPTION_NON_VOLATILE,
  533. KEY_READ | KEY_WRITE,
  534. NULL,
  535. &hKey,
  536. &disp );
  537. if (err == 0)
  538. {
  539. cbData = sizeof(DWORD);
  540. err = RegQueryValueEx( hKey,
  541. NODCMESSAGE,
  542. NULL,
  543. &dwType,
  544. (LPBYTE) &Flag,
  545. &cbData );
  546. if (err != ERROR_SUCCESS || dwType != REG_DWORD)
  547. {
  548. Flag = 1;
  549. }
  550. }
  551. else
  552. {
  553. hKey = NULL;
  554. }
  555. }
  556. else
  557. {
  558. MappedHKey = FALSE;
  559. }
  560. if ( Flag )
  561. {
  562. ReportControllerMissing = AllocAndGetProfileString( APPLICATION_NAME,
  563. REPORT_CONTROLLER_MISSING,
  564. TEXT("FALSE")
  565. );
  566. if ( ReportControllerMissing )
  567. {
  568. if ( lstrcmp( ReportControllerMissing, TEXT("TRUE")) == 0 )
  569. {
  570. Flag = 1;
  571. }
  572. else
  573. {
  574. Flag = 0;
  575. }
  576. Free( ReportControllerMissing );
  577. }
  578. else
  579. {
  580. Flag = 1;
  581. }
  582. }
  583. if (Flag)
  584. {
  585. pWlxFuncs->WlxSetTimeout( pGlobals->hGlobalWlx, 120 );
  586. Flag = pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx,
  587. hDllInstance,
  588. (LPTSTR) IDD_NODC_DIALOG,
  589. NULL,
  590. NoDCDlgProc,
  591. 0 );
  592. }
  593. else
  594. {
  595. Flag = BST_CHECKED;
  596. }
  597. if (hKey)
  598. {
  599. if (Flag == BST_CHECKED)
  600. {
  601. Flag = 0;
  602. }
  603. else
  604. {
  605. Flag = 1;
  606. }
  607. RegSetValueEx( hKey,
  608. NODCMESSAGE,
  609. 0,
  610. REG_DWORD,
  611. (LPBYTE) &Flag,
  612. sizeof(DWORD) );
  613. RegCloseKey( hKey );
  614. }
  615. if (MappedHKey)
  616. {
  617. CloseHKeyCurrentUser(pGlobals);
  618. }
  619. }
  620. //+---------------------------------------------------------------------------
  621. //
  622. // Function: GetPasswordExpiryWarningPeriod
  623. //
  624. // Synopsis: Returns the password expiry warning period in days: either
  625. // the value in the registry or the default value.
  626. //
  627. // Arguments: None
  628. //
  629. // Returns: Password expiry warning period in days.
  630. //
  631. // History: 10-09-01 CenkE Copied from ShouldPasswordExpiryWarningBeShown
  632. //
  633. //----------------------------------------------------------------------------
  634. DWORD
  635. GetPasswordExpiryWarningPeriod (
  636. VOID
  637. )
  638. {
  639. HKEY hKey;
  640. DWORD dwSize;
  641. DWORD dwType;
  642. DWORD DaysToCheck;
  643. DaysToCheck = PASSWORD_EXPIRY_WARNING_DAYS;
  644. if (RegOpenKey(HKEY_LOCAL_MACHINE, WINLOGON_USER_KEY, &hKey) == 0)
  645. {
  646. dwSize = sizeof(DWORD);
  647. if (RegQueryValueEx(hKey,
  648. PASSWORD_EXPIRY_WARNING,
  649. 0,
  650. &dwType,
  651. (LPBYTE) &DaysToCheck,
  652. &dwSize ) ||
  653. (dwType != REG_DWORD) )
  654. {
  655. DaysToCheck = PASSWORD_EXPIRY_WARNING_DAYS;
  656. }
  657. RegCloseKey(hKey);
  658. }
  659. return DaysToCheck;
  660. }
  661. //+---------------------------------------------------------------------------
  662. //
  663. // Function: GetDaysToExpiry
  664. //
  665. // Synopsis: If the passed in times can be converted to seconds since 1980,
  666. // returns how many days there are from CurrentTime to ExpiryTime
  667. //
  668. // Arguments: CurrentTime -- This can be the current time or the time of a
  669. // logon etc. as FILETIME.
  670. // ExpiryTime -- PasswordMustChange time from profile.
  671. // DaysToExpiry -- If successful, days to password expiry is
  672. // returned here.
  673. //
  674. // Returns: TRUE - DaysToExpiry could be calculated.
  675. // FALSE - DaysToExpiry could not be calculated, or the password
  676. // never expires.
  677. //
  678. // History: 10-09-01 CenkE Copied from ShouldPasswordExpiryWarningBeShown
  679. //
  680. //----------------------------------------------------------------------------
  681. #define SECONDS_PER_DAY (60*60*24)
  682. BOOL
  683. GetDaysToExpiry (
  684. IN PLARGE_INTEGER CurrentTime,
  685. IN PLARGE_INTEGER ExpiryTime,
  686. OUT PDWORD DaysToExpiry
  687. )
  688. {
  689. ULONG ElapsedSecondsNow;
  690. ULONG ElapsedSecondsPasswordExpires;
  691. //
  692. // Convert the expiry time to seconds.
  693. //
  694. if (!RtlTimeToSecondsSince1980(ExpiryTime, &ElapsedSecondsPasswordExpires))
  695. {
  696. //
  697. // The time was not expressable in 32-bit seconds
  698. // Set seconds to password expiry based on whether the expiry
  699. // time is way in the past or way in the future.
  700. //
  701. // Never expires?
  702. if (ExpiryTime->QuadPart > CurrentTime->QuadPart)
  703. {
  704. return FALSE;
  705. }
  706. ElapsedSecondsPasswordExpires = 0; // Already expired
  707. }
  708. //
  709. // Convert the start time to seconds.
  710. //
  711. if (!RtlTimeToSecondsSince1980(CurrentTime, &ElapsedSecondsNow)) {
  712. return FALSE;
  713. }
  714. if (ElapsedSecondsPasswordExpires < ElapsedSecondsNow)
  715. {
  716. (*DaysToExpiry) = 0;
  717. }
  718. else
  719. {
  720. (*DaysToExpiry) = (ElapsedSecondsPasswordExpires - ElapsedSecondsNow)/SECONDS_PER_DAY;
  721. }
  722. return TRUE;
  723. }
  724. BOOL
  725. ShouldPasswordExpiryWarningBeShown(
  726. IN PGLOBALS pGlobals,
  727. IN BOOL LogonCheck,
  728. OUT PDWORD pDaysToExpiry )
  729. {
  730. ULONG DaysToExpiry;
  731. DWORD DaysToCheck;
  732. LARGE_INTEGER Now;
  733. LARGE_INTEGER Last;
  734. PLARGE_INTEGER StartTime;
  735. if (pGlobals->TransderedCredentials) {
  736. // do not display password expiry in this case as it
  737. // would otherwise display the password expiry twice
  738. return FALSE;
  739. }
  740. Last.LowPart = pGlobals->LastNotification.dwLowDateTime;
  741. Last.HighPart = pGlobals->LastNotification.dwHighDateTime;
  742. GetSystemTimeAsFileTime((FILETIME*) &Now);
  743. Last.QuadPart += (24 * 60 * 60 * 10000000I64);
  744. //
  745. // Only if last shown more than 24 hours ago
  746. //
  747. if (Now.QuadPart < Last.QuadPart)
  748. {
  749. return FALSE;
  750. }
  751. //
  752. // Get password expiry warning period
  753. //
  754. DaysToCheck = GetPasswordExpiryWarningPeriod();
  755. //
  756. // Go get parameters from our user's profile
  757. //
  758. if (!pGlobals->Profile)
  759. {
  760. return FALSE;
  761. }
  762. if ( LogonCheck )
  763. {
  764. StartTime = &pGlobals->LogonTime;
  765. }
  766. else
  767. {
  768. StartTime = &Now;
  769. }
  770. //
  771. // Determine number of days till the password expires.
  772. //
  773. if (!GetDaysToExpiry(StartTime,
  774. &(pGlobals->Profile->PasswordMustChange),
  775. &DaysToExpiry))
  776. {
  777. return FALSE;
  778. }
  779. // Not within warning period?
  780. if (DaysToExpiry > DaysToCheck)
  781. {
  782. return FALSE;
  783. }
  784. // If return pointer... fill in
  785. if ( pDaysToExpiry )
  786. {
  787. *pDaysToExpiry = DaysToExpiry;
  788. }
  789. return TRUE;
  790. }
  791. //+---------------------------------------------------------------------------
  792. //
  793. // Function: CheckPasswordExpiry
  794. //
  795. // Synopsis: Does the password expiration check on demand
  796. //
  797. // Arguments: [pGlobals] --
  798. // [LogonCheck] --
  799. //
  800. // Requires:
  801. //
  802. // Returns:
  803. //
  804. // Signals:
  805. //
  806. // Modifies:
  807. //
  808. // Algorithm:
  809. //
  810. // History: 8-13-96 RichardW Created
  811. //
  812. // Notes:
  813. //
  814. //----------------------------------------------------------------------------
  815. INT_PTR
  816. CheckPasswordExpiry(
  817. PGLOBALS pGlobals,
  818. BOOL LogonCheck)
  819. {
  820. LARGE_INTEGER Now;
  821. ULONG DaysToExpiry;
  822. TCHAR Buffer1[MAX_STRING_BYTES];
  823. TCHAR Buffer2[MAX_STRING_BYTES];
  824. INT_PTR Result = IDOK;
  825. LPTSTR UserSidString;
  826. // Get current time
  827. GetSystemTimeAsFileTime((FILETIME*) &Now);
  828. if (ShouldPasswordExpiryWarningBeShown(pGlobals, LogonCheck, &DaysToExpiry))
  829. {
  830. //
  831. // Disable optimized logon for this user for next time if
  832. // we are entering the password expiry warning period, so
  833. // password expiry warning dialogs will be shown if the user
  834. // does not change the password right now. Otherwise
  835. // for cached logons password expiry time is invented to be
  836. // forever in the future.
  837. //
  838. if (pGlobals->UserProcessData.UserToken)
  839. {
  840. UserSidString = GcGetSidString(pGlobals->UserProcessData.UserToken);
  841. if (UserSidString)
  842. {
  843. GcSetNextLogonCacheable(UserSidString, FALSE);
  844. GcDeleteSidString(UserSidString);
  845. }
  846. }
  847. if (DaysToExpiry > 0)
  848. {
  849. LoadString(hDllInstance, IDS_PASSWORD_WILL_EXPIRE, Buffer1, sizeof(Buffer1) / sizeof( TCHAR ));
  850. _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR), Buffer1, DaysToExpiry);
  851. }
  852. else
  853. {
  854. LoadString(hDllInstance, IDS_PASSWORD_EXPIRES_TODAY, Buffer2, sizeof(Buffer2) / sizeof( TCHAR ));
  855. }
  856. LoadString(hDllInstance, IDS_LOGON_MESSAGE, Buffer1, sizeof(Buffer1) / sizeof( TCHAR ) );
  857. pGlobals->LastNotification.dwHighDateTime = Now.HighPart;
  858. pGlobals->LastNotification.dwLowDateTime = Now.LowPart;
  859. Result = TimeoutMessageBoxlpstr(NULL,
  860. pGlobals,
  861. Buffer2,
  862. Buffer1,
  863. MB_YESNO | MB_ICONEXCLAMATION,
  864. (LogonCheck ? LOGON_TIMEOUT : 60));
  865. if (Result == IDYES)
  866. {
  867. //
  868. // Let the user change their password now
  869. //
  870. if ( LogonCheck && pGlobals->SmartCardLogon )
  871. {
  872. LogonCheck = FALSE ;
  873. }
  874. if ( LogonCheck )
  875. {
  876. RevealPassword( &pGlobals->PasswordString );
  877. Result = ChangePasswordLogon(NULL,
  878. pGlobals,
  879. pGlobals->UserName,
  880. pGlobals->Domain,
  881. pGlobals->Password);
  882. if ( Result == IDCANCEL )
  883. {
  884. //
  885. // If we got cancelled, then the string won't get
  886. // updated, so rehide it so that unlocks work later
  887. //
  888. HidePassword( &pGlobals->Seed,
  889. &pGlobals->PasswordString );
  890. }
  891. }
  892. else
  893. {
  894. Result = ChangePassword(
  895. NULL,
  896. pGlobals,
  897. pGlobals->UserName,
  898. pGlobals->Domain,
  899. CHANGEPWD_OPTION_ALL );
  900. }
  901. }
  902. if (DLG_INTERRUPTED(Result))
  903. {
  904. return(Result);
  905. }
  906. }
  907. return MSGINA_DLG_SUCCESS;
  908. }
  909. /****************************************************************************\
  910. *
  911. * FUNCTION: DisplayPostShellLogonMessages
  912. *
  913. * PURPOSE: Displays any security warnings to the user after a successful logon
  914. * The messages are displayed while the shell is starting up.
  915. *
  916. * RETURNS: DLG_SUCCESS - the dialogs were displayed successfully.
  917. * DLG_INTERRUPTED() - a set defined in winlogon.h
  918. *
  919. * NOTE: Screen-saver timeouts are handled by our parent dialog so this
  920. * routine should never return DLG_SCREEN_SAVER_TIMEOUT
  921. *
  922. * HISTORY:
  923. *
  924. * 12-09-91 Davidc Created.
  925. *
  926. \****************************************************************************/
  927. INT_PTR
  928. DisplayPostShellLogonMessages(
  929. PGLOBALS pGlobals
  930. )
  931. {
  932. INT_PTR Result = IDOK;
  933. //
  934. // Check to see if the system time is properly set
  935. //
  936. {
  937. SYSTEMTIME Systime;
  938. GetSystemTime(&Systime);
  939. if ( Systime.wYear < 2000 ) {
  940. Result = TimeoutMessageBox(
  941. NULL,
  942. pGlobals,
  943. IDS_INVALID_TIME_MSG,
  944. IDS_INVALID_TIME,
  945. MB_OK | MB_ICONSTOP,
  946. TIMEOUT_NONE
  947. );
  948. if (DLG_INTERRUPTED(Result)) {
  949. return(Result);
  950. }
  951. }
  952. }
  953. pGlobals->LastNotification.dwHighDateTime = 0;
  954. pGlobals->LastNotification.dwLowDateTime = 0;
  955. if (!pGlobals->TransderedCredentials) {
  956. // do not display password expiry in this case as it
  957. // would otherwise display the password expiry twice
  958. Result = CheckPasswordExpiry( pGlobals, TRUE );
  959. }
  960. if (pGlobals->Profile != NULL) {
  961. //
  962. // Logon cache used
  963. //
  964. if (pGlobals->Profile->UserFlags & LOGON_CACHED_ACCOUNT)
  965. {
  966. //
  967. // Don't display any warning messages if we did an optimized logon.
  968. //
  969. if (pGlobals->OptimizedLogonStatus != OLS_LogonIsCached) {
  970. DoNoDCDialog( pGlobals );
  971. }
  972. }
  973. }
  974. //
  975. // Hash the password away, then destroy the text copy completely.
  976. //
  977. if (!pGlobals->TransderedCredentials) {
  978. RevealPassword( &pGlobals->PasswordString );
  979. if (pGlobals->SmartCardLogon)
  980. {
  981. // We don't want the SC PIN hash
  982. // (prevents password unlocks using the PIN)
  983. memset(pGlobals->PasswordHash, 0, sizeof(pGlobals->PasswordHash));
  984. }
  985. else
  986. {
  987. HashPassword( &pGlobals->PasswordString, pGlobals->PasswordHash );
  988. }
  989. ErasePassword( &pGlobals->PasswordString );
  990. }
  991. return(IDOK);
  992. }
  993. /***************************************************************************\
  994. * FUNCTION: SetLogonScriptVariables
  995. *
  996. * PURPOSE: Sets the appropriate environment variables in the user
  997. * process environment block so that the logon script information
  998. * can be passed into the userinit app.
  999. *
  1000. * RETURNS: TRUE on success, FALSE on failure
  1001. *
  1002. * HISTORY:
  1003. *
  1004. * 21-Aug-92 Davidc Created.
  1005. *
  1006. \***************************************************************************/
  1007. BOOL
  1008. SetLogonScriptVariables(
  1009. PGLOBALS pGlobals,
  1010. PVOID * pEnvironment
  1011. )
  1012. {
  1013. NTSTATUS Status;
  1014. LPWSTR EncodedMultiSz;
  1015. UNICODE_STRING Name, Value;
  1016. //
  1017. // Note whether we performed an optimized logon.
  1018. //
  1019. RtlInitUnicodeString(&Name, OPTIMIZED_LOGON_VARIABLE);
  1020. if (pGlobals->OptimizedLogonStatus == OLS_LogonIsCached) {
  1021. RtlInitUnicodeString(&Value, L"1");
  1022. } else {
  1023. RtlInitUnicodeString(&Value, L"0");
  1024. }
  1025. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &Value);
  1026. if (!NT_SUCCESS(Status)) {
  1027. WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &Value));
  1028. goto CleanupAndExit;
  1029. }
  1030. //
  1031. // Set our primary authenticator logon script variables
  1032. //
  1033. if (pGlobals->Profile != NULL) {
  1034. //
  1035. // Set the server name variable
  1036. //
  1037. RtlInitUnicodeString(&Name, LOGON_SERVER_VARIABLE);
  1038. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &pGlobals->Profile->LogonServer);
  1039. if (!NT_SUCCESS(Status)) {
  1040. WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &pGlobals->Profile->LogonServer));
  1041. goto CleanupAndExit;
  1042. }
  1043. //
  1044. // Set the script name variable
  1045. //
  1046. RtlInitUnicodeString(&Name, LOGON_SCRIPT_VARIABLE);
  1047. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &pGlobals->Profile->LogonScript);
  1048. if (!NT_SUCCESS(Status)) {
  1049. WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &pGlobals->Profile->LogonScript));
  1050. goto CleanupAndExit;
  1051. }
  1052. }
  1053. //
  1054. // Set the multiple provider script name variable
  1055. //
  1056. if (pGlobals->MprLogonScripts != NULL) {
  1057. RtlInitUnicodeString(&Name, MPR_LOGON_SCRIPT_VARIABLE);
  1058. EncodedMultiSz = EncodeMultiSzW(pGlobals->MprLogonScripts);
  1059. if (EncodedMultiSz == NULL) {
  1060. WLPrint(("Failed to encode MPR logon scripts into a string"));
  1061. goto CleanupAndExit;
  1062. }
  1063. RtlInitUnicodeString(&Value, EncodedMultiSz);
  1064. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &Value);
  1065. Free(EncodedMultiSz);
  1066. if (!NT_SUCCESS(Status)) {
  1067. WLPrint(("Failed to set mpr scripts environment variable <%Z>", &Name));
  1068. goto CleanupAndExit;
  1069. }
  1070. }
  1071. return(TRUE);
  1072. CleanupAndExit:
  1073. DeleteLogonScriptVariables(pGlobals, pEnvironment);
  1074. return(FALSE);
  1075. }
  1076. BOOL
  1077. SetAutoEnrollVariables(
  1078. PGLOBALS pGlobals,
  1079. PVOID * pEnvironment
  1080. )
  1081. {
  1082. BOOL Result = FALSE ;
  1083. UNICODE_STRING Name, Value ;
  1084. // we should check for safe boot, domain member, and policy flag in registry
  1085. // but we will always spawn userinit, so instead of duplicationg code, let
  1086. // autoenrollment do those checks.
  1087. /*
  1088. if (OpenHKeyCurrentUser(pGlobals))
  1089. {
  1090. if ( RegOpenKeyEx( pGlobals->UserProcessData.hCurrentUser,
  1091. WINLOGON_POLICY_KEY,
  1092. 0,
  1093. KEY_READ,
  1094. &hKey ) == 0 )
  1095. {
  1096. dwSize = sizeof( Result );
  1097. RegQueryValueEx( hKey,
  1098. DISABLE_AUTOENROLLMENT,
  1099. 0,
  1100. &dwType,
  1101. (PBYTE) &Result,
  1102. &dwSize );
  1103. RegCloseKey( hKey );
  1104. }
  1105. CloseHKeyCurrentUser(pGlobals);
  1106. }
  1107. */
  1108. //
  1109. // If the Disable flag hasn't been turned on, add the env var
  1110. //
  1111. if ( !Result )
  1112. {
  1113. RtlInitUnicodeString( &Name, USER_INIT_AUTOENROLL );
  1114. RtlInitUnicodeString( &Value, AUTOENROLL_NONEXCLUSIVE );
  1115. RtlSetEnvironmentVariable(pEnvironment, &Name, &Value);
  1116. RtlInitUnicodeString( &Name, USER_INIT_AUTOENROLLMODE );
  1117. RtlInitUnicodeString( &Value, AUTOENROLL_STARTUP );
  1118. RtlSetEnvironmentVariable(pEnvironment, &Name, &Value);
  1119. }
  1120. return TRUE ;
  1121. }
  1122. /***************************************************************************\
  1123. * FUNCTION: DeleteLogonScriptVariables
  1124. *
  1125. * PURPOSE: Deletes the environment variables in the user process
  1126. * environment block that we use to communicate logon script
  1127. * information to the userinit app
  1128. *
  1129. * RETURNS: Nothing
  1130. *
  1131. * HISTORY:
  1132. *
  1133. * 21-Aug-92 Davidc Created.
  1134. *
  1135. \***************************************************************************/
  1136. VOID
  1137. DeleteLogonScriptVariables(
  1138. PGLOBALS pGlobals,
  1139. PVOID * pEnvironment
  1140. )
  1141. {
  1142. NTSTATUS Status;
  1143. UNICODE_STRING Name;
  1144. RtlInitUnicodeString(&Name, OPTIMIZED_LOGON_VARIABLE);
  1145. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL);
  1146. if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) {
  1147. WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status));
  1148. }
  1149. RtlInitUnicodeString(&Name, LOGON_SERVER_VARIABLE);
  1150. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL);
  1151. if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) {
  1152. WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status));
  1153. }
  1154. RtlInitUnicodeString(&Name, LOGON_SCRIPT_VARIABLE);
  1155. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL);
  1156. if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) {
  1157. WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status));
  1158. }
  1159. if (pGlobals->MprLogonScripts != NULL) {
  1160. RtlInitUnicodeString(&Name, MPR_LOGON_SCRIPT_VARIABLE);
  1161. Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL);
  1162. if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) {
  1163. WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status));
  1164. }
  1165. }
  1166. }
  1167. BOOL
  1168. WINAPI
  1169. WlxActivateUserShell(
  1170. PVOID pWlxContext,
  1171. PWSTR pszDesktop,
  1172. PWSTR pszMprLogonScript,
  1173. PVOID pEnvironment
  1174. )
  1175. {
  1176. BOOL bExec;
  1177. PGLOBALS pGlobals;
  1178. PWSTR pchData;
  1179. BOOL fReturn = FALSE;
  1180. _ShellReleaseLogonMutex(TRUE);
  1181. pchData = AllocAndGetPrivateProfileString(APPLICATION_NAME,
  1182. USERINIT_KEY,
  1183. TEXT("%SystemRoot%\\system32\\userinit.exe"),
  1184. NULL);
  1185. if ( !pchData )
  1186. {
  1187. if (pszMprLogonScript) {
  1188. LocalFree(pszMprLogonScript);
  1189. }
  1190. goto WlxAUSEnd;
  1191. }
  1192. pGlobals = (PGLOBALS) pWlxContext;
  1193. if (pGlobals->MprLogonScripts) {
  1194. LocalFree(pGlobals->MprLogonScripts);
  1195. }
  1196. pGlobals->MprLogonScripts = pszMprLogonScript;
  1197. bExec = ExecProcesses(pWlxContext, pszDesktop, pchData, &pEnvironment, 0, 0);
  1198. Free( pchData );
  1199. if (!bExec && (DebugAllowNoShell == 0))
  1200. {
  1201. goto WlxAUSEnd;
  1202. }
  1203. if ( pGlobals->ExtraApps )
  1204. {
  1205. ExecProcesses( pWlxContext, pszDesktop, pGlobals->ExtraApps, &pEnvironment, 0, 0 );
  1206. Free( pGlobals->ExtraApps );
  1207. pGlobals->ExtraApps = NULL;
  1208. }
  1209. pGlobals->UserProcessData.pEnvironment = pEnvironment;
  1210. // Write out the current user name to a place where shell logoff can read it
  1211. if (OpenHKeyCurrentUser(pGlobals))
  1212. {
  1213. HKEY hkeyExplorer = NULL;
  1214. if (ERROR_SUCCESS == RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser,
  1215. SHUTDOWN_SETTING_KEY, 0, KEY_SET_VALUE, &hkeyExplorer))
  1216. {
  1217. RegSetValueEx(hkeyExplorer, LOGON_USERNAME_SETTING, 0, REG_SZ,
  1218. (CONST BYTE *) pGlobals->UserName,
  1219. ((lstrlen(pGlobals->UserName) + 1) * sizeof(WCHAR)));
  1220. RegCloseKey(hkeyExplorer);
  1221. }
  1222. CloseHKeyCurrentUser(pGlobals);
  1223. }
  1224. // Run the dirty dialog box.
  1225. if ( WinlogonDirtyDialog( NULL, pGlobals ) == WLX_SAS_ACTION_LOGOFF )
  1226. {
  1227. //
  1228. // If this returns logoff, it means that the dialog timed out and
  1229. // we need to force the user back off. Not the best user experience,
  1230. // but that's what the PMs want.
  1231. //
  1232. }
  1233. else
  1234. {
  1235. fReturn = TRUE ;
  1236. }
  1237. WlxAUSEnd:
  1238. return fReturn;
  1239. }
  1240. BOOL
  1241. WINAPI
  1242. WlxStartApplication(
  1243. PVOID pWlxContext,
  1244. PWSTR pszDesktop,
  1245. PVOID pEnvironment,
  1246. PWSTR pszCmdLine
  1247. )
  1248. {
  1249. PROCESS_INFORMATION ProcessInformation;
  1250. BOOL bExec;
  1251. PGLOBALS pGlobals = (PGLOBALS) pWlxContext;
  1252. WCHAR szCurrentDir[MAX_PATH];
  1253. WCHAR localApp[ MAX_PATH ];
  1254. szCurrentDir[0] = L'\0';
  1255. if (pEnvironment) {
  1256. UpdateUserEnvironment(pGlobals, &pEnvironment, szCurrentDir);
  1257. }
  1258. if ( (_wcsicmp(pszCmdLine, L"explorer.exe" ) == 0 ) ||
  1259. (_wcsicmp(pszCmdLine, L"explorer" ) == 0 ) ) {
  1260. //
  1261. // Avoid security problem since explorer is in SystemRoot,
  1262. // not SystemRoot\system32
  1263. //
  1264. if ( ExpandEnvironmentStrings(
  1265. L"%SystemRoot%\\explorer.exe",
  1266. localApp,
  1267. MAX_PATH ) != 0 ) {
  1268. pszCmdLine = localApp ;
  1269. }
  1270. }
  1271. bExec = ExecApplication (pszCmdLine,
  1272. pszDesktop,
  1273. pGlobals,
  1274. pEnvironment,
  1275. 0,
  1276. STARTF_USESHOWWINDOW,
  1277. _wcsicmp(pszCmdLine, TEXT("taskmgr.exe")), // don't restrict application
  1278. &ProcessInformation);
  1279. if (pEnvironment)
  1280. { // We don't need it anymore
  1281. VirtualFree(pEnvironment, 0, MEM_RELEASE);
  1282. }
  1283. if (!bExec) {
  1284. if ( szCurrentDir[0] )
  1285. {
  1286. SetCurrentDirectory(szCurrentDir);
  1287. }
  1288. return(FALSE);
  1289. }
  1290. if (SetProcessQuotas(pGlobals,
  1291. &ProcessInformation,
  1292. &pGlobals->UserProcessData))
  1293. {
  1294. ResumeThread(ProcessInformation.hThread);
  1295. }
  1296. else
  1297. {
  1298. TerminateProcess(ProcessInformation.hProcess,
  1299. ERROR_ACCESS_DENIED);
  1300. }
  1301. CloseHandle(ProcessInformation.hThread);
  1302. CloseHandle(ProcessInformation.hProcess);
  1303. if ( szCurrentDir[0] )
  1304. {
  1305. SetCurrentDirectory(szCurrentDir);
  1306. }
  1307. return(TRUE);
  1308. }
  1309. void
  1310. CtxCreateMigrateEnv( PVOID pEnv )
  1311. {
  1312. NTSTATUS Status;
  1313. UNICODE_STRING Name, Value;
  1314. DWORD cb;
  1315. cb = 1024;
  1316. Value.Buffer = Alloc(sizeof(TCHAR)*cb);
  1317. if (!Value.Buffer)
  1318. return;
  1319. Value.Length = (USHORT)cb;
  1320. Value.MaximumLength = (USHORT)cb;
  1321. RtlInitUnicodeString( &Name, HOMEDRIVE_VARIABLE );
  1322. Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value );
  1323. if ( NT_SUCCESS(Status) )
  1324. SetEnvironmentVariable( HOMEDRIVE_VARIABLE, Value.Buffer );
  1325. Value.Length = (USHORT)cb;
  1326. Value.MaximumLength = (USHORT)cb;
  1327. RtlInitUnicodeString( &Name, HOMEPATH_VARIABLE );
  1328. Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value );
  1329. if ( NT_SUCCESS(Status) )
  1330. SetEnvironmentVariable( HOMEPATH_VARIABLE, Value.Buffer );
  1331. Value.Length = (USHORT)cb;
  1332. Value.MaximumLength = (USHORT)cb;
  1333. RtlInitUnicodeString( &Name, INIDRIVE_VARIABLE );
  1334. Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value );
  1335. if ( NT_SUCCESS(Status) )
  1336. SetEnvironmentVariable( INIDRIVE_VARIABLE, Value.Buffer );
  1337. Value.Length = (USHORT)cb;
  1338. Value.MaximumLength = (USHORT)cb;
  1339. RtlInitUnicodeString(&Name, INIPATH_VARIABLE);
  1340. Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value );
  1341. if ( NT_SUCCESS(Status) )
  1342. SetEnvironmentVariable( INIPATH_VARIABLE, Value.Buffer );
  1343. Free(Value.Buffer);
  1344. }
  1345. void
  1346. CtxDeleteMigrateEnv( )
  1347. {
  1348. SetEnvironmentVariable( HOMEDRIVE_VARIABLE, NULL);
  1349. SetEnvironmentVariable( HOMEPATH_VARIABLE, NULL);
  1350. SetEnvironmentVariable( INIDRIVE_VARIABLE, NULL);
  1351. SetEnvironmentVariable( INIPATH_VARIABLE, NULL);
  1352. }