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.

1327 lines
37 KiB

  1. #define UNICODE 1
  2. #include "shellprv.h"
  3. #include <regapi.h>
  4. #pragma hdrstop
  5. char * __cdecl StrTokEx (char ** pstring, const char * control);
  6. //
  7. // Value names for for different environment variables
  8. //
  9. #define PATH_VARIABLE TEXT("Path")
  10. #define LIBPATH_VARIABLE TEXT("LibPath")
  11. #define OS2LIBPATH_VARIABLE TEXT("Os2LibPath")
  12. #define AUTOEXECPATH_VARIABLE TEXT("AutoexecPath")
  13. #define HOMEDRIVE_VARIABLE TEXT("HOMEDRIVE")
  14. #define HOMESHARE_VARIABLE TEXT("HOMESHARE")
  15. #define HOMEPATH_VARIABLE TEXT("HOMEPATH")
  16. #define COMPUTERNAME_VARIABLE TEXT("COMPUTERNAME")
  17. #define USERNAME_VARIABLE TEXT("USERNAME")
  18. #define USERDOMAIN_VARIABLE TEXT("USERDOMAIN")
  19. #define USERDNSDOMAIN_VARIABLE TEXT("USERDNSDOMAIN")
  20. #define USERPROFILE_VARIABLE TEXT("USERPROFILE")
  21. #define ALLUSERSPROFILE_VARIABLE TEXT("ALLUSERSPROFILE")
  22. #define OS_VARIABLE TEXT("OS")
  23. #define PROCESSOR_VARIABLE TEXT("PROCESSOR_ARCHITECTURE")
  24. #define PROCESSOR_LEVEL_VARIABLE TEXT("PROCESSOR_LEVEL")
  25. #define SYSTEMDRIVE_VARIABLE TEXT("SystemDrive")
  26. #define SYSTEMROOT_VARIABLE TEXT("SystemRoot")
  27. #define PROGRAMFILES_VARIABLE TEXT("ProgramFiles")
  28. #define COMMONPROGRAMFILES_VARIABLE TEXT("CommonProgramFiles")
  29. #if defined(WX86) || defined(_WIN64)
  30. #define PROGRAMFILESX86_VARIABLE TEXT("ProgramFiles(x86)")
  31. #define COMMONPROGRAMFILESX86_VARIABLE TEXT("CommonProgramFiles(x86)")
  32. #endif
  33. #define SYSTEM_ENV_SUBKEY TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment")
  34. #define USER_ENV_SUBKEY TEXT("Environment")
  35. #define USER_VOLATILE_ENV_SUBKEY TEXT("Volatile Environment")
  36. //
  37. // Max environment variable length
  38. //
  39. #define MAX_VALUE_LEN 1024
  40. //
  41. // Parsing information for autoexec.bat
  42. //
  43. #define PARSE_AUTOEXEC_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
  44. #define PARSE_AUTOEXEC_ENTRY TEXT("ParseAutoexec")
  45. #define PARSE_AUTOEXEC_DEFAULT TEXT("1")
  46. #define MAX_PARSE_AUTOEXEC_BUFFER 2
  47. #ifdef _X86_
  48. BOOL IsPathIncludeRemovable(LPCTSTR lpValue)
  49. {
  50. BOOL ret = FALSE;
  51. LPTSTR pszDup = StrDup(lpValue);
  52. if (pszDup)
  53. {
  54. LPTSTR pszTemp = pszDup;
  55. while (*pszTemp)
  56. {
  57. // skip spaces
  58. for ( ; *pszTemp && *pszTemp == TEXT(' '); pszTemp++)
  59. ;
  60. // check if the drive is removable
  61. if (pszTemp[0] && pszTemp[1] && pszTemp[1] == TEXT(':') && pszTemp[2]) { // ex) "A:\"
  62. TCHAR c = pszTemp[3];
  63. pszTemp[3] = 0;
  64. if (PathIsRemovable(pszTemp)) {
  65. pszTemp[3] = c;
  66. ret = TRUE;
  67. break;
  68. }
  69. pszTemp[3] = c;
  70. }
  71. // skip to the next path
  72. for ( ; *pszTemp && *pszTemp != TEXT(';'); pszTemp++)
  73. ;
  74. if (*pszTemp)
  75. pszTemp++;
  76. }
  77. LocalFree(pszDup);
  78. }
  79. return ret;
  80. }
  81. #endif
  82. /***************************************************************************\
  83. * SetUserEvironmentVariable
  84. *
  85. *
  86. * History:
  87. * 2-28-92 Johannec Created
  88. *
  89. \***************************************************************************/
  90. BOOL SetUserEnvironmentVariable(void **pEnv, LPTSTR lpVariable, LPTSTR lpValue, BOOL bOverwrite)
  91. {
  92. NTSTATUS Status;
  93. UNICODE_STRING Name;
  94. UNICODE_STRING Value;
  95. DWORD cb;
  96. TCHAR szValue[1024];
  97. if (!*pEnv || !lpVariable || !*lpVariable) {
  98. return(FALSE);
  99. }
  100. RtlInitUnicodeString(&Name, lpVariable);
  101. cb = 1024;
  102. Value.Buffer = (PTCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  103. if (Value.Buffer) {
  104. Value.Length = (USHORT)cb;
  105. Value.MaximumLength = (USHORT)cb;
  106. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  107. LocalFree(Value.Buffer);
  108. if (NT_SUCCESS(Status) && !bOverwrite) {
  109. return(TRUE);
  110. }
  111. }
  112. if (lpValue && *lpValue) {
  113. //
  114. // Special case TEMP and TMP and shorten the path names
  115. //
  116. if ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
  117. (!lstrcmpi(lpVariable, TEXT("TMP")))) {
  118. if (!GetShortPathName (lpValue, szValue, 1024)) {
  119. lstrcpyn (szValue, lpValue, 1024);
  120. }
  121. } else {
  122. lstrcpyn (szValue, lpValue, 1024);
  123. }
  124. RtlInitUnicodeString(&Value, szValue);
  125. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  126. }
  127. else {
  128. Status = RtlSetEnvironmentVariable( pEnv, &Name, NULL);
  129. }
  130. return NT_SUCCESS(Status);
  131. }
  132. /***************************************************************************\
  133. * ExpandUserEvironmentVariable
  134. *
  135. *
  136. * History:
  137. * 2-28-92 Johannec Created
  138. *
  139. \***************************************************************************/
  140. DWORD ExpandUserEnvironmentStrings(void *pEnv, LPTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
  141. {
  142. NTSTATUS Status;
  143. UNICODE_STRING Source, Destination;
  144. ULONG Length;
  145. RtlInitUnicodeString( &Source, lpSrc );
  146. Destination.Buffer = lpDst;
  147. Destination.Length = 0;
  148. Destination.MaximumLength = (USHORT)(nSize*SIZEOF(WCHAR));
  149. Length = 0;
  150. Status = RtlExpandEnvironmentStrings_U( pEnv,
  151. (PUNICODE_STRING)&Source,
  152. (PUNICODE_STRING)&Destination,
  153. &Length
  154. );
  155. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) {
  156. return( Length );
  157. }
  158. else {
  159. return( 0 );
  160. }
  161. }
  162. /***************************************************************************\
  163. * BuildEnvironmentPath
  164. *
  165. *
  166. * History:
  167. * 2-28-92 Johannec Created
  168. *
  169. \***************************************************************************/
  170. BOOL BuildEnvironmentPath(void **pEnv, LPTSTR lpPathVariable, LPTSTR lpPathValue)
  171. {
  172. NTSTATUS Status;
  173. UNICODE_STRING Name;
  174. UNICODE_STRING Value;
  175. WCHAR lpTemp[1025];
  176. DWORD cb;
  177. if (!*pEnv) {
  178. return(FALSE);
  179. }
  180. RtlInitUnicodeString(&Name, lpPathVariable);
  181. cb = 1024;
  182. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  183. if (!Value.Buffer) {
  184. return(FALSE);
  185. }
  186. Value.Length = (USHORT)(sizeof(WCHAR) * cb);
  187. Value.MaximumLength = (USHORT)(sizeof(WCHAR) * cb);
  188. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  189. if (!NT_SUCCESS(Status)) {
  190. LocalFree(Value.Buffer);
  191. Value.Length = 0;
  192. *lpTemp = 0;
  193. }
  194. if (Value.Length) {
  195. lstrcpy(lpTemp, Value.Buffer);
  196. if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') ) {
  197. lstrcat(lpTemp, TEXT(";"));
  198. }
  199. LocalFree(Value.Buffer);
  200. }
  201. if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb)) {
  202. lstrcat(lpTemp, lpPathValue);
  203. RtlInitUnicodeString(&Value, lpTemp);
  204. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  205. }
  206. if (NT_SUCCESS(Status)) {
  207. return(TRUE);
  208. }
  209. return(FALSE);
  210. }
  211. /***************************************************************************\
  212. * SetEnvironmentVariables
  213. *
  214. * Reads the user-defined environment variables from the user registry
  215. * and adds them to the environment block at pEnv.
  216. *
  217. * History:
  218. * 2-28-92 Johannec Created
  219. *
  220. \***************************************************************************/
  221. BOOL SetEnvironmentVariables(void **pEnv, LPTSTR lpRegSubKey)
  222. {
  223. WCHAR lpValueName[MAX_PATH];
  224. LPBYTE lpDataBuffer;
  225. DWORD cbDataBuffer;
  226. LPBYTE lpData;
  227. LPTSTR lpExpandedValue = NULL;
  228. DWORD cbValueName = MAX_PATH;
  229. DWORD cbData;
  230. DWORD dwType;
  231. DWORD dwIndex = 0;
  232. HKEY hkey;
  233. BOOL bResult;
  234. if (RegOpenKeyExW(HKEY_CURRENT_USER, lpRegSubKey, 0, KEY_READ, &hkey)) {
  235. return(FALSE);
  236. }
  237. cbDataBuffer = 4096;
  238. lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cbDataBuffer*sizeof(WCHAR));
  239. if (lpDataBuffer == NULL) {
  240. RegCloseKey(hkey);
  241. return(FALSE);
  242. }
  243. lpData = lpDataBuffer;
  244. cbData = cbDataBuffer;
  245. bResult = TRUE;
  246. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  247. lpData, &cbData)) {
  248. if (cbValueName) {
  249. //
  250. // Limit environment variable length
  251. //
  252. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  253. if (dwType == REG_SZ) {
  254. //
  255. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  256. // their values apppended to the system path.
  257. //
  258. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  259. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  260. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  261. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpData);
  262. }
  263. else {
  264. //
  265. // the other environment variables are just set.
  266. //
  267. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpData, TRUE);
  268. }
  269. }
  270. }
  271. dwIndex++;
  272. cbData = cbDataBuffer;
  273. cbValueName = MAX_PATH;
  274. }
  275. dwIndex = 0;
  276. cbData = cbDataBuffer;
  277. cbValueName = MAX_PATH;
  278. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  279. lpData, &cbData)) {
  280. if (cbValueName) {
  281. //
  282. // Limit environment variable length
  283. //
  284. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  285. if (dwType == REG_EXPAND_SZ) {
  286. DWORD cb, cbNeeded;
  287. cb = 1024;
  288. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  289. if (lpExpandedValue) {
  290. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  291. if (cbNeeded > cb) {
  292. LocalFree(lpExpandedValue);
  293. cb = cbNeeded;
  294. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  295. if (lpExpandedValue) {
  296. ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  297. }
  298. }
  299. }
  300. if (lpExpandedValue == NULL) {
  301. bResult = FALSE;
  302. break;
  303. }
  304. //
  305. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  306. // their values apppended to the system path.
  307. //
  308. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  309. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  310. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  311. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpExpandedValue);
  312. }
  313. else {
  314. //
  315. // the other environment variables are just set.
  316. //
  317. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE);
  318. }
  319. LocalFree(lpExpandedValue);
  320. }
  321. }
  322. dwIndex++;
  323. cbData = cbDataBuffer;
  324. cbValueName = MAX_PATH;
  325. }
  326. LocalFree(lpDataBuffer);
  327. RegCloseKey(hkey);
  328. return(bResult);
  329. }
  330. /***************************************************************************\
  331. * SetSystemEnvironmentVariables
  332. *
  333. * Reads the system environment variables from the LOCAL_MACHINE registry
  334. * and adds them to the environment block at pEnv.
  335. *
  336. * History:
  337. * 2-28-92 Johannec Created
  338. *
  339. \***************************************************************************/
  340. BOOL SetSystemEnvironmentVariables(void **pEnv)
  341. {
  342. WCHAR lpValueName[MAX_PATH];
  343. LPBYTE lpDataBuffer;
  344. DWORD cbDataBuffer;
  345. LPBYTE lpData;
  346. LPTSTR lpExpandedValue = NULL;
  347. DWORD cbValueName = MAX_PATH;
  348. DWORD cbData;
  349. DWORD dwType;
  350. DWORD dwIndex = 0;
  351. HKEY hkey;
  352. BOOL bResult;
  353. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, SYSTEM_ENV_SUBKEY, 0, KEY_READ, &hkey)) {
  354. return(FALSE);
  355. }
  356. cbDataBuffer = 4096;
  357. lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cbDataBuffer*sizeof(WCHAR));
  358. if (lpDataBuffer == NULL) {
  359. KdPrint(("REGENENV: SetSystemEnvironmentVariables: Failed to allocate %d bytes\n", cbDataBuffer));
  360. RegCloseKey(hkey);
  361. return(FALSE);
  362. }
  363. //
  364. // First start by getting the systemroot and systemdrive values and
  365. // setting it in the new environment.
  366. //
  367. GetEnvironmentVariable(SYSTEMROOT_VARIABLE, (LPTSTR)lpDataBuffer, cbDataBuffer);
  368. SetUserEnvironmentVariable(pEnv, SYSTEMROOT_VARIABLE, (LPTSTR)lpDataBuffer, TRUE);
  369. GetEnvironmentVariable(SYSTEMDRIVE_VARIABLE, (LPTSTR)lpDataBuffer, cbDataBuffer);
  370. SetUserEnvironmentVariable(pEnv, SYSTEMDRIVE_VARIABLE, (LPTSTR)lpDataBuffer, TRUE);
  371. GetEnvironmentVariable(ALLUSERSPROFILE_VARIABLE, (LPTSTR)lpDataBuffer, cbDataBuffer);
  372. SetUserEnvironmentVariable(pEnv, ALLUSERSPROFILE_VARIABLE, (LPTSTR)lpDataBuffer, TRUE);
  373. lpData = lpDataBuffer;
  374. cbData = cbDataBuffer;
  375. bResult = TRUE;
  376. //
  377. // To generate the environment, this requires two passes. First pass
  378. // sets all the variables which do not need to be expanded. The
  379. // second pass expands variables (so it can use the variables from
  380. // the first pass.
  381. //
  382. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  383. lpData, &cbData)) {
  384. if (cbValueName) {
  385. //
  386. // Limit environment variable length
  387. //
  388. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  389. if (dwType == REG_SZ) {
  390. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpData, TRUE);
  391. }
  392. }
  393. dwIndex++;
  394. cbData = cbDataBuffer;
  395. cbValueName = MAX_PATH;
  396. }
  397. dwIndex = 0;
  398. cbData = cbDataBuffer;
  399. cbValueName = MAX_PATH;
  400. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  401. lpData, &cbData)) {
  402. if (cbValueName) {
  403. //
  404. // Limit environment variable length
  405. //
  406. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  407. if (dwType == REG_EXPAND_SZ) {
  408. DWORD cb, cbNeeded;
  409. cb = 1024;
  410. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  411. if (lpExpandedValue) {
  412. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  413. if (cbNeeded > cb) {
  414. LocalFree(lpExpandedValue);
  415. cb = cbNeeded;
  416. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb);
  417. if (lpExpandedValue) {
  418. ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  419. }
  420. }
  421. }
  422. if (lpExpandedValue == NULL) {
  423. bResult = FALSE;
  424. break;
  425. }
  426. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE);
  427. LocalFree(lpExpandedValue);
  428. }
  429. }
  430. dwIndex++;
  431. cbData = cbDataBuffer;
  432. cbValueName = MAX_PATH;
  433. }
  434. LocalFree(lpDataBuffer);
  435. RegCloseKey(hkey);
  436. return(bResult);
  437. }
  438. /***************************************************************************\
  439. * ProcessAutoexecPath
  440. *
  441. * Creates AutoexecPath environment variable using autoexec.bat
  442. * LpValue may be freed by this routine.
  443. *
  444. * History:
  445. * 06-02-92 Johannec Created.
  446. *
  447. \***************************************************************************/
  448. LPTSTR ProcessAutoexecPath(void *pEnv, LPTSTR lpValue, DWORD cb)
  449. {
  450. LPTSTR lpt;
  451. LPTSTR lpStart;
  452. LPTSTR lpPath;
  453. DWORD cbt;
  454. UNICODE_STRING Name;
  455. UNICODE_STRING Value;
  456. BOOL bPrevAutoexecPath;
  457. WCHAR ch;
  458. DWORD dwTemp, dwCount = 0;
  459. cbt = 1024;
  460. lpt = (LPTSTR)LocalAlloc(LPTR, cbt*sizeof(WCHAR));
  461. if (!lpt) {
  462. return(lpValue);
  463. }
  464. *lpt = 0;
  465. lpStart = lpValue;
  466. RtlInitUnicodeString(&Name, AUTOEXECPATH_VARIABLE);
  467. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cbt*sizeof(WCHAR));
  468. if (!Value.Buffer) {
  469. goto Fail;
  470. }
  471. while (NULL != (lpPath = wcsstr (lpValue, TEXT("%")))) {
  472. if (!_wcsnicmp(lpPath+1, TEXT("PATH%"), 5)) {
  473. //
  474. // check if we have an autoexecpath already set, if not just remove
  475. // the %path%
  476. //
  477. Value.Length = (USHORT)cbt;
  478. Value.MaximumLength = (USHORT)cbt;
  479. bPrevAutoexecPath = (BOOL)!RtlQueryEnvironmentVariable_U(pEnv, &Name, &Value);
  480. *lpPath = 0;
  481. dwTemp = dwCount + lstrlen (lpValue);
  482. if (dwTemp < cbt) {
  483. lstrcat(lpt, lpValue);
  484. dwCount = dwTemp;
  485. }
  486. if (bPrevAutoexecPath) {
  487. dwTemp = dwCount + lstrlen (Value.Buffer);
  488. if (dwTemp < cbt) {
  489. lstrcat(lpt, Value.Buffer);
  490. dwCount = dwTemp;
  491. }
  492. }
  493. *lpPath++ = TEXT('%');
  494. lpPath += 5; // go passed %path%
  495. lpValue = lpPath;
  496. }
  497. else {
  498. lpPath = wcsstr(lpPath+1, TEXT("%"));
  499. if (!lpPath) {
  500. lpStart = NULL;
  501. goto Fail;
  502. }
  503. lpPath++;
  504. ch = *lpPath;
  505. *lpPath = 0;
  506. dwTemp = dwCount + lstrlen (lpValue);
  507. if (dwTemp < cbt) {
  508. lstrcat(lpt, lpValue);
  509. dwCount = dwTemp;
  510. }
  511. *lpPath = ch;
  512. lpValue = lpPath;
  513. }
  514. }
  515. if (*lpValue) {
  516. dwTemp = dwCount + lstrlen (lpValue);
  517. if (dwTemp < cbt) {
  518. lstrcat(lpt, lpValue);
  519. dwCount = dwTemp;
  520. }
  521. }
  522. LocalFree(Value.Buffer);
  523. LocalFree(lpStart);
  524. return(lpt);
  525. Fail:
  526. LocalFree(lpt);
  527. return(lpStart);
  528. }
  529. /***************************************************************************\
  530. * ProcessCommand
  531. *
  532. * History:
  533. * 01-24-92 Johannec Created.
  534. *
  535. \***************************************************************************/
  536. BOOL ProcessCommand(LPSTR lpStart, void **pEnv)
  537. {
  538. LPTSTR lpt, lptt;
  539. LPTSTR lpVariable;
  540. LPTSTR lpValue;
  541. LPTSTR lpExpandedValue = NULL;
  542. WCHAR c;
  543. DWORD cb, cbNeeded;
  544. LPTSTR lpu;
  545. //
  546. // convert to Unicode
  547. //
  548. lpu = (LPTSTR)LocalAlloc(LPTR, (cb=lstrlenA(lpStart)+1)*sizeof(WCHAR));
  549. if (!lpu) {
  550. return FALSE;
  551. }
  552. MultiByteToWideChar(CP_OEMCP, 0, lpStart, -1, lpu, cb);
  553. //
  554. // Find environment variable.
  555. //
  556. for (lpt = lpu; *lpt && *lpt == TEXT(' '); lpt++) //skip spaces
  557. ;
  558. if (!*lpt) {
  559. LocalFree (lpu);
  560. return(FALSE);
  561. }
  562. lptt = lpt;
  563. for (; *lpt && *lpt != TEXT(' ') && *lpt != TEXT('='); lpt++) //find end of variable name
  564. ;
  565. c = *lpt;
  566. *lpt = 0;
  567. lpVariable = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lptt) + 1)*sizeof(WCHAR));
  568. if (!lpVariable) {
  569. LocalFree (lpu);
  570. return(FALSE);
  571. }
  572. lstrcpy(lpVariable, lptt);
  573. *lpt = c;
  574. //
  575. // Find environment variable value.
  576. //
  577. for (; *lpt && (*lpt == TEXT(' ') || *lpt == TEXT('=')); lpt++)
  578. ;
  579. if (!*lpt) {
  580. // if we have a blank path statement in the autoexec file,
  581. // then we don't want to pass "PATH" as the environment
  582. // variable because it trashes the system's PATH. Instead
  583. // we want to change the variable AutoexecPath. This would have
  584. // be handled below if a value had been assigned to the
  585. // environment variable.
  586. if (lstrcmpi(lpVariable, PATH_VARIABLE) == 0)
  587. {
  588. SetUserEnvironmentVariable(pEnv, AUTOEXECPATH_VARIABLE, TEXT(""), TRUE);
  589. }
  590. else
  591. {
  592. SetUserEnvironmentVariable(pEnv, lpVariable, TEXT(""), TRUE);
  593. }
  594. LocalFree (lpu);
  595. LocalFree (lpVariable);
  596. return(FALSE);
  597. }
  598. lptt = lpt;
  599. for (; *lpt; lpt++) //find end of varaible value
  600. ;
  601. c = *lpt;
  602. *lpt = 0;
  603. lpValue = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lptt) + 1)*sizeof(WCHAR));
  604. if (!lpValue) {
  605. LocalFree (lpu);
  606. LocalFree(lpVariable);
  607. return(FALSE);
  608. }
  609. lstrcpy(lpValue, lptt);
  610. *lpt = c;
  611. #ifdef _X86_
  612. // NEC98
  613. //
  614. // If the path includes removable drive,
  615. // it is assumed that the drive assignment has changed from DOS.
  616. //
  617. if (IsNEC_98 && (lstrcmpi(lpVariable, PATH_VARIABLE) == 0) && IsPathIncludeRemovable(lpValue)) {
  618. LocalFree(lpVariable);
  619. LocalFree(lpValue);
  620. return(FALSE);
  621. }
  622. #endif
  623. cb = 1024;
  624. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  625. if (lpExpandedValue) {
  626. if (!lstrcmpi(lpVariable, PATH_VARIABLE)) {
  627. lpValue = ProcessAutoexecPath(*pEnv, lpValue, (lstrlen(lpValue)+1)*sizeof(WCHAR));
  628. }
  629. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  630. if (cbNeeded > cb) {
  631. LocalFree(lpExpandedValue);
  632. cb = cbNeeded;
  633. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  634. if (lpExpandedValue) {
  635. ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  636. }
  637. }
  638. }
  639. if (!lpExpandedValue) {
  640. lpExpandedValue = lpValue;
  641. }
  642. if (lstrcmpi(lpVariable, PATH_VARIABLE)) {
  643. SetUserEnvironmentVariable(pEnv, lpVariable, lpExpandedValue, FALSE);
  644. }
  645. else {
  646. SetUserEnvironmentVariable(pEnv, AUTOEXECPATH_VARIABLE, lpExpandedValue, TRUE);
  647. }
  648. if (lpExpandedValue != lpValue) {
  649. LocalFree(lpExpandedValue);
  650. }
  651. LocalFree(lpVariable);
  652. LocalFree(lpValue);
  653. return(TRUE);
  654. }
  655. /***************************************************************************\
  656. * ProcessSetCommand
  657. *
  658. * History:
  659. * 01-24-92 Johannec Created.
  660. *
  661. \***************************************************************************/
  662. BOOL ProcessSetCommand(LPSTR lpStart, void **pEnv)
  663. {
  664. LPSTR lpt;
  665. //
  666. // Find environment variable.
  667. //
  668. for (lpt = lpStart; *lpt && *lpt != TEXT(' '); lpt++)
  669. ;
  670. if (!*lpt)
  671. return(FALSE);
  672. return (ProcessCommand(lpt, pEnv));
  673. }
  674. /***************************************************************************\
  675. * ProcessAutoexec
  676. *
  677. * History:
  678. * 01-24-92 Johannec Created.
  679. *
  680. \***************************************************************************/
  681. BOOL ProcessAutoexec(void **pEnv, LPTSTR lpPathVariable)
  682. {
  683. HANDLE fh;
  684. DWORD dwFileSize;
  685. DWORD dwBytesRead;
  686. CHAR *lpBuffer = NULL;
  687. CHAR *token;
  688. CHAR Seps[] = "&\n\r"; // Seperators for tokenizing autoexec.bat
  689. BOOL Status = FALSE;
  690. TCHAR szAutoExecBat [] = TEXT("c:\\autoexec.bat");
  691. #ifdef _X86_
  692. TCHAR szTemp[3];
  693. #endif
  694. UINT uiErrMode;
  695. CHAR *lpszStrTokBegin = NULL;
  696. // There is a case where the OS might not be booting from drive
  697. // C, so we can not assume that the autoexec.bat file is on c:\.
  698. // Set the error mode so the user doesn't see the critical error
  699. // popup and attempt to open the file on c:\.
  700. uiErrMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  701. #ifdef _X86_
  702. if (IsNEC_98) {
  703. if (GetEnvironmentVariable (TEXT("SystemDrive"), szTemp, 3)) {
  704. szAutoExecBat[0] = szTemp[0];
  705. }
  706. }
  707. #endif
  708. fh = CreateFile (szAutoExecBat, GENERIC_READ, FILE_SHARE_READ,
  709. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  710. SetErrorMode (uiErrMode);
  711. if (fh == INVALID_HANDLE_VALUE) {
  712. return(FALSE); //could not open autoexec.bat file, we're done.
  713. }
  714. dwFileSize = GetFileSize(fh, NULL);
  715. if (dwFileSize == -1) {
  716. goto Exit; // can't read the file size
  717. }
  718. lpBuffer = (PCHAR)LocalAlloc(LPTR, dwFileSize+1);
  719. if (!lpBuffer) {
  720. goto Exit;
  721. }
  722. Status = ReadFile(fh, lpBuffer, dwFileSize, &dwBytesRead, NULL);
  723. if (!Status) {
  724. goto Exit; // error reading file
  725. }
  726. //
  727. // Zero terminate the buffer so we don't walk off the end
  728. //
  729. ASSERT(dwBytesRead <= dwFileSize);
  730. lpBuffer[dwBytesRead] = 0;
  731. //
  732. // Search for SET and PATH commands
  733. //
  734. // save off lpBuffer
  735. lpszStrTokBegin = lpBuffer;
  736. token = StrTokEx(&lpBuffer, Seps);
  737. while (token != NULL) {
  738. for (;*token && *token == ' ';token++) //skip spaces
  739. ;
  740. if (*token == TEXT('@'))
  741. token++;
  742. for (;*token && *token == ' ';token++) //skip spaces
  743. ;
  744. if (!_strnicmp(token, "Path", 4)) {
  745. ProcessCommand(token, pEnv);
  746. }
  747. if (!_strnicmp(token, "SET", 3)) {
  748. ProcessSetCommand(token, pEnv);
  749. }
  750. token = StrTokEx(&lpBuffer, Seps);
  751. }
  752. lpBuffer=lpszStrTokBegin;
  753. Exit:
  754. CloseHandle(fh);
  755. if (lpBuffer) {
  756. LocalFree(lpBuffer);
  757. }
  758. return(Status);
  759. }
  760. /***************************************************************************\
  761. * AppendNTPathWithAutoexecPath
  762. *
  763. * Gets the AutoexecPath created in ProcessAutoexec, and appends it to
  764. * the NT path.
  765. *
  766. * History:
  767. * 05-28-92 Johannec Created.
  768. *
  769. \***************************************************************************/
  770. BOOL
  771. AppendNTPathWithAutoexecPath(
  772. void **pEnv,
  773. LPTSTR lpPathVariable,
  774. LPTSTR lpAutoexecPath
  775. )
  776. {
  777. NTSTATUS Status;
  778. UNICODE_STRING Name;
  779. UNICODE_STRING Value;
  780. WCHAR AutoexecPathValue[1024];
  781. DWORD cb;
  782. BOOL Success;
  783. if (!*pEnv) {
  784. return(FALSE);
  785. }
  786. RtlInitUnicodeString(&Name, lpAutoexecPath);
  787. cb = 1024;
  788. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  789. if (!Value.Buffer) {
  790. return(FALSE);
  791. }
  792. Value.Length = (USHORT)cb;
  793. Value.MaximumLength = (USHORT)cb;
  794. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  795. if (!NT_SUCCESS(Status)) {
  796. LocalFree(Value.Buffer);
  797. return(FALSE);
  798. }
  799. if (Value.Length) {
  800. lstrcpy(AutoexecPathValue, Value.Buffer);
  801. }
  802. LocalFree(Value.Buffer);
  803. Success = BuildEnvironmentPath(pEnv, lpPathVariable, AutoexecPathValue);
  804. RtlSetEnvironmentVariable( pEnv, &Name, NULL);
  805. return(Success);
  806. }
  807. STDAPI_(BOOL) GetUserNameAndDomain(LPTSTR *ppszUserName, LPTSTR *ppszUserDomain)
  808. {
  809. BOOL bRet = FALSE;
  810. HANDLE hToken;
  811. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  812. {
  813. DWORD cbTokenBuffer = 0;
  814. if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer) ||
  815. GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  816. {
  817. PTOKEN_USER pUserToken = (PTOKEN_USER)LocalAlloc(LPTR, cbTokenBuffer * sizeof(WCHAR));
  818. if (pUserToken)
  819. {
  820. if (GetTokenInformation(hToken, TokenUser, pUserToken, cbTokenBuffer, &cbTokenBuffer))
  821. {
  822. DWORD cbAccountName = 0, cbUserDomain = 0;
  823. SID_NAME_USE SidNameUse;
  824. if (LookupAccountSid(NULL, pUserToken->User.Sid, NULL, &cbAccountName, NULL, &cbUserDomain, &SidNameUse) ||
  825. GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  826. {
  827. LPTSTR pszUserName = (LPTSTR)LocalAlloc(LPTR, cbAccountName * sizeof(WCHAR));
  828. LPTSTR pszUserDomain = (LPTSTR)LocalAlloc(LPTR, cbUserDomain * sizeof(WCHAR));
  829. if (pszUserName && pszUserDomain &&
  830. LookupAccountSid(NULL, pUserToken->User.Sid,
  831. pszUserName, &cbAccountName,
  832. pszUserDomain, &cbUserDomain, &SidNameUse))
  833. {
  834. if (ppszUserName)
  835. {
  836. *ppszUserName = pszUserName;
  837. pszUserName = NULL;
  838. }
  839. if (ppszUserDomain)
  840. {
  841. *ppszUserDomain = pszUserDomain;
  842. pszUserDomain = NULL;
  843. }
  844. bRet = TRUE;
  845. }
  846. if (pszUserName)
  847. LocalFree(pszUserName);
  848. if (pszUserDomain)
  849. LocalFree(pszUserDomain);
  850. }
  851. }
  852. LocalFree(pUserToken);
  853. }
  854. }
  855. CloseHandle(hToken);
  856. }
  857. return bRet;
  858. }
  859. //
  860. // tsnotify.dll export
  861. //
  862. typedef BOOL (*PTERMSRVCREATETEMPDIR) (PVOID *pEnv,HANDLE UserToken,PSECURITY_DESCRIPTOR SD);
  863. /***************************************************************************\
  864. * SetPerSessionTempDir - adds a session number to the TMP/TEMP path if necessary.
  865. *
  866. *
  867. * History:
  868. * 10-4-2000 skuzin Created
  869. *
  870. \***************************************************************************/
  871. void
  872. SetPerSessionTempDir(
  873. PVOID *ppEnvironment)
  874. {
  875. HKEY Handle;
  876. DWORD fPerSessionTempDir = 0;
  877. DWORD dwValueData;
  878. /*
  879. * Open registry value set thru TSCC
  880. */
  881. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  882. REG_CONTROL_TSERVER,
  883. 0,
  884. KEY_READ,
  885. &Handle ) == ERROR_SUCCESS )
  886. {
  887. DWORD ValueSize;
  888. DWORD ValueType;
  889. LONG rc;
  890. ValueSize = sizeof(fPerSessionTempDir);
  891. /*
  892. * Read registry value
  893. */
  894. rc = RegQueryValueExW( Handle,
  895. REG_TERMSRV_PERSESSIONTEMPDIR,
  896. NULL,
  897. &ValueType,
  898. (LPBYTE) &fPerSessionTempDir,
  899. &ValueSize );
  900. /*
  901. * Close registry and key handle
  902. */
  903. RegCloseKey( Handle );
  904. }
  905. /*
  906. * Check the machine wide policy set thru Group Policy
  907. */
  908. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  909. TS_POLICY_SUB_TREE,
  910. 0,
  911. KEY_READ,
  912. &Handle ) == ERROR_SUCCESS )
  913. {
  914. DWORD ValueSize;
  915. DWORD ValueType;
  916. LONG rc;
  917. ValueSize = sizeof(fPerSessionTempDir);
  918. /*
  919. * Read registry value
  920. */
  921. rc = RegQueryValueExW( Handle,
  922. REG_TERMSRV_PERSESSIONTEMPDIR,
  923. NULL,
  924. &ValueType,
  925. (LPBYTE) &dwValueData,
  926. &ValueSize );
  927. if (rc == ERROR_SUCCESS )
  928. {
  929. fPerSessionTempDir = dwValueData;
  930. }
  931. /*
  932. * Close registry and key handle
  933. */
  934. RegCloseKey( Handle );
  935. }
  936. if (fPerSessionTempDir)
  937. {
  938. PTERMSRVCREATETEMPDIR pfnTermsrvCreateTempDir;
  939. HANDLE dllHandle;
  940. dllHandle = LoadLibrary(TEXT("wlnotify.dll"));
  941. if (dllHandle)
  942. {
  943. pfnTermsrvCreateTempDir = (PTERMSRVCREATETEMPDIR)
  944. GetProcAddress(dllHandle, "TermsrvCreateTempDir");
  945. if (pfnTermsrvCreateTempDir)
  946. {
  947. pfnTermsrvCreateTempDir(ppEnvironment, NULL, NULL);
  948. }
  949. FreeLibrary(dllHandle);
  950. }
  951. }
  952. }
  953. /***************************************************************************\
  954. * RegenerateUserEnvironment
  955. *
  956. *
  957. * History:
  958. * 11-5-92 Johannec Created
  959. *
  960. \***************************************************************************/
  961. BOOL APIENTRY RegenerateUserEnvironment(void **pNewEnv, BOOL bSetCurrentEnv)
  962. {
  963. NTSTATUS Status;
  964. WCHAR szValue[1025];
  965. TCHAR szExpValue[1025];
  966. void *pEnv = NULL;
  967. void *pPrevEnv;
  968. LPTSTR UserName = NULL;
  969. LPTSTR UserDomain = NULL;
  970. HKEY hKey;
  971. DWORD dwDisp, dwType, dwMaxBufferSize;
  972. TCHAR szParseAutoexec[MAX_PARSE_AUTOEXEC_BUFFER];
  973. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  974. DWORD dwComputerNameSize = MAX_COMPUTERNAME_LENGTH+1;
  975. /*
  976. * Create a new environment for the user.
  977. */
  978. Status = RtlCreateEnvironment((BOOLEAN)FALSE, &pEnv);
  979. if (!NT_SUCCESS(Status)) {
  980. return(FALSE);
  981. }
  982. SetSystemEnvironmentVariables(&pEnv);
  983. /*
  984. * Initialize user's environment.
  985. */
  986. if (GetComputerName (szComputerName, &dwComputerNameSize)) {
  987. SetUserEnvironmentVariable(&pEnv, COMPUTERNAME_VARIABLE, (LPTSTR) szComputerName, TRUE);
  988. }
  989. if (GetUserNameAndDomain(&UserName, &UserDomain))
  990. {
  991. SetUserEnvironmentVariable( &pEnv, USERNAME_VARIABLE, UserName, TRUE);
  992. SetUserEnvironmentVariable( &pEnv, USERDOMAIN_VARIABLE, UserDomain, TRUE);
  993. LocalFree(UserName);
  994. LocalFree(UserDomain);
  995. }
  996. if (GetEnvironmentVariable(USERDNSDOMAIN_VARIABLE, szValue, ARRAYSIZE(szValue)))
  997. SetUserEnvironmentVariable( &pEnv, USERDNSDOMAIN_VARIABLE, szValue, TRUE);
  998. //
  999. // Set home directory env. vars.
  1000. //
  1001. if (GetEnvironmentVariable(HOMEDRIVE_VARIABLE, szValue, ARRAYSIZE(szValue)))
  1002. SetUserEnvironmentVariable( &pEnv, HOMEDRIVE_VARIABLE, szValue, TRUE);
  1003. if (GetEnvironmentVariable(HOMESHARE_VARIABLE, szValue, ARRAYSIZE(szValue)))
  1004. SetUserEnvironmentVariable( &pEnv, HOMESHARE_VARIABLE, szValue, TRUE);
  1005. if (GetEnvironmentVariable(HOMEPATH_VARIABLE, szValue, ARRAYSIZE(szValue)))
  1006. SetUserEnvironmentVariable( &pEnv, HOMEPATH_VARIABLE, szValue, TRUE);
  1007. //
  1008. // Set the user profile dir env var
  1009. //
  1010. if (GetEnvironmentVariable(USERPROFILE_VARIABLE, szValue, ARRAYSIZE(szValue)))
  1011. SetUserEnvironmentVariable( &pEnv, USERPROFILE_VARIABLE, szValue, TRUE);
  1012. //
  1013. // Set the program files env var
  1014. //
  1015. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion"),
  1016. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  1017. dwMaxBufferSize = sizeof(szValue);
  1018. if (SHQueryValueEx (hKey, TEXT("ProgramFilesDir"), NULL, &dwType,
  1019. (LPBYTE) szValue, &dwMaxBufferSize) == ERROR_SUCCESS) {
  1020. SHExpandEnvironmentStrings(szValue, szExpValue, ARRAYSIZE(szExpValue));
  1021. SetUserEnvironmentVariable(&pEnv, PROGRAMFILES_VARIABLE, szExpValue, TRUE);
  1022. }
  1023. dwMaxBufferSize = sizeof(szValue);
  1024. if (SHQueryValueEx (hKey, TEXT("CommonFilesDir"), NULL, &dwType,
  1025. (LPBYTE) szValue, &dwMaxBufferSize) == ERROR_SUCCESS) {
  1026. SHExpandEnvironmentStrings (szValue, szExpValue, ARRAYSIZE(szExpValue));
  1027. SetUserEnvironmentVariable(&pEnv, COMMONPROGRAMFILES_VARIABLE, szExpValue, TRUE);
  1028. }
  1029. #if defined(WX86) || defined(_WIN64)
  1030. dwMaxBufferSize = sizeof(szValue);
  1031. if (SHQueryValueEx (hKey, TEXT("ProgramFilesDir (x86)"), NULL, &dwType,
  1032. (LPBYTE) szValue, &dwMaxBufferSize) == ERROR_SUCCESS) {
  1033. SHExpandEnvironmentStrings(szValue, szExpValue, ARRAYSIZE(szExpValue));
  1034. SetUserEnvironmentVariable(&pEnv, PROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  1035. }
  1036. dwMaxBufferSize = sizeof(szValue);
  1037. if (SHQueryValueEx (hKey, TEXT("CommonFilesDir (x86)"), NULL, &dwType,
  1038. (LPBYTE) szValue, &dwMaxBufferSize) == ERROR_SUCCESS) {
  1039. SHExpandEnvironmentStrings (szValue, szExpValue, ARRAYSIZE(szExpValue));
  1040. SetUserEnvironmentVariable(&pEnv, COMMONPROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  1041. }
  1042. #endif
  1043. RegCloseKey (hKey);
  1044. }
  1045. /*
  1046. * Set 16-bit apps environment variables by processing autoexec.bat
  1047. * User can turn this off and on via the registry.
  1048. */
  1049. //
  1050. // Set the default case, and open the key
  1051. //
  1052. lstrcpy (szParseAutoexec, PARSE_AUTOEXEC_DEFAULT);
  1053. if (RegCreateKeyEx (HKEY_CURRENT_USER, PARSE_AUTOEXEC_KEY, 0, 0,
  1054. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  1055. NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  1056. //
  1057. // Query the current value. If it doesn't exist, then add
  1058. // the entry for next time.
  1059. //
  1060. dwMaxBufferSize = sizeof (TCHAR) * MAX_PARSE_AUTOEXEC_BUFFER;
  1061. if (SHQueryValueEx (hKey, PARSE_AUTOEXEC_ENTRY, NULL, &dwType,
  1062. (LPBYTE) szParseAutoexec, &dwMaxBufferSize)
  1063. != ERROR_SUCCESS) {
  1064. //
  1065. // Set the default value
  1066. //
  1067. RegSetValueEx (hKey, PARSE_AUTOEXEC_ENTRY, 0, REG_SZ,
  1068. (LPBYTE) szParseAutoexec,
  1069. sizeof (TCHAR) * lstrlen (szParseAutoexec) + 1);
  1070. }
  1071. //
  1072. // Close key
  1073. //
  1074. RegCloseKey (hKey);
  1075. }
  1076. //
  1077. // Process the autoexec if appropriate
  1078. //
  1079. if (szParseAutoexec[0] == TEXT('1')) {
  1080. ProcessAutoexec(&pEnv, PATH_VARIABLE);
  1081. }
  1082. /*
  1083. * Set User environment variables.
  1084. */
  1085. SetEnvironmentVariables( &pEnv, USER_ENV_SUBKEY);
  1086. /*
  1087. * Set User volatile environment variables.
  1088. */
  1089. SetEnvironmentVariables( &pEnv, USER_VOLATILE_ENV_SUBKEY);
  1090. AppendNTPathWithAutoexecPath( &pEnv, PATH_VARIABLE, AUTOEXECPATH_VARIABLE);
  1091. if (bSetCurrentEnv) {
  1092. Status = RtlSetCurrentEnvironment( pEnv, &pPrevEnv);
  1093. if (!NT_SUCCESS(Status)) {
  1094. // RtlDestroyEnvironment(pEnv);
  1095. return(FALSE);
  1096. }
  1097. else {
  1098. RtlDestroyEnvironment(pPrevEnv);
  1099. }
  1100. }
  1101. //
  1102. //If it's not a session 0 we might need to change value of TMP/TEMP
  1103. //so they will be different for each session.
  1104. //
  1105. if(NtCurrentPeb()->SessionId)
  1106. {
  1107. SetPerSessionTempDir(&pEnv);
  1108. }
  1109. *pNewEnv = pEnv;
  1110. return(TRUE);
  1111. }