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.

984 lines
29 KiB

  1. #include "stdafx.h"
  2. #include "RemoteEnv.h"
  3. #include "common.h"
  4. #include <strsafe.h>
  5. #include "cryptpass.h"
  6. typedef LONG NTSTATUS;
  7. #define MAX_ENV_VALUE_LEN 1024
  8. #define DEFAULT_ROOT_KEY HKEY_LOCAL_MACHINE
  9. #define REG_PATH_TO_SYSROOT TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion")
  10. #define REG_PATH_TO_COMMON_FOLDERS TEXT("Software\\Microsoft\\Windows\\CurrentVersion")
  11. #define REG_PATH_TO_ENV TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment")
  12. #define PATH_VARIABLE TEXT("Path")
  13. #define LIBPATH_VARIABLE TEXT("LibPath")
  14. #define OS2LIBPATH_VARIABLE TEXT("Os2LibPath")
  15. #define AUTOEXECPATH_VARIABLE TEXT("AutoexecPath")
  16. #define ENV_KEYWORD_SYSTEMROOT TEXT("SystemRoot")
  17. #define ENV_KEYWORD_PROGRAMFILESDIR TEXT("ProgramFilesDir")
  18. #define ENV_KEYWORD_COMMONFILESDIR TEXT("CommonFilesDir")
  19. #define ENV_KEYWORD_PROGRAMFILESDIR_X86 TEXT("ProgramFilesDir (x86)")
  20. #define ENV_KEYWORD_COMMONFILESDIR_X86 TEXT("CommonFilesDir (x86)")
  21. #define PROGRAMFILES_VARIABLE TEXT("ProgramFiles")
  22. #define COMMONPROGRAMFILES_VARIABLE TEXT("CommonProgramFiles")
  23. #define PROGRAMFILESX86_VARIABLE TEXT("ProgramFiles(x86)")
  24. #define COMMONPROGRAMFILESX86_VARIABLE TEXT("CommonProgramFiles(x86)")
  25. CRemoteExpandEnvironmentStrings::CRemoteExpandEnvironmentStrings()
  26. {
  27. m_pEnvironment = NULL;
  28. m_lpszUncServerName = NULL;
  29. m_lpszUserName = NULL;
  30. m_lpszUserPasswordEncrypted = NULL;
  31. m_cbUserPasswordEncrypted = 0;
  32. return;
  33. }
  34. CRemoteExpandEnvironmentStrings::~CRemoteExpandEnvironmentStrings()
  35. {
  36. DeleteRemoteEnvironment();
  37. if (m_lpszUncServerName)
  38. {
  39. LocalFree(m_lpszUncServerName);
  40. m_lpszUncServerName = NULL;
  41. }
  42. if (m_lpszUserName)
  43. {
  44. LocalFree(m_lpszUserName);
  45. m_lpszUserName = NULL;
  46. }
  47. if (m_lpszUserPasswordEncrypted)
  48. {
  49. if (m_cbUserPasswordEncrypted > 0)
  50. {
  51. // erase any password we may have in memory -- even though it's encrypted in memory
  52. SecureZeroMemory(m_lpszUserPasswordEncrypted,m_cbUserPasswordEncrypted);
  53. }
  54. LocalFree(m_lpszUserPasswordEncrypted);
  55. }
  56. m_lpszUserPasswordEncrypted = NULL;
  57. m_cbUserPasswordEncrypted = 0;
  58. return;
  59. }
  60. BOOL
  61. CRemoteExpandEnvironmentStrings::NewRemoteEnvironment()
  62. {
  63. BOOL bReturn = FALSE;
  64. // already have a cached one, use that...
  65. if (m_pEnvironment)
  66. {
  67. bReturn = TRUE;
  68. }
  69. else
  70. {
  71. //
  72. // Create a temporary environment, which we'll fill in and let RTL
  73. // routines do the expansion for us.
  74. //
  75. if ( !NT_SUCCESS(RtlCreateEnvironment((BOOLEAN) FALSE,&m_pEnvironment)) )
  76. {
  77. bReturn = FALSE;
  78. goto NewRemoteEnvironment_Exit;
  79. }
  80. SetOtherEnvironmentValues(&m_pEnvironment);
  81. SetEnvironmentVariables(&m_pEnvironment);
  82. bReturn = TRUE;
  83. }
  84. NewRemoteEnvironment_Exit:
  85. return bReturn;
  86. }
  87. void
  88. CRemoteExpandEnvironmentStrings::DeleteRemoteEnvironment()
  89. {
  90. if (m_pEnvironment != NULL)
  91. {
  92. RtlDestroyEnvironment(m_pEnvironment);
  93. m_pEnvironment = NULL;
  94. }
  95. return;
  96. }
  97. BOOL CRemoteExpandEnvironmentStrings::IsLocalMachine(LPCTSTR psz)
  98. {
  99. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  100. DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH + 1;
  101. if (_tcsicmp(psz,_T("")) == 0)
  102. {
  103. // it's empty,
  104. // yeah it's local machine
  105. return TRUE;
  106. }
  107. // get the actual name of the local machine
  108. if (!GetComputerName(szComputerName, &cbComputerName))
  109. {
  110. return FALSE;
  111. }
  112. // compare and return
  113. if (0 == _tcsicmp(szComputerName, psz))
  114. {
  115. return TRUE;
  116. }
  117. return FALSE;
  118. }
  119. BOOL
  120. CRemoteExpandEnvironmentStrings::SetUserName(IN LPCTSTR szUserName)
  121. {
  122. BOOL bReturn = FALSE;
  123. DWORD dwSize = 0;
  124. LPTSTR lpszUserNameOriginal = NULL;
  125. // free any previous thing we had...
  126. if (m_lpszUserName)
  127. {
  128. // Make a copy of it before we delete it
  129. dwSize = (_tcslen(m_lpszUserName) + 1) * sizeof(TCHAR);
  130. lpszUserNameOriginal = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
  131. if (lpszUserNameOriginal)
  132. {
  133. StringCbCopy(lpszUserNameOriginal,dwSize,m_lpszUserName);
  134. }
  135. // free up anything we had before
  136. LocalFree(m_lpszUserName);
  137. m_lpszUserName = NULL;
  138. }
  139. if (_tcsicmp(szUserName,_T("")) == 0)
  140. {
  141. bReturn = TRUE;
  142. goto SetUserName_Exit;
  143. }
  144. dwSize = (_tcslen(szUserName) + 1 + 2) * sizeof(TCHAR);
  145. m_lpszUserName = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
  146. if (m_lpszUserName)
  147. {
  148. StringCbCopy(m_lpszUserName,dwSize,szUserName);
  149. bReturn = TRUE;
  150. }
  151. SetUserName_Exit:
  152. if (lpszUserNameOriginal)
  153. {LocalFree(lpszUserNameOriginal);lpszUserNameOriginal=NULL;}
  154. return TRUE;
  155. }
  156. BOOL
  157. CRemoteExpandEnvironmentStrings::SetUserPassword(IN LPCTSTR szUserPassword)
  158. {
  159. BOOL bReturn = FALSE;
  160. // free any previous thing we had...
  161. if (m_lpszUserPasswordEncrypted)
  162. {
  163. // free up anything we had before
  164. if (m_cbUserPasswordEncrypted > 0)
  165. {
  166. SecureZeroMemory(m_lpszUserPasswordEncrypted,m_cbUserPasswordEncrypted);
  167. }
  168. LocalFree(m_lpszUserPasswordEncrypted);
  169. m_lpszUserPasswordEncrypted = NULL;
  170. m_cbUserPasswordEncrypted = 0;
  171. }
  172. if (_tcsicmp(szUserPassword,_T("")) == 0)
  173. {
  174. bReturn = TRUE;
  175. goto SetUserPassword_Exit;
  176. }
  177. // encrypt the password in memory (CryptProtectMemory)
  178. // this way if the process get's paged out to the swapfile,
  179. // the password won't be in clear text.
  180. if (SUCCEEDED(EncryptMemoryPassword((LPWSTR) szUserPassword,&m_lpszUserPasswordEncrypted,&m_cbUserPasswordEncrypted)))
  181. {
  182. bReturn = TRUE;
  183. goto SetUserPassword_Exit;
  184. }
  185. SetUserPassword_Exit:
  186. return bReturn;
  187. }
  188. BOOL
  189. CRemoteExpandEnvironmentStrings::SetMachineName(IN LPCTSTR szMachineName)
  190. {
  191. BOOL bReturn = FALSE;
  192. DWORD dwSize = 0;
  193. LPTSTR lpszUncServerNameOriginal = NULL;
  194. // free any previous thing we had...
  195. if (m_lpszUncServerName)
  196. {
  197. // Make a copy of it before we delete it
  198. dwSize = (_tcslen(m_lpszUncServerName) + 1) * sizeof(TCHAR);
  199. lpszUncServerNameOriginal = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
  200. if (lpszUncServerNameOriginal)
  201. {
  202. StringCbCopy(lpszUncServerNameOriginal,dwSize,m_lpszUncServerName);
  203. }
  204. // free up anything we had before
  205. LocalFree(m_lpszUncServerName);
  206. m_lpszUncServerName = NULL;
  207. }
  208. if (_tcsicmp(szMachineName,_T("")) == 0)
  209. {
  210. bReturn = TRUE;
  211. goto SetMachineName_Exit;
  212. }
  213. // if it's the localmachine name
  214. // then set it to NULL
  215. // so that it will be treated as localmachine.
  216. if (IsLocalMachine(szMachineName))
  217. {
  218. m_lpszUncServerName = NULL;
  219. bReturn = TRUE;
  220. goto SetMachineName_Exit;
  221. }
  222. dwSize = (_tcslen(szMachineName) + 1 + 2) * sizeof(TCHAR);
  223. m_lpszUncServerName = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
  224. if (m_lpszUncServerName)
  225. {
  226. // check if szMachineName already starts with "\\"
  227. if (szMachineName[0] == _T('\\') && szMachineName[1] == _T('\\'))
  228. {
  229. StringCbCopy(m_lpszUncServerName,dwSize,szMachineName);
  230. }
  231. else
  232. {
  233. StringCbCopy(m_lpszUncServerName,dwSize,_T("\\\\"));
  234. StringCbCat(m_lpszUncServerName,dwSize,szMachineName);
  235. }
  236. bReturn = TRUE;
  237. }
  238. // if the machine name is different from what it was before
  239. // then delete the current environment if any...
  240. if (m_lpszUncServerName && lpszUncServerNameOriginal)
  241. {
  242. if (0 != _tcsicmp(lpszUncServerNameOriginal,m_lpszUncServerName))
  243. {
  244. DeleteRemoteEnvironment();
  245. }
  246. }
  247. else
  248. {
  249. DeleteRemoteEnvironment();
  250. }
  251. SetMachineName_Exit:
  252. if (lpszUncServerNameOriginal)
  253. {LocalFree(lpszUncServerNameOriginal);lpszUncServerNameOriginal=NULL;}
  254. return bReturn;
  255. }
  256. DWORD
  257. CRemoteExpandEnvironmentStrings::GetRegKeyMaxSizes(
  258. IN HKEY WinRegHandle,
  259. OUT LPDWORD MaxKeywordSize OPTIONAL,
  260. OUT LPDWORD MaxValueSize OPTIONAL
  261. )
  262. {
  263. LONG Error;
  264. DWORD MaxValueNameLength;
  265. DWORD MaxValueDataLength;
  266. Error = RegQueryInfoKey(
  267. WinRegHandle,
  268. NULL,
  269. NULL,
  270. NULL,
  271. NULL,
  272. NULL,
  273. NULL,
  274. NULL,
  275. &MaxValueNameLength,
  276. &MaxValueDataLength,
  277. NULL,
  278. NULL
  279. );
  280. if (ERROR_SUCCESS == Error)
  281. {
  282. //
  283. // MaxValueNameLength is a count of TCHARs.
  284. // MaxValueDataLength is a count of bytes already.
  285. //
  286. MaxValueNameLength = (MaxValueNameLength + 1) * sizeof(TCHAR);
  287. if (MaxKeywordSize)
  288. {
  289. *MaxKeywordSize = MaxValueNameLength;
  290. }
  291. if (MaxValueSize)
  292. {
  293. *MaxValueSize = MaxValueDataLength;
  294. }
  295. }
  296. return (Error);
  297. }
  298. NET_API_STATUS
  299. CRemoteExpandEnvironmentStrings::RemoteExpandEnvironmentStrings(
  300. IN LPCTSTR UnexpandedString,
  301. OUT LPTSTR * ValueBufferPtr // Must be freed by LocalFree().
  302. )
  303. /*++
  304. Routine Description:
  305. This function expands a value string (which may include references to
  306. environment variables). For instance, an unexpanded string might be:
  307. %SystemRoot%\System32\Repl\Export
  308. This could be expanded to:
  309. c:\nt\System32\Repl\Export
  310. The expansion makes use of environment variables on m_lpszUncServerName,
  311. if given. This allows remote administration of the directory
  312. replicator.
  313. Arguments:
  314. m_lpszUncServerName - assumed to NOT BE EXPLICIT LOCAL SERVER NAME.
  315. UnexpandedString - points to source string to be expanded.
  316. ValueBufferPtr - indicates a pointer which will be set by this routine.
  317. This routine will allocate memory for a null-terminated string.
  318. The caller must free this with LocalFree() or equivalent.
  319. Return Value:
  320. NET_API_STATUS
  321. --*/
  322. {
  323. NET_API_STATUS ApiStatus = NO_ERROR;
  324. LPTSTR ExpandedString = NULL;
  325. DWORD LastAllocationSize = 0;
  326. NTSTATUS NtStatus;
  327. //
  328. // Check for caller errors.
  329. //
  330. if (ValueBufferPtr == NULL) {
  331. // Can't goto Cleanup here, as it assumes this pointer is valid
  332. return (ERROR_INVALID_PARAMETER);
  333. }
  334. *ValueBufferPtr = NULL; // assume error until proven otherwise.
  335. if (UnexpandedString == NULL)
  336. {
  337. ApiStatus = ERROR_INVALID_PARAMETER;
  338. goto Cleanup;
  339. }
  340. //
  341. // This is probably just a constant string.
  342. //
  343. if (wcschr( UnexpandedString, _T('%') ) == NULL)
  344. {
  345. // Just need to allocate a copy of the input string.
  346. DWORD dwSize = (_tcslen(UnexpandedString) + 1) * sizeof(TCHAR);
  347. ExpandedString = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
  348. if (ExpandedString == NULL)
  349. {
  350. ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
  351. goto Cleanup;
  352. }
  353. else
  354. {
  355. RtlCopyMemory(ExpandedString, UnexpandedString, dwSize);
  356. }
  357. // That's all, folks!
  358. ApiStatus = NO_ERROR;
  359. //
  360. // Otherwise, is this local? Maybe we can
  361. // handle local expansion the easy (fast) way: using win32 API.
  362. //
  363. }
  364. else if (m_lpszUncServerName == NULL)
  365. {
  366. DWORD CharsRequired = wcslen(UnexpandedString)+1;
  367. do {
  368. // Clean up from previous pass.
  369. if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;}
  370. // Allocate the memory.
  371. ExpandedString = (LPTSTR) LocalAlloc(LMEM_FIXED, CharsRequired * sizeof(TCHAR));
  372. if (ExpandedString == NULL)
  373. {
  374. ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
  375. goto Cleanup;
  376. }
  377. LastAllocationSize = CharsRequired * sizeof(TCHAR);
  378. // Expand string using local env vars.
  379. CharsRequired = ExpandEnvironmentStrings(UnexpandedString,ExpandedString,LastAllocationSize / sizeof(TCHAR));
  380. if (CharsRequired == 0)
  381. {
  382. ApiStatus = (NET_API_STATUS) GetLastError();
  383. goto Cleanup;
  384. }
  385. } while ((CharsRequired*sizeof(TCHAR)) > LastAllocationSize);
  386. ApiStatus = NO_ERROR;
  387. //
  388. // Oh well, remote expansion required.
  389. //
  390. }
  391. else
  392. {
  393. UNICODE_STRING ExpandedUnicode;
  394. DWORD SizeRequired;
  395. UNICODE_STRING UnexpandedUnicode;
  396. //
  397. // Create a temporary environment, which we'll fill in and let RTL
  398. // routines do the expansion for us.
  399. //
  400. if (FALSE == NewRemoteEnvironment())
  401. {
  402. ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
  403. goto Cleanup;
  404. }
  405. //
  406. // Loop until we have enough storage.
  407. // Expand the string.
  408. //
  409. SizeRequired = (_tcslen(UnexpandedString) + 1) * sizeof(TCHAR); // First pass, try same size
  410. RtlInitUnicodeString(&UnexpandedUnicode,(PCWSTR) UnexpandedString);
  411. do {
  412. // Clean up from previous pass.
  413. if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;}
  414. // Allocate the memory.
  415. ExpandedString = (LPTSTR) LocalAlloc(LMEM_FIXED, SizeRequired);
  416. if (ExpandedString == NULL)
  417. {
  418. ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
  419. goto Cleanup;
  420. }
  421. LastAllocationSize = SizeRequired;
  422. ExpandedUnicode.MaximumLength = (USHORT)SizeRequired;
  423. ExpandedUnicode.Buffer = ExpandedString;
  424. NtStatus = RtlExpandEnvironmentStrings_U(
  425. m_pEnvironment, // env to use
  426. &UnexpandedUnicode, // source
  427. &ExpandedUnicode, // dest
  428. (PULONG) &SizeRequired ); // dest size needed next time.
  429. if ( NtStatus == STATUS_BUFFER_TOO_SMALL )
  430. {
  431. continue; // try again with larger buffer.
  432. }
  433. else if ( !NT_SUCCESS( NtStatus ) )
  434. {
  435. ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
  436. goto Cleanup;
  437. }
  438. else
  439. {
  440. break; // All done.
  441. }
  442. } while (SizeRequired > LastAllocationSize);
  443. ApiStatus = NO_ERROR;
  444. }
  445. Cleanup:
  446. if (ApiStatus == NO_ERROR)
  447. {
  448. *ValueBufferPtr = ExpandedString;
  449. }
  450. else
  451. {
  452. *ValueBufferPtr = NULL;
  453. if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;}
  454. }
  455. return (ApiStatus);
  456. }
  457. BOOL CRemoteExpandEnvironmentStrings::BuildEnvironmentPath(void **pEnv, LPTSTR lpPathVariable, LPTSTR lpPathValue)
  458. {
  459. NTSTATUS Status;
  460. UNICODE_STRING Name;
  461. UNICODE_STRING Value;
  462. WCHAR lpTemp[1025];
  463. DWORD cb;
  464. if (!*pEnv) {
  465. return(FALSE);
  466. }
  467. RtlInitUnicodeString(&Name, lpPathVariable);
  468. cb = 1024;
  469. Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  470. if (!Value.Buffer) {
  471. return(FALSE);
  472. }
  473. Value.Length = (USHORT)(sizeof(WCHAR) * cb);
  474. Value.MaximumLength = (USHORT)(sizeof(WCHAR) * cb);
  475. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  476. if (!NT_SUCCESS(Status)) {
  477. LocalFree(Value.Buffer);
  478. Value.Length = 0;
  479. *lpTemp = 0;
  480. }
  481. if (Value.Length)
  482. {
  483. StringCbCopy(lpTemp,sizeof(lpTemp),Value.Buffer);
  484. if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') )
  485. {
  486. StringCbCat(lpTemp,sizeof(lpTemp),TEXT(";"));
  487. }
  488. LocalFree(Value.Buffer);
  489. }
  490. if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb))
  491. {
  492. StringCbCat(lpTemp,sizeof(lpTemp),lpPathValue);
  493. RtlInitUnicodeString(&Value, lpTemp);
  494. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  495. }
  496. if (NT_SUCCESS(Status)) {
  497. return(TRUE);
  498. }
  499. return(FALSE);
  500. }
  501. DWORD CRemoteExpandEnvironmentStrings::ExpandUserEnvironmentStrings(void *pEnv, LPTSTR lpSrc, LPTSTR lpDst, DWORD nSize)
  502. {
  503. NTSTATUS Status;
  504. UNICODE_STRING Source, Destination;
  505. ULONG Length;
  506. RtlInitUnicodeString( &Source, lpSrc );
  507. Destination.Buffer = lpDst;
  508. Destination.Length = 0;
  509. Destination.MaximumLength = (USHORT)(nSize* sizeof(WCHAR));
  510. Length = 0;
  511. Status = RtlExpandEnvironmentStrings_U(pEnv,
  512. (PUNICODE_STRING)&Source,
  513. (PUNICODE_STRING)&Destination,
  514. &Length
  515. );
  516. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) {
  517. return( Length );
  518. }
  519. else {
  520. return( 0 );
  521. }
  522. }
  523. BOOL CRemoteExpandEnvironmentStrings::SetUserEnvironmentVariable(void **pEnv, LPTSTR lpVariable, LPTSTR lpValue, BOOL bOverwrite)
  524. {
  525. NTSTATUS Status;
  526. UNICODE_STRING Name;
  527. UNICODE_STRING Value;
  528. DWORD cb;
  529. TCHAR szValue[1024];
  530. if (!*pEnv || !lpVariable || !*lpVariable) {
  531. return(FALSE);
  532. }
  533. RtlInitUnicodeString(&Name, lpVariable);
  534. cb = 1024;
  535. Value.Buffer = (PTCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  536. if (Value.Buffer) {
  537. Value.Length = (USHORT)cb;
  538. Value.MaximumLength = (USHORT)cb;
  539. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  540. LocalFree(Value.Buffer);
  541. if (NT_SUCCESS(Status) && !bOverwrite) {
  542. return(TRUE);
  543. }
  544. }
  545. if (lpValue && *lpValue) {
  546. //
  547. // Special case TEMP and TMP and shorten the path names
  548. //
  549. if ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
  550. (!lstrcmpi(lpVariable, TEXT("TMP")))) {
  551. if (!GetShortPathName (lpValue, szValue, 1024)) {
  552. lstrcpyn (szValue, lpValue, 1024);
  553. }
  554. } else {
  555. lstrcpyn (szValue, lpValue, 1024);
  556. }
  557. RtlInitUnicodeString(&Value, szValue);
  558. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  559. }
  560. else {
  561. Status = RtlSetEnvironmentVariable( pEnv, &Name, NULL);
  562. }
  563. return NT_SUCCESS(Status);
  564. }
  565. // Reads the system environment variables from the registry
  566. // and adds them to the environment block at pEnv.
  567. BOOL CRemoteExpandEnvironmentStrings::SetEnvironmentVariables(void **pEnv)
  568. {
  569. WCHAR lpValueName[MAX_PATH];
  570. LPBYTE lpDataBuffer;
  571. DWORD cbDataBuffer;
  572. LPBYTE lpData;
  573. LPTSTR lpExpandedValue = NULL;
  574. DWORD cbValueName = MAX_PATH;
  575. DWORD cbData;
  576. DWORD dwType;
  577. DWORD dwIndex = 0;
  578. HKEY hkey;
  579. BOOL bResult;
  580. HKEY RootKey = DEFAULT_ROOT_KEY;
  581. // If any of this fails...
  582. // we should try to use the username/userpassword to connect to the server
  583. // and try it again...
  584. if (ERROR_SUCCESS != RegConnectRegistry((LPTSTR) m_lpszUncServerName,DEFAULT_ROOT_KEY,& RootKey ))
  585. {
  586. return(FALSE);
  587. }
  588. if (RegOpenKeyExW(RootKey,REG_PATH_TO_ENV,REG_OPTION_NON_VOLATILE,KEY_READ,& hkey))
  589. {
  590. return(FALSE);
  591. }
  592. cbDataBuffer = 4096;
  593. lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cbDataBuffer*sizeof(WCHAR));
  594. if (lpDataBuffer == NULL) {
  595. RegCloseKey(hkey);
  596. return(FALSE);
  597. }
  598. lpData = lpDataBuffer;
  599. cbData = cbDataBuffer;
  600. bResult = TRUE;
  601. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  602. lpData, &cbData)) {
  603. if (cbValueName) {
  604. //
  605. // Limit environment variable length
  606. //
  607. lpData[MAX_ENV_VALUE_LEN-1] = TEXT('\0');
  608. if (dwType == REG_SZ) {
  609. //
  610. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  611. // their values apppended to the system path.
  612. //
  613. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  614. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  615. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  616. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpData);
  617. }
  618. else {
  619. //
  620. // the other environment variables are just set.
  621. //
  622. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpData, TRUE);
  623. }
  624. }
  625. }
  626. dwIndex++;
  627. cbData = cbDataBuffer;
  628. cbValueName = MAX_PATH;
  629. }
  630. dwIndex = 0;
  631. cbData = cbDataBuffer;
  632. cbValueName = MAX_PATH;
  633. while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType,
  634. lpData, &cbData)) {
  635. if (cbValueName) {
  636. //
  637. // Limit environment variable length
  638. //
  639. lpData[MAX_ENV_VALUE_LEN-1] = TEXT('\0');
  640. if (dwType == REG_EXPAND_SZ) {
  641. DWORD cb, cbNeeded;
  642. cb = 1024;
  643. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  644. if (lpExpandedValue) {
  645. cbNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  646. if (cbNeeded > cb) {
  647. LocalFree(lpExpandedValue);
  648. cb = cbNeeded;
  649. lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR));
  650. if (lpExpandedValue) {
  651. ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb);
  652. }
  653. }
  654. }
  655. if (lpExpandedValue == NULL) {
  656. bResult = FALSE;
  657. break;
  658. }
  659. //
  660. // The path variables PATH, LIBPATH and OS2LIBPATH must have
  661. // their values apppended to the system path.
  662. //
  663. if ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
  664. !lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
  665. !lstrcmpi(lpValueName, OS2LIBPATH_VARIABLE) ) {
  666. BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpExpandedValue);
  667. }
  668. else {
  669. //
  670. // the other environment variables are just set.
  671. //
  672. SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE);
  673. }
  674. LocalFree(lpExpandedValue);
  675. }
  676. }
  677. dwIndex++;
  678. cbData = cbDataBuffer;
  679. cbValueName = MAX_PATH;
  680. }
  681. LocalFree(lpDataBuffer);
  682. RegCloseKey(hkey);
  683. return(bResult);
  684. }
  685. //*************************************************************
  686. //
  687. // SetEnvironmentVariableInBlock()
  688. //
  689. // Purpose: Sets the environment variable in the given block
  690. //
  691. // Parameters: pEnv - Environment block
  692. // lpVariable - Variables
  693. // lpValue - Value
  694. // bOverwrite - Overwrite
  695. //
  696. //
  697. // Return: TRUE if successful
  698. // FALSE if an error occurs
  699. //
  700. // Comments:
  701. //
  702. // History: Date Author Comment
  703. // 6/21/96 ericflo Ported
  704. //
  705. //*************************************************************
  706. BOOL CRemoteExpandEnvironmentStrings::SetEnvironmentVariableInBlock(PVOID *pEnv, LPTSTR lpVariable,LPTSTR lpValue, BOOL bOverwrite)
  707. {
  708. NTSTATUS Status;
  709. UNICODE_STRING Name, Value;
  710. DWORD cb;
  711. LPTSTR szValue = NULL;
  712. if (!*pEnv || !lpVariable || !*lpVariable) {
  713. return(FALSE);
  714. }
  715. RtlInitUnicodeString(&Name, lpVariable);
  716. cb = 1025 * sizeof(WCHAR);
  717. Value.Buffer = (PWSTR) LocalAlloc(LPTR, cb);
  718. if (Value.Buffer) {
  719. Value.Length = 0;
  720. Value.MaximumLength = (USHORT)cb;
  721. Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
  722. LocalFree(Value.Buffer);
  723. if ( NT_SUCCESS(Status) && !bOverwrite) {
  724. return(TRUE);
  725. }
  726. }
  727. szValue = (LPTSTR)LocalAlloc(LPTR, 1024*sizeof(TCHAR));
  728. if (!szValue)
  729. {
  730. return FALSE;
  731. }
  732. if (lpValue && *lpValue) {
  733. //
  734. // Special case TEMP and TMP and shorten the path names
  735. //
  736. if ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
  737. (!lstrcmpi(lpVariable, TEXT("TMP")))) {
  738. if (!GetShortPathName (lpValue, szValue, 1024)) {
  739. lstrcpyn (szValue, lpValue, 1024);
  740. }
  741. } else {
  742. lstrcpyn (szValue, lpValue, 1024);
  743. }
  744. RtlInitUnicodeString(&Value, szValue);
  745. Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
  746. }
  747. else {
  748. Status = RtlSetEnvironmentVariable(pEnv, &Name, NULL);
  749. }
  750. LocalFree(szValue);
  751. if (NT_SUCCESS(Status)) {
  752. return(TRUE);
  753. }
  754. return(FALSE);
  755. }
  756. // Just set the environmental variables that we can
  757. // if we can't set them because of no access, no biggie
  758. DWORD CRemoteExpandEnvironmentStrings::SetOtherEnvironmentValues(void **pEnv)
  759. {
  760. DWORD dwResult = ERROR_SUCCESS;
  761. HKEY hKey = NULL;
  762. HKEY RootKey = DEFAULT_ROOT_KEY;
  763. DWORD dwType, dwSize;
  764. TCHAR szValue[MAX_ENV_VALUE_LEN + 1];
  765. TCHAR szExpValue[MAX_ENV_VALUE_LEN + 1];
  766. DWORD RandomValueSize = 0;
  767. LPTSTR RandomValueW = NULL;
  768. // If any of this fails...
  769. // we should try to use the username/userpassword to connect to the server
  770. // and try it again...
  771. // try to connect to remote registry (or local registry if Null)
  772. dwResult = RegConnectRegistry((LPTSTR) m_lpszUncServerName,DEFAULT_ROOT_KEY,& RootKey);
  773. if (ERROR_SUCCESS != dwResult)
  774. {
  775. goto SetOtherEnvironmentValues_Exit;
  776. }
  777. dwResult = RegOpenKeyEx(RootKey,REG_PATH_TO_SYSROOT,REG_OPTION_NON_VOLATILE,KEY_READ,&hKey);
  778. if (ERROR_SUCCESS == dwResult)
  779. {
  780. dwResult = GetRegKeyMaxSizes(
  781. hKey,
  782. NULL, // don't need keyword size
  783. &RandomValueSize ); // set max value size.
  784. if (ERROR_SUCCESS != dwResult)
  785. {
  786. goto SetOtherEnvironmentValues_Exit;
  787. }
  788. RandomValueW = (LPTSTR) LocalAlloc(LMEM_FIXED, RandomValueSize);
  789. if (RandomValueW == NULL)
  790. {
  791. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  792. }
  793. else
  794. {
  795. if (RegQueryValueEx(hKey,(LPTSTR)ENV_KEYWORD_SYSTEMROOT,REG_OPTION_NON_VOLATILE,&dwType,(LPBYTE) RandomValueW,&RandomValueSize) == ERROR_SUCCESS)
  796. {
  797. SetEnvironmentVariableInBlock(pEnv, ENV_KEYWORD_SYSTEMROOT, RandomValueW, TRUE);
  798. }
  799. }
  800. if (hKey) {RegCloseKey(hKey);}
  801. }
  802. dwResult = RegOpenKeyEx (RootKey, REG_PATH_TO_COMMON_FOLDERS, REG_OPTION_NON_VOLATILE, KEY_READ, &hKey);
  803. if (ERROR_SUCCESS == dwResult)
  804. {
  805. dwSize = (MAX_ENV_VALUE_LEN+1) * sizeof(TCHAR);
  806. if (RegQueryValueEx (hKey, ENV_KEYWORD_PROGRAMFILESDIR, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS)
  807. {
  808. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1));
  809. SetEnvironmentVariableInBlock(pEnv, PROGRAMFILES_VARIABLE, szExpValue, TRUE);
  810. }
  811. dwSize = (MAX_ENV_VALUE_LEN+1) * sizeof(TCHAR);
  812. if (RegQueryValueEx (hKey, ENV_KEYWORD_COMMONFILESDIR, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS)
  813. {
  814. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1));
  815. SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILES_VARIABLE, szExpValue, TRUE);
  816. }
  817. dwSize = (MAX_ENV_VALUE_LEN+1)*sizeof(TCHAR);
  818. if (RegQueryValueEx (hKey, ENV_KEYWORD_PROGRAMFILESDIR_X86, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS)
  819. {
  820. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1));
  821. SetEnvironmentVariableInBlock(pEnv, PROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  822. }
  823. dwSize = (MAX_ENV_VALUE_LEN+1)*sizeof(TCHAR);
  824. if (RegQueryValueEx (hKey, ENV_KEYWORD_COMMONFILESDIR_X86, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS)
  825. {
  826. ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1));
  827. SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
  828. }
  829. }
  830. SetOtherEnvironmentValues_Exit:
  831. if (RootKey != DEFAULT_ROOT_KEY)
  832. {RegCloseKey(RootKey);}
  833. if (hKey) {RegCloseKey(hKey);}
  834. return dwResult;
  835. }