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.

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