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.

1955 lines
50 KiB

  1. //*************************************************************
  2. // File name: envvar.c
  3. //
  4. // Description: Contains the environment variable functions
  5. //
  6. //
  7. // Microsoft Confidential
  8. // Copyright (c) Microsoft Corporation 1996
  9. // All rights reserved
  10. //
  11. //*************************************************************
  12. #include "uenv.h"
  13. //
  14. // Max environment variable length
  15. //
  16. #define MAX_VALUE_LEN 1024
  17. //
  18. // Environment variables
  19. //
  20. #define COMPUTERNAME_VARIABLE TEXT("COMPUTERNAME")
  21. #define HOMEDRIVE_VARIABLE TEXT("HOMEDRIVE")
  22. #define HOMESHARE_VARIABLE TEXT("HOMESHARE")
  23. #define HOMEPATH_VARIABLE TEXT("HOMEPATH")
  24. #define SYSTEMDRIVE_VARIABLE TEXT("SystemDrive")
  25. #define SYSTEMROOT_VARIABLE TEXT("SystemRoot")
  26. #define USERNAME_VARIABLE TEXT("USERNAME")
  27. #define USERDOMAIN_VARIABLE TEXT("USERDOMAIN")
  28. #define USERDNSDOMAIN_VARIABLE TEXT("USERDNSDOMAIN")
  29. #define USERPROFILE_VARIABLE TEXT("USERPROFILE")
  30. #define ALLUSERSPROFILE_VARIABLE TEXT("ALLUSERSPROFILE")
  31. #define PATH_VARIABLE TEXT("Path")
  32. #define LIBPATH_VARIABLE TEXT("LibPath")
  33. #define OS2LIBPATH_VARIABLE TEXT("Os2LibPath")
  34. #define PROGRAMFILES_VARIABLE TEXT("ProgramFiles")
  35. #define COMMONPROGRAMFILES_VARIABLE TEXT("CommonProgramFiles")
  36. #if defined(WX86) || defined(_WIN64)
  37. #define PROGRAMFILESX86_VARIABLE TEXT("ProgramFiles(x86)")
  38. #define COMMONPROGRAMFILESX86_VARIABLE TEXT("CommonProgramFiles(x86)")
  39. #endif
  40. #define USER_ENV_SUBKEY TEXT("Environment")
  41. #define USER_VOLATILE_ENV_SUBKEY TEXT("Volatile Environment")
  42. //
  43. // Parsing information for autoexec.bat
  44. //
  45. #define AUTOEXECPATH_VARIABLE TEXT("AutoexecPath")
  46. #define PARSE_AUTOEXEC_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
  47. #define PARSE_AUTOEXEC_ENTRY TEXT("ParseAutoexec")
  48. #define PARSE_AUTOEXEC_DEFAULT TEXT("1")
  49. #define MAX_PARSE_AUTOEXEC_BUFFER 2
  50. #define SYS_ENVVARS TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment")
  51. BOOL UpdateSystemEnvironment(PVOID *pEnv);
  52. BOOL GetUserNameAndDomain(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain);
  53. BOOL GetUserNameAndDomainSlowly(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain);
  54. LPTSTR GetUserDNSDomainName(LPTSTR lpDomain, HANDLE hUserToken);
  55. LONG GetHKeyCU(HANDLE hToken, HKEY *hKeyCU);
  56. BOOL ProcessAutoexec(PVOID *pEnv);
  57. BOOL AppendNTPathWithAutoexecPath(PVOID *pEnv, LPTSTR lpPathVariable, LPTSTR lpAutoexecPath);
  58. BOOL SetEnvironmentVariables(PVOID *pEnv, LPTSTR lpRegSubKey, HKEY hKeyCU);
  59. #ifdef _X86_
  60. BOOL IsPathIncludeRemovable(LPTSTR lpValue);
  61. #endif
  62. //*************************************************************
  63. //
  64. // CreateEnvironmentBlock()
  65. //
  66. // Purpose: Creates the environment variables for the
  67. // specificed hToken. If hToken is NULL, the
  68. // environment block will only contain system
  69. // variables.
  70. //
  71. // Parameters: pEnv - Receives the environment block
  72. // hToken - User's token or NULL
  73. // bInherit - Inherit the current process environment
  74. //
  75. // Return: TRUE if successful
  76. // FALSE if not
  77. //
  78. // Comments: The pEnv value must be destroyed by
  79. // calling DestroyEnvironmentBlock
  80. //
  81. // History: Date Author Comment
  82. // 6/19/96 ericflo Created
  83. //
  84. //*************************************************************
  85. BOOL WINAPI CreateEnvironmentBlock (LPVOID *pEnv, HANDLE hToken, BOOL bInherit)
  86. {
  87. LPTSTR szBuffer = NULL;
  88. LPTSTR szValue = NULL;
  89. LPTSTR szExpValue = NULL;
  90. DWORD dwBufferSize = MAX_PATH+1;
  91. NTSTATUS Status;
  92. LPTSTR UserName = NULL;
  93. LPTSTR UserDomain = NULL;
  94. LPTSTR UserDNSDomain = NULL;
  95. HKEY hKey, hKeyCU;
  96. DWORD dwDisp, dwType, dwSize;
  97. TCHAR szParseAutoexec[MAX_PARSE_AUTOEXEC_BUFFER];
  98. LONG dwError;
  99. BOOL bRetVal = FALSE;
  100. //
  101. // Arg check
  102. //
  103. if (!pEnv) {
  104. SetLastError (ERROR_INVALID_PARAMETER);
  105. goto Exit;
  106. }
  107. Status = RtlCreateEnvironment((BOOLEAN)bInherit, pEnv);
  108. if (!NT_SUCCESS(Status)) {
  109. goto Exit;
  110. }
  111. //
  112. // Allocate memory for Local variables to avoid stack overflow
  113. //
  114. szBuffer = (LPTSTR)LocalAlloc(LPTR, (MAX_PATH+1)*sizeof(TCHAR));
  115. if (!szBuffer) {
  116. DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
  117. goto Exit;
  118. }
  119. szValue = (LPTSTR)LocalAlloc(LPTR, (MAX_VALUE_LEN+1)*sizeof(TCHAR));
  120. if (!szValue) {
  121. DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
  122. goto Exit;
  123. }
  124. szExpValue = (LPTSTR)LocalAlloc(LPTR, (MAX_VALUE_LEN+1)*sizeof(TCHAR));
  125. if (!szExpValue) {
  126. DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
  127. goto Exit;
  128. }
  129. //
  130. // First start by getting the systemroot and systemdrive values and
  131. // setting it in the new environment.
  132. //
  133. if ( GetEnvironmentVariable(SYSTEMROOT_VARIABLE, szBuffer, dwBufferSize) )
  134. {
  135. SetEnvironmentVariableInBlock(pEnv, SYSTEMROOT_VARIABLE, szBuffer, TRUE);
  136. }
  137. if ( GetEnvironmentVariable(SYSTEMDRIVE_VARIABLE, szBuffer, dwBufferSize) )
  138. {
  139. SetEnvironmentVariableInBlock(pEnv, SYSTEMDRIVE_VARIABLE, szBuffer, TRUE);
  140. }
  141. //
  142. // Set the all users profile location.
  143. //
  144. dwBufferSize = MAX_PATH+1;
  145. if (GetAllUsersProfileDirectory(szBuffer, &dwBufferSize)) {
  146. SetEnvironmentVariableInBlock(pEnv, ALLUSERSPROFILE_VARIABLE, szBuffer, TRUE);
  147. }
  148. //
  149. // We must examine the registry directly to pull out
  150. // the system environment variables, because they
  151. // may have changed since the system was booted.
  152. //
  153. if (!UpdateSystemEnvironment(pEnv)) {
  154. RtlDestroyEnvironment(*pEnv);
  155. goto Exit;
  156. }
  157. //
  158. // Set the computername
  159. //
  160. dwBufferSize = MAX_PATH+1;
  161. if (GetComputerName (szBuffer, &dwBufferSize)) {
  162. SetEnvironmentVariableInBlock(pEnv, COMPUTERNAME_VARIABLE, szBuffer, TRUE);
  163. }
  164. //
  165. // Set the default user profile location
  166. //
  167. dwBufferSize = MAX_PATH+1;
  168. if (GetDefaultUserProfileDirectory(szBuffer, &dwBufferSize)) {
  169. SetEnvironmentVariableInBlock(pEnv, USERPROFILE_VARIABLE, szBuffer, TRUE);
  170. }
  171. //
  172. // Set the Program Files environment variable
  173. //
  174. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion"),
  175. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  176. dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
  177. if (RegQueryValueEx (hKey, TEXT("ProgramFilesDir"), NULL, &dwType,
  178. (LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
  179. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1));
  180. SetEnvironmentVariableInBlock(pEnv, PROGRAMFILES_VARIABLE, szExpValue, TRUE);
  181. }
  182. dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
  183. if (RegQueryValueEx (hKey, TEXT("CommonFilesDir"), NULL, &dwType,
  184. (LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
  185. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1));
  186. SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILES_VARIABLE, szExpValue, TRUE);
  187. }
  188. #if defined(WX86) || defined(_WIN64)
  189. dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
  190. if (RegQueryValueEx (hKey, TEXT("ProgramFilesDir (x86)"), NULL, &dwType,
  191. (LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
  192. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1));
  193. SetEnvironmentVariableInBlock(pEnv, PROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  194. }
  195. dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
  196. if (RegQueryValueEx (hKey, TEXT("CommonFilesDir (x86)"), NULL, &dwType,
  197. (LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
  198. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1));
  199. SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  200. }
  201. #endif
  202. RegCloseKey (hKey);
  203. }
  204. //
  205. // If hToken is NULL, we can exit now since the caller only wants
  206. // system environment variables.
  207. //
  208. if (!hToken) {
  209. bRetVal = TRUE;
  210. goto Exit;
  211. }
  212. //
  213. // Open the HKEY_CURRENT_USER for this token.
  214. //
  215. dwError = GetHKeyCU(hToken, &hKeyCU);
  216. //
  217. // if the hive is not found assume that the caller just needs the system attribute.
  218. //
  219. if ((!hKeyCU) && (dwError == ERROR_FILE_NOT_FOUND)) {
  220. bRetVal = TRUE;
  221. goto Exit;
  222. }
  223. if (!hKeyCU) {
  224. RtlDestroyEnvironment(*pEnv);
  225. DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Failed to open HKEY_CURRENT_USER, error = %d"), dwError));
  226. goto Exit;
  227. }
  228. //
  229. // Set the user's name and domain.
  230. //
  231. if (!GetUserNameAndDomain(hToken, &UserName, &UserDomain)) {
  232. GetUserNameAndDomainSlowly(hToken, &UserName, &UserDomain);
  233. }
  234. UserDNSDomain = GetUserDNSDomainName(UserDomain, hToken);
  235. SetEnvironmentVariableInBlock( pEnv, USERNAME_VARIABLE, UserName, TRUE);
  236. SetEnvironmentVariableInBlock( pEnv, USERDOMAIN_VARIABLE, UserDomain, TRUE);
  237. SetEnvironmentVariableInBlock( pEnv, USERDNSDOMAIN_VARIABLE, UserDNSDomain, TRUE);
  238. LocalFree(UserName);
  239. LocalFree(UserDomain);
  240. LocalFree(UserDNSDomain);
  241. //
  242. // Set the user's profile location.
  243. //
  244. dwBufferSize = MAX_PATH+1;
  245. if (GetUserProfileDirectory(hToken, szBuffer, &dwBufferSize)) {
  246. SetEnvironmentVariableInBlock(pEnv, USERPROFILE_VARIABLE, szBuffer, TRUE);
  247. }
  248. //
  249. // Process autoexec.bat
  250. //
  251. lstrcpy (szParseAutoexec, PARSE_AUTOEXEC_DEFAULT);
  252. if (RegCreateKeyEx (hKeyCU, PARSE_AUTOEXEC_KEY, 0, 0,
  253. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  254. NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  255. //
  256. // Query the current value. If it doesn't exist, then add
  257. // the entry for next time.
  258. //
  259. dwBufferSize = sizeof (TCHAR) * MAX_PARSE_AUTOEXEC_BUFFER;
  260. if (RegQueryValueEx (hKey, PARSE_AUTOEXEC_ENTRY, NULL, &dwType,
  261. (LPBYTE) szParseAutoexec, &dwBufferSize)
  262. != ERROR_SUCCESS) {
  263. //
  264. // Set the default value
  265. //
  266. RegSetValueEx (hKey, PARSE_AUTOEXEC_ENTRY, 0, REG_SZ,
  267. (LPBYTE) szParseAutoexec,
  268. sizeof (TCHAR) * lstrlen (szParseAutoexec) + 1);
  269. }
  270. //
  271. // Close key
  272. //
  273. RegCloseKey (hKey);
  274. }
  275. //
  276. // Process autoexec if appropriate
  277. //
  278. if (szParseAutoexec[0] == TEXT('1')) {
  279. ProcessAutoexec(pEnv);
  280. }
  281. //
  282. // Set User environment variables.
  283. //
  284. SetEnvironmentVariables(pEnv, USER_ENV_SUBKEY, hKeyCU);
  285. //
  286. // Set User volatile environment variables.
  287. //
  288. SetEnvironmentVariables(pEnv, USER_VOLATILE_ENV_SUBKEY, hKeyCU);
  289. //
  290. // Merge the paths
  291. //
  292. AppendNTPathWithAutoexecPath(pEnv, PATH_VARIABLE, AUTOEXECPATH_VARIABLE);
  293. RegCloseKey (hKeyCU);
  294. bRetVal = TRUE;
  295. Exit:
  296. if (szBuffer) {
  297. LocalFree(szBuffer);
  298. }
  299. if (szValue) {
  300. LocalFree(szValue);
  301. }
  302. if (szExpValue) {
  303. LocalFree(szExpValue);
  304. }
  305. return bRetVal;
  306. }
  307. //*************************************************************
  308. //
  309. // DestroyEnvironmentBlock()
  310. //
  311. // Purpose: Frees the environment block created by
  312. // CreateEnvironmentBlock
  313. //
  314. // Parameters: lpEnvironment - Pointer to variables
  315. //
  316. // Return: TRUE if successful
  317. // FALSE if an error occurs
  318. //
  319. // Comments:
  320. //
  321. // History: Date Author Comment
  322. // 6/19/96 ericflo Created
  323. //
  324. //*************************************************************
  325. BOOL WINAPI DestroyEnvironmentBlock (LPVOID lpEnvironment)
  326. {
  327. if (!lpEnvironment) {
  328. SetLastError (ERROR_INVALID_PARAMETER);
  329. return FALSE;
  330. }
  331. RtlDestroyEnvironment(lpEnvironment);
  332. return TRUE;
  333. }
  334. //*************************************************************
  335. //
  336. // UpdateSystemEnvironment()
  337. //
  338. // Purpose: Reads the system environment variables from the
  339. // registry.
  340. //
  341. // Parameters: pEnv - Environment block pointer
  342. //
  343. // Return: TRUE if successful
  344. // FALSE if an error occurs
  345. //
  346. // Comments:
  347. //
  348. // History: Date Author Comment
  349. // 6/21/96 ericflo Ported
  350. //
  351. //*************************************************************
  352. BOOL UpdateSystemEnvironment(PVOID *pEnv)
  353. {
  354. HKEY KeyHandle;
  355. DWORD Result;
  356. DWORD ValueNameLength;
  357. DWORD Type;
  358. DWORD DataLength;
  359. DWORD cValues; /* address of buffer for number of value identifiers */
  360. DWORD chMaxValueName; /* address of buffer for longest value name length */
  361. DWORD cbMaxValueData; /* address of buffer for longest value data length */
  362. DWORD junk;
  363. FILETIME FileTime;
  364. PTCHAR ValueName;
  365. PTCHAR ValueData;
  366. DWORD i;
  367. BOOL Bool;
  368. PTCHAR ExpandedValue;
  369. BOOL rc = TRUE;
  370. DWORD ClassStringSize = MAX_PATH + 1;
  371. TCHAR Class[MAX_PATH + 1];
  372. Result = RegOpenKeyEx (
  373. HKEY_LOCAL_MACHINE,
  374. SYS_ENVVARS,
  375. 0,
  376. KEY_QUERY_VALUE,
  377. &KeyHandle
  378. );
  379. if ( Result != ERROR_SUCCESS ) {
  380. DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: RegOpenKeyEx failed, error = %d"),Result));
  381. return( TRUE );
  382. }
  383. Result = RegQueryInfoKey(
  384. KeyHandle,
  385. Class, /* address of buffer for class string */
  386. &ClassStringSize, /* address of size of class string buffer */
  387. NULL, /* reserved */
  388. &junk, /* address of buffer for number of subkeys */
  389. &junk, /* address of buffer for longest subkey */
  390. &junk, /* address of buffer for longest class string length */
  391. &cValues, /* address of buffer for number of value identifiers */
  392. &chMaxValueName, /* address of buffer for longest value name length */
  393. &cbMaxValueData, /* address of buffer for longest value data length */
  394. &junk, /* address of buffer for descriptor length */
  395. &FileTime /* address of buffer for last write time */
  396. );
  397. if ( Result != NO_ERROR && Result != ERROR_MORE_DATA ) {
  398. DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: RegQueryInfoKey failed, error = %d"),Result));
  399. RegCloseKey(KeyHandle);
  400. return( TRUE );
  401. }
  402. //
  403. // No need to adjust the datalength for TCHAR issues
  404. //
  405. ValueData = LocalAlloc(LPTR, cbMaxValueData);
  406. if ( ValueData == NULL ) {
  407. RegCloseKey(KeyHandle);
  408. return( FALSE );
  409. }
  410. //
  411. // The maximum value name length comes back in characters, convert to bytes
  412. // before allocating storage. Allow for trailing NULL also.
  413. //
  414. ValueName = LocalAlloc(LPTR, (++chMaxValueName) * sizeof( TCHAR ) );
  415. if ( ValueName == NULL ) {
  416. RegCloseKey(KeyHandle);
  417. LocalFree( ValueData );
  418. return( FALSE );
  419. }
  420. //
  421. // To exit from here on, set rc and jump to Cleanup
  422. //
  423. for (i=0; i<cValues ; i++) {
  424. ValueNameLength = chMaxValueName;
  425. DataLength = cbMaxValueData;
  426. Result = RegEnumValue (
  427. KeyHandle,
  428. i,
  429. ValueName,
  430. &ValueNameLength, // Size in TCHARs
  431. NULL,
  432. &Type,
  433. (LPBYTE)ValueData,
  434. &DataLength // Size in bytes
  435. );
  436. if ( Result != ERROR_SUCCESS ) {
  437. //
  438. // Problem getting the value. We can either try
  439. // the rest or punt completely.
  440. //
  441. goto Cleanup;
  442. }
  443. //
  444. // If the buffer size is greater than the max allowed,
  445. // terminate the string at MAX_VALUE_LEN - 1.
  446. //
  447. if (DataLength >= (MAX_VALUE_LEN * sizeof(TCHAR))) {
  448. ValueData[MAX_VALUE_LEN-1] = TEXT('\0');
  449. }
  450. switch ( Type ) {
  451. case REG_SZ:
  452. {
  453. Bool = SetEnvironmentVariableInBlock(
  454. pEnv,
  455. ValueName,
  456. ValueData,
  457. TRUE
  458. );
  459. if ( !Bool ) {
  460. DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: Failed to set environment variable <%s> to <%s> with %d."),
  461. ValueName, ValueData, GetLastError()));
  462. }
  463. break;
  464. }
  465. default:
  466. {
  467. continue;
  468. }
  469. }
  470. }
  471. //
  472. // To exit from here on, set rc and jump to Cleanup
  473. //
  474. for (i=0; i<cValues ; i++) {
  475. ValueNameLength = chMaxValueName;
  476. DataLength = cbMaxValueData;
  477. Result = RegEnumValue (
  478. KeyHandle,
  479. i,
  480. ValueName,
  481. &ValueNameLength, // Size in TCHARs
  482. NULL,
  483. &Type,
  484. (LPBYTE)ValueData,
  485. &DataLength // Size in bytes
  486. );
  487. if ( Result != ERROR_SUCCESS ) {
  488. //
  489. // Problem getting the value. We can either try
  490. // the rest or punt completely.
  491. //
  492. goto Cleanup;
  493. }
  494. //
  495. // If the buffer size is greater than the max allowed,
  496. // terminate the string at MAX_VALUE_LEN - 1.
  497. //
  498. if (DataLength >= (MAX_VALUE_LEN * sizeof(TCHAR))) {
  499. ValueData[MAX_VALUE_LEN-1] = TEXT('\0');
  500. }
  501. switch ( Type ) {
  502. case REG_EXPAND_SZ:
  503. {
  504. ExpandedValue = AllocAndExpandEnvironmentStrings( ValueData );
  505. Bool = SetEnvironmentVariableInBlock(
  506. pEnv,
  507. ValueName,
  508. ExpandedValue,
  509. TRUE
  510. );
  511. LocalFree( ExpandedValue );
  512. if ( !Bool ) {
  513. DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: Failed to set environment variable <%s> to <%s> with %d."),
  514. ValueName, ValueData, GetLastError()));
  515. }
  516. break;
  517. }
  518. default:
  519. {
  520. continue;
  521. }
  522. }
  523. }
  524. Cleanup:
  525. RegCloseKey(KeyHandle);
  526. LocalFree( ValueName );
  527. LocalFree( ValueData );
  528. return( rc );
  529. }
  530. //*************************************************************
  531. //
  532. // GetUserNameAndDomain()
  533. //
  534. // Purpose: Gets the user's name and domain
  535. //
  536. // Parameters: hToken - User's token
  537. // UserName - Receives pointer to user's name
  538. // UserDomain - Receives pointer to user's domain
  539. //
  540. // Return: TRUE if successful
  541. // FALSE if an error occurs
  542. //
  543. // Comments:
  544. //
  545. // History: Date Author Comment
  546. // 6/21/96 ericflo Ported
  547. //
  548. //*************************************************************
  549. BOOL GetUserNameAndDomain(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain)
  550. {
  551. BOOL bResult = FALSE;
  552. LPTSTR lpTemp, lpDomain = NULL;
  553. LPTSTR lpUserName, lpUserDomain;
  554. HANDLE hOldToken;
  555. //
  556. // Impersonate the user
  557. //
  558. if (!ImpersonateUser(hToken, &hOldToken)) {
  559. DebugMsg((DM_VERBOSE, TEXT("GetUserNameAndDomain Failed to impersonate user")));
  560. goto Exit;
  561. }
  562. //
  563. // Get the username in NT4 format
  564. //
  565. lpDomain = MyGetUserNameEx (NameSamCompatible);
  566. RevertToUser(&hOldToken);
  567. if (!lpDomain) {
  568. DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain: MyGetUserNameEx failed for NT4 style name with %d"),
  569. GetLastError()));
  570. goto Exit;
  571. }
  572. //
  573. // Look for the \ between the domain and username and replace
  574. // it with a NULL
  575. //
  576. lpTemp = lpDomain;
  577. while (*lpTemp && ((*lpTemp) != TEXT('\\')))
  578. lpTemp++;
  579. if (*lpTemp != TEXT('\\')) {
  580. DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to find slash in NT4 style name: <%s>"),
  581. lpDomain));
  582. goto Exit;
  583. }
  584. *lpTemp = TEXT('\0');
  585. lpTemp++;
  586. //
  587. // Allocate space for the results
  588. //
  589. lpUserName = LocalAlloc (LPTR, (lstrlen(lpTemp) + 1) * sizeof(TCHAR));
  590. if (!lpUserName) {
  591. DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to allocate memory with %d"),
  592. GetLastError()));
  593. goto Exit;
  594. }
  595. lstrcpy (lpUserName, lpTemp);
  596. lpUserDomain = LocalAlloc (LPTR, (lstrlen(lpDomain) + 1) * sizeof(TCHAR));
  597. if (!lpUserDomain) {
  598. DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to allocate memory with %d"),
  599. GetLastError()));
  600. LocalFree (lpUserName);
  601. goto Exit;
  602. }
  603. lstrcpy (lpUserDomain, lpDomain);
  604. //
  605. // Save the results in the outbound arguments
  606. //
  607. *UserName = lpUserName;
  608. *UserDomain = lpUserDomain;
  609. //
  610. // Success
  611. //
  612. bResult = TRUE;
  613. Exit:
  614. if (lpDomain) {
  615. LocalFree (lpDomain);
  616. }
  617. return(bResult);
  618. }
  619. //*************************************************************
  620. //
  621. // GetUserNameAndDomainSlowly()
  622. //
  623. // Purpose: Gets the user's name and domain from a DC
  624. //
  625. // Parameters: hToken - User's token
  626. // UserName - Receives pointer to user's name
  627. // UserDomain - Receives pointer to user's domain
  628. //
  629. // Return: TRUE if successful
  630. // FALSE if an error occurs
  631. //
  632. // Comments:
  633. //
  634. // History: Date Author Comment
  635. // 6/21/96 ericflo Ported
  636. //
  637. //*************************************************************
  638. BOOL GetUserNameAndDomainSlowly(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain)
  639. {
  640. LPTSTR lpUserName = NULL;
  641. LPTSTR lpUserDomain = NULL;
  642. DWORD cbAccountName = 0;
  643. DWORD cbUserDomain = 0;
  644. SID_NAME_USE SidNameUse;
  645. BOOL bRet = FALSE;
  646. PSID pSid;
  647. //
  648. // Get the user's sid
  649. //
  650. pSid = GetUserSid (hToken);
  651. if (!pSid) {
  652. return FALSE;
  653. }
  654. //
  655. // Get the space needed for the User name and the Domain name
  656. //
  657. if (!LookupAccountSid(NULL,
  658. pSid,
  659. NULL, &cbAccountName,
  660. NULL, &cbUserDomain,
  661. &SidNameUse
  662. ) ) {
  663. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  664. goto Error;
  665. }
  666. }
  667. lpUserName = (LPTSTR)LocalAlloc(LPTR, cbAccountName*sizeof(TCHAR));
  668. if (!lpUserName) {
  669. goto Error;
  670. }
  671. lpUserDomain = (LPTSTR)LocalAlloc(LPTR, cbUserDomain*sizeof(WCHAR));
  672. if (!lpUserDomain) {
  673. LocalFree(lpUserName);
  674. goto Error;
  675. }
  676. //
  677. // Now get the user name and domain name
  678. //
  679. if (!LookupAccountSid(NULL,
  680. pSid,
  681. lpUserName, &cbAccountName,
  682. lpUserDomain, &cbUserDomain,
  683. &SidNameUse
  684. ) ) {
  685. LocalFree(lpUserName);
  686. LocalFree(lpUserDomain);
  687. goto Error;
  688. }
  689. *UserName = lpUserName;
  690. *UserDomain = lpUserDomain;
  691. bRet = TRUE;
  692. Error:
  693. DeleteUserSid (pSid);
  694. return(bRet);
  695. }
  696. //*************************************************************
  697. //
  698. // GetUserDNSDomainName()
  699. //
  700. // Purpose: Gets the DNS domain name for the user
  701. //
  702. // Parameters: lpDomain - User's flat domain name
  703. // hUserToken - User's token
  704. //
  705. //
  706. // Return: DNS domain name if successful
  707. // NULL if an error occurs
  708. //
  709. //*************************************************************
  710. LPTSTR GetUserDNSDomainName(LPTSTR lpDomain, HANDLE hUserToken)
  711. {
  712. LPTSTR lpDnsDomain = NULL, lpTemp = NULL;
  713. DWORD dwBufferSize;
  714. TCHAR szBuffer[MAX_PATH];
  715. INT iRole;
  716. HANDLE hOldToken;
  717. BOOL bResult = FALSE;
  718. //
  719. // Check if this machine is running standalone, if so, there won't be
  720. // a DNS domain name
  721. //
  722. if (!GetMachineRole (&iRole)) {
  723. DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: Failed to get the role of the computer.")));
  724. return NULL;
  725. }
  726. if (iRole == 0) {
  727. DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Computer is running standalone. No DNS domain name available.")));
  728. return NULL;
  729. }
  730. //
  731. // Get the computer name to see if the user logged on locally
  732. //
  733. dwBufferSize = ARRAYSIZE(szBuffer);
  734. if (GetComputerName (szBuffer, &dwBufferSize)) {
  735. if (!lstrcmpi(lpDomain, szBuffer)) {
  736. DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Local user account. No DNS domain name available.")));
  737. return NULL;
  738. }
  739. }
  740. if (LoadString (g_hDllInstance, IDS_NT_AUTHORITY, szBuffer, ARRAYSIZE(szBuffer))) {
  741. if (!lstrcmpi(lpDomain, szBuffer)) {
  742. DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Domain name is NT Authority. No DNS domain name available.")));
  743. return NULL;
  744. }
  745. }
  746. if (LoadString (g_hDllInstance, IDS_BUILTIN, szBuffer, ARRAYSIZE(szBuffer))) {
  747. if (!lstrcmpi(lpDomain, szBuffer)) {
  748. DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Domain name is BuiltIn. No DNS domain name available.")));
  749. return NULL;
  750. }
  751. }
  752. //
  753. // Impersonate the user
  754. //
  755. if (!ImpersonateUser(hUserToken, &hOldToken)) {
  756. DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Failed to impersonate user")));
  757. goto Exit;
  758. }
  759. //
  760. // Get the username in DnsDomainName format
  761. //
  762. lpDnsDomain = MyGetUserNameEx (NameDnsDomain);
  763. RevertToUser(&hOldToken);
  764. if (!lpDnsDomain) {
  765. DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: MyGetUserNameEx failed for NameDnsDomain style name with %d"),
  766. GetLastError()));
  767. goto Exit;
  768. }
  769. //
  770. // Look for the \ between the domain and username and replace
  771. // it with a NULL
  772. //
  773. lpTemp = lpDnsDomain;
  774. while (*lpTemp && (*lpTemp != TEXT('\\')))
  775. lpTemp++;
  776. if (*lpTemp != TEXT('\\')) {
  777. DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: Failed to find slash in NameDnsDomain style name: <%s>"),
  778. lpDnsDomain));
  779. goto Exit;
  780. }
  781. *lpTemp = TEXT('\0');
  782. bResult = TRUE;
  783. Exit:
  784. if (!bResult && lpDnsDomain) {
  785. LocalFree(lpDnsDomain);
  786. lpDnsDomain = NULL;
  787. }
  788. return lpDnsDomain;
  789. }
  790. //*************************************************************
  791. //
  792. // GetHKeyCU()
  793. //
  794. // Purpose: Get HKEY_CURRENT_USER for the given hToken
  795. //
  796. // Parameters: hToken - token handle
  797. //
  798. // Return: hKey if successful
  799. // NULL if an error occurs
  800. //
  801. // Comments:
  802. //
  803. // History: Date Author Comment
  804. // 6/21/96 ericflo Created
  805. //
  806. //*************************************************************
  807. LONG GetHKeyCU(HANDLE hToken, HKEY *hKeyCU)
  808. {
  809. LPTSTR lpSidString;
  810. LONG dwError;
  811. *hKeyCU = NULL;
  812. lpSidString = GetSidString (hToken);
  813. if (!lpSidString) {
  814. return GetLastError();
  815. }
  816. dwError = RegOpenKeyEx (HKEY_USERS, lpSidString, 0, KEY_READ, hKeyCU);
  817. if (!(*hKeyCU))
  818. DebugMsg((DM_VERBOSE, TEXT("GetHkeyCU: RegOpenKey failed with error %d"), dwError));
  819. DeleteSidString(lpSidString);
  820. return dwError;
  821. }
  822. /***************************************************************************\
  823. * ProcessAutoexecPath
  824. *
  825. * Creates AutoexecPath environment variable using autoexec.bat
  826. * LpValue may be freed by this routine.
  827. *
  828. * History:
  829. * 06-02-92 Johannec Created.
  830. *
  831. \***************************************************************************/
  832. LPTSTR ProcessAutoexecPath(PVOID pEnv, LPTSTR lpValue, DWORD cb)
  833. {
  834. LPTSTR lpt;
  835. LPTSTR lpStart;
  836. LPTSTR lpPath;
  837. DWORD cbt;
  838. UNICODE_STRING Name;
  839. UNICODE_STRING Value;
  840. BOOL bPrevAutoexecPath;
  841. WCHAR ch;
  842. DWORD dwTemp, dwCount = 0;
  843. cbt = 1024;
  844. lpt = (LPTSTR)LocalAlloc(LPTR, cbt*sizeof(WCHAR));
  845. if (!lpt) {
  846. return(lpValue);
  847. }
  848. *lpt = 0;
  849. lpStart = lpValue;
  850. RtlInitUnicodeString(&Name, AUTOEXECPATH_VARIABLE);
  851. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cbt*sizeof(WCHAR));
  852. if (!Value.Buffer) {
  853. goto Fail;
  854. }
  855. while (NULL != (lpPath = wcsstr (lpValue, TEXT("%")))) {
  856. if (!_wcsnicmp(lpPath+1, TEXT("PATH%"), 5)) {
  857. //
  858. // check if we have an autoexecpath already set, if not just remove
  859. // the %path%
  860. //
  861. Value.Length = (USHORT)cbt;
  862. Value.MaximumLength = (USHORT)cbt;
  863. bPrevAutoexecPath = (BOOL)!RtlQueryEnvironmentVariable_U(pEnv, &Name, &Value);
  864. *lpPath = 0;
  865. dwTemp = dwCount + lstrlen (lpValue);
  866. if (dwTemp < cbt) {
  867. lstrcat(lpt, lpValue);
  868. dwCount = dwTemp;
  869. }
  870. if (bPrevAutoexecPath) {
  871. dwTemp = dwCount + lstrlen (Value.Buffer);
  872. if (dwTemp < cbt) {
  873. lstrcat(lpt, Value.Buffer);
  874. dwCount = dwTemp;
  875. }
  876. }
  877. *lpPath++ = TEXT('%');
  878. lpPath += 5; // go passed %path%
  879. lpValue = lpPath;
  880. }
  881. else {
  882. lpPath = wcsstr(lpPath+1, TEXT("%"));
  883. if (!lpPath) {
  884. lpStart = NULL;
  885. goto Fail;
  886. }
  887. lpPath++;
  888. ch = *lpPath;
  889. *lpPath = 0;
  890. dwTemp = dwCount + lstrlen (lpValue);
  891. if (dwTemp < cbt) {
  892. lstrcat(lpt, lpValue);
  893. dwCount = dwTemp;
  894. }
  895. *lpPath = ch;
  896. lpValue = lpPath;
  897. }
  898. }
  899. if (*lpValue) {
  900. dwTemp = dwCount + lstrlen (lpValue);
  901. if (dwTemp < cbt) {
  902. lstrcat(lpt, lpValue);
  903. dwCount = dwTemp;
  904. }
  905. }
  906. LocalFree(Value.Buffer);
  907. LocalFree(lpStart);
  908. return(lpt);
  909. Fail:
  910. LocalFree(lpt);
  911. return(lpStart);
  912. }
  913. /***************************************************************************\
  914. * ProcessCommand
  915. *
  916. * History:
  917. * 01-24-92 Johannec Created.
  918. *
  919. \***************************************************************************/
  920. BOOL ProcessCommand(LPSTR lpStart, PVOID *pEnv)
  921. {
  922. LPTSTR lpt, lptt;
  923. LPTSTR lpVariable;
  924. LPTSTR lpValue;
  925. LPTSTR lpExpandedValue = NULL;
  926. WCHAR c;
  927. DWORD cb, cbNeeded;
  928. LPTSTR lpu;
  929. //
  930. // convert to Unicode
  931. //
  932. lpu = (LPTSTR)LocalAlloc(LPTR, (cb=lstrlenA(lpStart)+1)*sizeof(WCHAR));
  933. if (!lpu) {
  934. return FALSE;
  935. }
  936. MultiByteToWideChar(CP_OEMCP, 0, lpStart, -1, lpu, cb);
  937. //
  938. // Find environment variable.
  939. //
  940. for (lpt = lpu; *lpt && *lpt == TEXT(' '); lpt++) //skip spaces
  941. ;
  942. if (!*lpt) {
  943. LocalFree (lpu);
  944. return(FALSE);
  945. }
  946. lptt = lpt;
  947. for (; *lpt && *lpt != TEXT(' ') && *lpt != TEXT('='); lpt++) //find end of variable name
  948. ;
  949. c = *lpt;
  950. *lpt = 0;
  951. lpVariable = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lptt) + 1)*sizeof(WCHAR));
  952. if (!lpVariable) {
  953. LocalFree (lpu);
  954. return(FALSE);
  955. }
  956. lstrcpy(lpVariable, lptt);
  957. *lpt = c;
  958. //
  959. // Find environment variable value.
  960. //
  961. for (; *lpt && (*lpt == TEXT(' ') || *lpt == TEXT('=')); lpt++)
  962. ;
  963. if (!*lpt) {
  964. // if we have a blank path statement in the autoexec file,
  965. // then we don't want to pass "PATH" as the environment
  966. // variable because it trashes the system's PATH. Instead
  967. // we want to change the variable AutoexecPath. This would have
  968. // be handled below if a value had been assigned to the
  969. // environment variable.
  970. if (lstrcmpi(lpVariable, PATH_VARIABLE) == 0)
  971. {
  972. SetEnvironmentVariableInBlock(pEnv, AUTOEXECPATH_VARIABLE, TEXT(""), TRUE);
  973. }
  974. else
  975. {
  976. SetEnvironmentVariableInBlock(pEnv, lpVariable, TEXT(""), TRUE);
  977. }
  978. LocalFree (lpVariable);
  979. LocalFree (lpu);
  980. return(FALSE);
  981. }
  982. lptt = lpt;
  983. for (; *lpt; lpt++) //find end of varaible value
  984. ;
  985. c = *lpt;
  986. *lpt = 0;
  987. lpValue = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lptt) + 1)*sizeof(WCHAR));
  988. if (!lpValue) {
  989. LocalFree (lpu);
  990. LocalFree(lpVariable);
  991. return(FALSE);
  992. }
  993. lstrcpy(lpValue, lptt);
  994. *lpt = c;
  995. #ifdef _X86_
  996. // NEC98
  997. //
  998. // If the path includes removable drive,
  999. // it is assumed that the drive assignment has changed from DOS.
  1000. //
  1001. if (IsNEC_98 && (lstrcmpi(lpVariable, PATH_VARIABLE) == 0) && IsPathIncludeRemovable(lpValue)) {
  1002. LocalFree (lpu);
  1003. LocalFree(lpVariable);
  1004. LocalFree(lpValue);
  1005. return(FALSE);
  1006. }
  1007. #endif
  1008. cb = 1024;
  1009. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1010. if (lpExpandedValue) {
  1011. if (!lstrcmpi(lpVariable, PATH_VARIABLE)) {
  1012. lpValue = ProcessAutoexecPath(*pEnv, lpValue, (lstrlen(lpValue)+1)*sizeof(WCHAR));
  1013. }
  1014. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  1015. if (cbNeeded > cb) {
  1016. LocalFree(lpExpandedValue);
  1017. cb = cbNeeded;
  1018. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1019. if (lpExpandedValue) {
  1020. ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cb);
  1021. }
  1022. }
  1023. }
  1024. if (!lpExpandedValue) {
  1025. lpExpandedValue = lpValue;
  1026. }
  1027. if (lstrcmpi(lpVariable, PATH_VARIABLE)) {
  1028. SetEnvironmentVariableInBlock(pEnv, lpVariable, lpExpandedValue, FALSE);
  1029. }
  1030. else {
  1031. SetEnvironmentVariableInBlock(pEnv, AUTOEXECPATH_VARIABLE, lpExpandedValue, TRUE);
  1032. }
  1033. if (lpExpandedValue != lpValue) {
  1034. LocalFree(lpExpandedValue);
  1035. }
  1036. LocalFree(lpVariable);
  1037. LocalFree(lpValue);
  1038. LocalFree (lpu);
  1039. return(TRUE);
  1040. }
  1041. /***************************************************************************\
  1042. * ProcessSetCommand
  1043. *
  1044. * History:
  1045. * 01-24-92 Johannec Created.
  1046. *
  1047. \***************************************************************************/
  1048. BOOL ProcessSetCommand(LPSTR lpStart, PVOID *pEnv)
  1049. {
  1050. LPSTR lpt;
  1051. //
  1052. // Find environment variable.
  1053. //
  1054. for (lpt = lpStart; *lpt && *lpt != TEXT(' '); lpt++)
  1055. ;
  1056. if (!*lpt)
  1057. return(FALSE);
  1058. return (ProcessCommand(lpt, pEnv));
  1059. }
  1060. /***************************************************************************\
  1061. * ProcessAutoexec
  1062. *
  1063. * History:
  1064. * 01-24-92 Johannec Created.
  1065. *
  1066. \***************************************************************************/
  1067. BOOL
  1068. ProcessAutoexec(
  1069. PVOID *pEnv
  1070. )
  1071. {
  1072. HANDLE fh = NULL;
  1073. DWORD dwFileSize;
  1074. DWORD dwBytesRead;
  1075. CHAR *lpBuffer = NULL;
  1076. CHAR *token;
  1077. CHAR Seps[] = "&\n\r"; // Seperators for tokenizing autoexec.bat
  1078. BOOL Status = FALSE;
  1079. TCHAR szAutoExecBat [] = TEXT("c:\\autoexec.bat");
  1080. #ifdef _X86_
  1081. TCHAR szTemp[3];
  1082. #endif
  1083. UINT uiErrMode;
  1084. // There is a case where the OS might not be booting from drive
  1085. // C, so we can not assume that the autoexec.bat file is on c:\.
  1086. // Set the error mode so the user doesn't see the critical error
  1087. // popup and attempt to open the file on c:\.
  1088. uiErrMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  1089. #ifdef _X86_
  1090. if (IsNEC_98) {
  1091. if (GetEnvironmentVariable (TEXT("SystemDrive"), szTemp, 3)) {
  1092. szAutoExecBat[0] = szTemp[0];
  1093. }
  1094. }
  1095. #endif
  1096. // if autoexec.bat is encrypted then ignore it as it creates cyclic-dependency
  1097. // and don't allow any user to logon
  1098. if (GetFileAttributes(szAutoExecBat) & FILE_ATTRIBUTE_ENCRYPTED) {
  1099. goto Exit;
  1100. }
  1101. fh = CreateFile (szAutoExecBat, GENERIC_READ, FILE_SHARE_READ,
  1102. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1103. SetErrorMode (uiErrMode);
  1104. if (fh == INVALID_HANDLE_VALUE) {
  1105. return(FALSE); //could not open autoexec.bat file, we're done.
  1106. }
  1107. dwFileSize = GetFileSize(fh, NULL);
  1108. if (dwFileSize == -1) {
  1109. goto Exit; // can't read the file size
  1110. }
  1111. lpBuffer = (PCHAR)LocalAlloc(LPTR, dwFileSize+1);
  1112. if (!lpBuffer) {
  1113. goto Exit;
  1114. }
  1115. Status = ReadFile(fh, lpBuffer, dwFileSize, &dwBytesRead, NULL);
  1116. if (!Status) {
  1117. goto Exit; // error reading file
  1118. }
  1119. //
  1120. // Zero terminate the buffer so we don't walk off the end
  1121. //
  1122. ASSERT(dwBytesRead <= dwFileSize);
  1123. lpBuffer[dwBytesRead] = 0;
  1124. //
  1125. // Search for SET and PATH commands
  1126. //
  1127. token = strtok(lpBuffer, Seps);
  1128. while (token != NULL) {
  1129. for (;*token && *token == ' ';token++) //skip spaces
  1130. ;
  1131. if (*token == TEXT('@'))
  1132. token++;
  1133. for (;*token && *token == ' ';token++) //skip spaces
  1134. ;
  1135. if (!_strnicmp(token, "Path", 4)) {
  1136. ProcessCommand(token, pEnv);
  1137. }
  1138. if (!_strnicmp(token, "SET", 3)) {
  1139. ProcessSetCommand(token, pEnv);
  1140. }
  1141. token = strtok(NULL, Seps);
  1142. }
  1143. Exit:
  1144. if (fh) {
  1145. CloseHandle(fh);
  1146. }
  1147. if (lpBuffer) {
  1148. LocalFree(lpBuffer);
  1149. }
  1150. if (!Status) {
  1151. DebugMsg((DM_WARNING, TEXT("ProcessAutoexec: Cannot process autoexec.bat.")));
  1152. }
  1153. return(Status);
  1154. }
  1155. /***************************************************************************\
  1156. * BuildEnvironmentPath
  1157. *
  1158. *
  1159. * History:
  1160. * 2-28-92 Johannec Created
  1161. *
  1162. \***************************************************************************/
  1163. BOOL BuildEnvironmentPath(PVOID *pEnv,
  1164. LPTSTR lpPathVariable,
  1165. LPTSTR lpPathValue)
  1166. {
  1167. NTSTATUS Status;
  1168. UNICODE_STRING Name;
  1169. UNICODE_STRING Value;
  1170. WCHAR lpTemp[1025];
  1171. DWORD cb;
  1172. if (!*pEnv) {
  1173. return(FALSE);
  1174. }
  1175. RtlInitUnicodeString(&Name, lpPathVariable);
  1176. cb = 1024;
  1177. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1178. if (!Value.Buffer) {
  1179. return(FALSE);
  1180. }
  1181. Value.Length = (USHORT)(sizeof(WCHAR) * cb);
  1182. Value.MaximumLength = (USHORT)(sizeof(WCHAR) * cb);
  1183. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  1184. if (!NT_SUCCESS(Status)) {
  1185. LocalFree(Value.Buffer);
  1186. Value.Length = 0;
  1187. *lpTemp = 0;
  1188. }
  1189. if (Value.Length) {
  1190. lstrcpy(lpTemp, Value.Buffer);
  1191. if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') ) {
  1192. lstrcat(lpTemp, TEXT(";"));
  1193. }
  1194. LocalFree(Value.Buffer);
  1195. }
  1196. if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb)) {
  1197. lstrcat(lpTemp, lpPathValue);
  1198. RtlInitUnicodeString(&Value, lpTemp);
  1199. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  1200. }
  1201. if (NT_SUCCESS(Status)) {
  1202. return(TRUE);
  1203. }
  1204. return(FALSE);
  1205. }
  1206. /***************************************************************************\
  1207. * AppendNTPathWithAutoexecPath
  1208. *
  1209. * Gets the AutoexecPath created in ProcessAutoexec, and appends it to
  1210. * the NT path.
  1211. *
  1212. * History:
  1213. * 05-28-92 Johannec Created.
  1214. *
  1215. \***************************************************************************/
  1216. BOOL
  1217. AppendNTPathWithAutoexecPath(
  1218. PVOID *pEnv,
  1219. LPTSTR lpPathVariable,
  1220. LPTSTR lpAutoexecPath
  1221. )
  1222. {
  1223. NTSTATUS Status;
  1224. UNICODE_STRING Name;
  1225. UNICODE_STRING Value;
  1226. WCHAR AutoexecPathValue[1024];
  1227. DWORD cb;
  1228. BOOL Success;
  1229. if (!*pEnv) {
  1230. return(FALSE);
  1231. }
  1232. RtlInitUnicodeString(&Name, lpAutoexecPath);
  1233. cb = 1024;
  1234. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1235. if (!Value.Buffer) {
  1236. return(FALSE);
  1237. }
  1238. Value.Length = (USHORT)cb;
  1239. Value.MaximumLength = (USHORT)cb;
  1240. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  1241. if (!NT_SUCCESS(Status)) {
  1242. LocalFree(Value.Buffer);
  1243. return(FALSE);
  1244. }
  1245. if (Value.Length) {
  1246. lstrcpy(AutoexecPathValue, Value.Buffer);
  1247. }
  1248. LocalFree(Value.Buffer);
  1249. Success = BuildEnvironmentPath(pEnv, lpPathVariable, AutoexecPathValue);
  1250. RtlSetEnvironmentVariable( pEnv, &Name, NULL);
  1251. return(Success);
  1252. }
  1253. /***************************************************************************\
  1254. * SetEnvironmentVariables
  1255. *
  1256. * Reads the user-defined environment variables from the user registry
  1257. * and adds them to the environment block at pEnv.
  1258. *
  1259. * History:
  1260. * 2-28-92 Johannec Created
  1261. *
  1262. \***************************************************************************/
  1263. BOOL
  1264. SetEnvironmentVariables(
  1265. PVOID *pEnv,
  1266. LPTSTR lpRegSubKey,
  1267. HKEY hKeyCU
  1268. )
  1269. {
  1270. WCHAR lpValueName[MAX_PATH];
  1271. LPBYTE lpDataBuffer;
  1272. DWORD cbDataBuffer;
  1273. LPBYTE lpData;
  1274. LPTSTR lpExpandedValue = NULL;
  1275. DWORD cbValueName = MAX_PATH;
  1276. DWORD cbData;
  1277. DWORD dwType;
  1278. DWORD dwIndex = 0;
  1279. HKEY hkey;
  1280. BOOL bResult;
  1281. if (RegOpenKeyExW(hKeyCU, lpRegSubKey, 0, KEY_READ, &hkey)) {
  1282. return(FALSE);
  1283. }
  1284. cbDataBuffer = 4096;
  1285. lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cbDataBuffer*sizeof(WCHAR));
  1286. if (lpDataBuffer == NULL) {
  1287. RegCloseKey(hkey);
  1288. return(FALSE);
  1289. }
  1290. lpData = lpDataBuffer;
  1291. cbData = cbDataBuffer;
  1292. bResult = TRUE;
  1293. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  1294. lpData, &cbData)) {
  1295. if (cbValueName) {
  1296. //
  1297. // Limit environment variable length
  1298. //
  1299. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  1300. if (dwType == REG_SZ) {
  1301. //
  1302. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  1303. // their values apppended to the system path.
  1304. //
  1305. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  1306. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  1307. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  1308. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpData);
  1309. }
  1310. else {
  1311. //
  1312. // the other environment variables are just set.
  1313. //
  1314. SetEnvironmentVariableInBlock(pEnv, lpValueName, (LPTSTR)lpData, TRUE);
  1315. }
  1316. }
  1317. }
  1318. dwIndex++;
  1319. cbData = cbDataBuffer;
  1320. cbValueName = MAX_PATH;
  1321. }
  1322. dwIndex = 0;
  1323. cbData = cbDataBuffer;
  1324. cbValueName = MAX_PATH;
  1325. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  1326. lpData, &cbData)) {
  1327. if (cbValueName) {
  1328. //
  1329. // Limit environment variable length
  1330. //
  1331. lpData[MAX_VALUE_LEN-1] = TEXT('\0');
  1332. if (dwType == REG_EXPAND_SZ) {
  1333. DWORD cb, cbNeeded;
  1334. cb = 1024;
  1335. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1336. if (lpExpandedValue) {
  1337. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  1338. if (cbNeeded > cb) {
  1339. LocalFree(lpExpandedValue);
  1340. cb = cbNeeded;
  1341. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  1342. if (lpExpandedValue) {
  1343. ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  1344. }
  1345. }
  1346. }
  1347. if (lpExpandedValue == NULL) {
  1348. bResult = FALSE;
  1349. break;
  1350. }
  1351. //
  1352. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  1353. // their values apppended to the system path.
  1354. //
  1355. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  1356. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  1357. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  1358. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpExpandedValue);
  1359. }
  1360. else {
  1361. //
  1362. // the other environment variables are just set.
  1363. //
  1364. SetEnvironmentVariableInBlock(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE);
  1365. }
  1366. LocalFree(lpExpandedValue);
  1367. }
  1368. }
  1369. dwIndex++;
  1370. cbData = cbDataBuffer;
  1371. cbValueName = MAX_PATH;
  1372. }
  1373. LocalFree(lpDataBuffer);
  1374. RegCloseKey(hkey);
  1375. return(bResult);
  1376. }
  1377. //*************************************************************
  1378. //
  1379. // ExpandEnvironmentStringsForUser()
  1380. //
  1381. // Purpose: Expands the source string using the environment block for the
  1382. // specified user. If hToken is null, the system environment block
  1383. // will be used (no user environment variables).
  1384. //
  1385. // Parameters: hToken - User's token (or null for system env vars)
  1386. // lpSrc - String to be expanded
  1387. // lpDest - Buffer to receive string
  1388. // dwSize - Size of dest buffer
  1389. //
  1390. // Return: TRUE if successful
  1391. // FALSE if an error occurs
  1392. //
  1393. //*************************************************************
  1394. BOOL WINAPI ExpandEnvironmentStringsForUser(HANDLE hToken, LPCTSTR lpSrc,
  1395. LPTSTR lpDest, DWORD dwSize)
  1396. {
  1397. LPVOID pEnv;
  1398. DWORD dwNeeded;
  1399. BOOL bResult = FALSE;
  1400. //
  1401. // Arg check
  1402. //
  1403. if ( !lpDest || !lpSrc )
  1404. {
  1405. SetLastError (ERROR_INVALID_PARAMETER);
  1406. return FALSE;
  1407. }
  1408. //
  1409. // Get the user's environment block
  1410. //
  1411. if (!CreateEnvironmentBlock (&pEnv, hToken, FALSE)) {
  1412. DebugMsg((DM_WARNING, TEXT("ExpandEnvironmentStringsForUser: CreateEnvironmentBlock failed with = %d"),
  1413. GetLastError()));
  1414. return FALSE;
  1415. }
  1416. //
  1417. // Expand the string
  1418. //
  1419. dwNeeded = ExpandUserEnvironmentStrings(pEnv, lpSrc, lpDest, dwSize);
  1420. if (dwNeeded && (dwNeeded < dwSize)) {
  1421. bResult = TRUE;
  1422. } else {
  1423. SetLastError(ERROR_INSUFFICIENT_BUFFER );
  1424. }
  1425. //
  1426. // Free the environment block
  1427. //
  1428. DestroyEnvironmentBlock (pEnv);
  1429. return bResult;
  1430. }
  1431. //*************************************************************
  1432. //
  1433. // GetSystemTempDirectory()
  1434. //
  1435. // Purpose: Gets the system temp directory in short form
  1436. //
  1437. // Parameters: lpDir - Receives the directory
  1438. // lpcchSize - Size of the lpDir buffer
  1439. //
  1440. //
  1441. // Return: TRUE if successful
  1442. // FALSE if an error occurs
  1443. //
  1444. //*************************************************************
  1445. BOOL WINAPI GetSystemTempDirectory(LPTSTR lpDir, LPDWORD lpcchSize)
  1446. {
  1447. TCHAR szTemp[MAX_PATH];
  1448. TCHAR szDirectory[MAX_PATH];
  1449. DWORD dwLength;
  1450. HKEY hKey;
  1451. LONG lResult;
  1452. DWORD dwSize, dwType;
  1453. BOOL bRetVal = FALSE;
  1454. WIN32_FILE_ATTRIBUTE_DATA fad;
  1455. szTemp[0] = TEXT('\0');
  1456. szDirectory[0] = TEXT('\0');
  1457. //
  1458. // Look in the system environment variables
  1459. //
  1460. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SYS_ENVVARS, 0,
  1461. KEY_READ, &hKey) == ERROR_SUCCESS) {
  1462. //
  1463. // Check for TEMP
  1464. //
  1465. dwSize = sizeof(szTemp);
  1466. if (RegQueryValueEx (hKey, TEXT("TEMP"), NULL, &dwType,
  1467. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  1468. RegCloseKey (hKey);
  1469. goto FoundTemp;
  1470. }
  1471. //
  1472. // Check for TMP
  1473. //
  1474. dwSize = sizeof(szTemp);
  1475. if (RegQueryValueEx (hKey, TEXT("TMP"), NULL, &dwType,
  1476. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  1477. RegCloseKey (hKey);
  1478. goto FoundTemp;
  1479. }
  1480. RegCloseKey (hKey);
  1481. }
  1482. //
  1483. // Check if %SystemRoot%\Temp exists
  1484. //
  1485. lstrcpy (szDirectory, TEXT("%SystemRoot%\\Temp"));
  1486. ExpandEnvironmentStrings (szDirectory, szTemp, ARRAYSIZE (szTemp));
  1487. if (GetFileAttributesEx (szTemp, GetFileExInfoStandard, &fad) &&
  1488. fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1489. goto FoundTemp;
  1490. }
  1491. //
  1492. // Check if %SystemDrive%\Temp exists
  1493. //
  1494. lstrcpy (szDirectory, TEXT("%SystemDrive%\\Temp"));
  1495. ExpandEnvironmentStrings (szDirectory, szTemp, ARRAYSIZE (szTemp));
  1496. if (GetFileAttributesEx (szTemp, GetFileExInfoStandard, &fad) &&
  1497. fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1498. goto FoundTemp;
  1499. }
  1500. //
  1501. // Last resort is %SystemRoot%
  1502. //
  1503. lstrcpy (szTemp, TEXT("%SystemRoot%"));
  1504. FoundTemp:
  1505. ExpandEnvironmentStrings (szTemp, szDirectory, ARRAYSIZE (szDirectory));
  1506. GetShortPathName (szDirectory, szTemp, ARRAYSIZE(szTemp));
  1507. dwLength = lstrlen(szTemp) + 1;
  1508. if (lpDir) {
  1509. if (*lpcchSize >= dwLength) {
  1510. lstrcpy (lpDir, szTemp);
  1511. bRetVal = TRUE;
  1512. } else {
  1513. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1514. }
  1515. } else {
  1516. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1517. }
  1518. *lpcchSize = dwLength;
  1519. return bRetVal;
  1520. }
  1521. #ifdef _X86_
  1522. BOOL
  1523. IsPathIncludeRemovable(LPTSTR lpValue)
  1524. {
  1525. LPTSTR lpt, tmp;
  1526. BOOL ret = FALSE;
  1527. WCHAR c;
  1528. tmp = LocalAlloc(LPTR, (lstrlen(lpValue) + 1) * sizeof(WCHAR));
  1529. if (!tmp) {
  1530. DebugMsg((DM_WARNING, TEXT("IsPathIncludeRemovable : Failed to LocalAlloc (%d)"), GetLastError()));
  1531. }
  1532. else {
  1533. lstrcpy(tmp, lpValue);
  1534. lpt = tmp;
  1535. while (*lpt) {
  1536. // skip spaces
  1537. for ( ; *lpt && *lpt == TEXT(' '); lpt++)
  1538. ;
  1539. // check if the drive is removable
  1540. if (lpt[0] && lpt[1] && lpt[1] == TEXT(':') && lpt[2]) { // ex) "A:\"
  1541. c = lpt[3];
  1542. lpt[3] = 0;
  1543. if (GetDriveType(lpt) == DRIVE_REMOVABLE) {
  1544. lpt[3] = c;
  1545. ret = TRUE;
  1546. break;
  1547. }
  1548. lpt[3] = c;
  1549. }
  1550. // skip to the next path
  1551. for ( ; *lpt && *lpt != TEXT(';'); lpt++)
  1552. ;
  1553. if (*lpt)
  1554. lpt++;
  1555. }
  1556. LocalFree(tmp);
  1557. }
  1558. return(ret);
  1559. }
  1560. #endif