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.

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