#include "stdafx.h" #include "RemoteEnv.h" typedef LONG NTSTATUS; #define MAX_ENV_VALUE_LEN 1024 #define DEFAULT_ROOT_KEY HKEY_LOCAL_MACHINE #define REG_PATH_TO_SYSROOT TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion") #define REG_PATH_TO_COMMON_FOLDERS TEXT("Software\\Microsoft\\Windows\\CurrentVersion") #define REG_PATH_TO_ENV TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment") #define PATH_VARIABLE TEXT("Path") #define LIBPATH_VARIABLE TEXT("LibPath") #define OS2LIBPATH_VARIABLE TEXT("Os2LibPath") #define AUTOEXECPATH_VARIABLE TEXT("AutoexecPath") #define ENV_KEYWORD_SYSTEMROOT TEXT("SystemRoot") #define ENV_KEYWORD_PROGRAMFILESDIR TEXT("ProgramFilesDir") #define ENV_KEYWORD_COMMONFILESDIR TEXT("CommonFilesDir") #define ENV_KEYWORD_PROGRAMFILESDIR_X86 TEXT("ProgramFilesDir (x86)") #define ENV_KEYWORD_COMMONFILESDIR_X86 TEXT("CommonFilesDir (x86)") #define PROGRAMFILES_VARIABLE TEXT("ProgramFiles") #define COMMONPROGRAMFILES_VARIABLE TEXT("CommonProgramFiles") #define PROGRAMFILESX86_VARIABLE TEXT("ProgramFiles(x86)") #define COMMONPROGRAMFILESX86_VARIABLE TEXT("CommonProgramFiles(x86)") CRemoteExpandEnvironmentStrings::CRemoteExpandEnvironmentStrings() { m_pEnvironment = NULL; m_lpszUncServerName = NULL; return; } CRemoteExpandEnvironmentStrings::~CRemoteExpandEnvironmentStrings() { DeleteRemoteEnvironment(); if (m_lpszUncServerName) { LocalFree(m_lpszUncServerName); m_lpszUncServerName = NULL; } return; } BOOL CRemoteExpandEnvironmentStrings::NewRemoteEnvironment() { BOOL bReturn = FALSE; // already have a cached one, use that... if (m_pEnvironment) { bReturn = TRUE; } else { // // Create a temporary environment, which we'll fill in and let RTL // routines do the expansion for us. // if ( !NT_SUCCESS(RtlCreateEnvironment((BOOLEAN) FALSE,&m_pEnvironment)) ) { bReturn = FALSE; goto NewRemoteEnvironment_Exit; } SetOtherEnvironmentValues(&m_pEnvironment); SetEnvironmentVariables(&m_pEnvironment); bReturn = TRUE; } NewRemoteEnvironment_Exit: return bReturn; } void CRemoteExpandEnvironmentStrings::DeleteRemoteEnvironment() { if (m_pEnvironment != NULL) { RtlDestroyEnvironment(m_pEnvironment); m_pEnvironment = NULL; } return; } BOOL CRemoteExpandEnvironmentStrings::IsLocalMachine(LPCTSTR psz) { CString szLocal; DWORD cch = MAX_COMPUTERNAME_LENGTH + 1; BOOL bAnswer; if (_tcsicmp(psz,_T("")) == 0) { // it's empty, // yeah it's local machine return TRUE; } // get the actual name of the local machine bAnswer = GetComputerName(szLocal.GetBuffer(cch), &cch); szLocal.ReleaseBuffer(); if ( !bAnswer ) return FALSE; // compare and return bAnswer = (szLocal.CompareNoCase( psz ) == 0); return bAnswer; } BOOL CRemoteExpandEnvironmentStrings::SetMachineName(IN LPCTSTR szMachineName) { BOOL bReturn = FALSE; DWORD dwSize = 0; LPTSTR lpszUncServerNameOriginal = NULL; // free any previous thing we had... if (m_lpszUncServerName) { // Make a copy of it before we delete it dwSize = (_tcslen(m_lpszUncServerName) + 1) * sizeof(TCHAR); lpszUncServerNameOriginal = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize); if (lpszUncServerNameOriginal) { _tcscpy(lpszUncServerNameOriginal, m_lpszUncServerName); } // free up anything we had before LocalFree(m_lpszUncServerName); m_lpszUncServerName = NULL; } if (_tcsicmp(szMachineName,_T("")) == 0) { bReturn = TRUE; goto CRemoteExpandEnvironmentStrings_Exit; } // if it's the localmachine name // then set it to NULL // so that it will be treated as localmachine. if (IsLocalMachine(szMachineName)) { m_lpszUncServerName = NULL; bReturn = TRUE; goto CRemoteExpandEnvironmentStrings_Exit; } dwSize = (_tcslen(szMachineName) + 1 + 2) * sizeof(TCHAR); m_lpszUncServerName = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize); if (m_lpszUncServerName) { // check if szMachineName already starts with "\\" if (szMachineName[0] == _T('\\') && szMachineName[1] == _T('\\')) { _tcscpy(m_lpszUncServerName, szMachineName); } else { _tcscpy(m_lpszUncServerName, _T("\\\\")); _tcscat(m_lpszUncServerName, szMachineName); } bReturn = TRUE; } // if the machine name is different from what it was before // then delete the current environment if any... if (m_lpszUncServerName && lpszUncServerNameOriginal) { if (0 != _tcsicmp(lpszUncServerNameOriginal,m_lpszUncServerName)) { DeleteRemoteEnvironment(); } } else { DeleteRemoteEnvironment(); } CRemoteExpandEnvironmentStrings_Exit: if (lpszUncServerNameOriginal) {LocalFree(lpszUncServerNameOriginal);lpszUncServerNameOriginal=NULL;} return bReturn; } DWORD CRemoteExpandEnvironmentStrings::GetRegKeyMaxSizes( IN HKEY WinRegHandle, OUT LPDWORD MaxKeywordSize OPTIONAL, OUT LPDWORD MaxValueSize OPTIONAL ) { LONG Error; DWORD MaxValueNameLength; DWORD MaxValueDataLength; Error = RegQueryInfoKey( WinRegHandle, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxValueNameLength, &MaxValueDataLength, NULL, NULL ); if (ERROR_SUCCESS == Error) { // // MaxValueNameLength is a count of TCHARs. // MaxValueDataLength is a count of bytes already. // MaxValueNameLength = (MaxValueNameLength + 1) * sizeof(TCHAR); if (MaxKeywordSize) { *MaxKeywordSize = MaxValueNameLength; } if (MaxValueSize) { *MaxValueSize = MaxValueDataLength; } } return (Error); } NET_API_STATUS CRemoteExpandEnvironmentStrings::RemoteExpandEnvironmentStrings( IN LPCTSTR UnexpandedString, OUT LPTSTR * ValueBufferPtr // Must be freed by LocalFree(). ) /*++ Routine Description: This function expands a value string (which may include references to environment variables). For instance, an unexpanded string might be: %SystemRoot%\System32\Repl\Export This could be expanded to: c:\nt\System32\Repl\Export The expansion makes use of environment variables on m_lpszUncServerName, if given. This allows remote administration of the directory replicator. Arguments: m_lpszUncServerName - assumed to NOT BE EXPLICIT LOCAL SERVER NAME. UnexpandedString - points to source string to be expanded. ValueBufferPtr - indicates a pointer which will be set by this routine. This routine will allocate memory for a null-terminated string. The caller must free this with LocalFree() or equivalent. Return Value: NET_API_STATUS --*/ { NET_API_STATUS ApiStatus = NO_ERROR; LPTSTR ExpandedString = NULL; DWORD LastAllocationSize = 0; NTSTATUS NtStatus; // // Check for caller errors. // if (ValueBufferPtr == NULL) { // Can't goto Cleanup here, as it assumes this pointer is valid return (ERROR_INVALID_PARAMETER); } *ValueBufferPtr = NULL; // assume error until proven otherwise. if (UnexpandedString == NULL) { ApiStatus = ERROR_INVALID_PARAMETER; goto Cleanup; } // // This is probably just a constant string. // if (wcschr( UnexpandedString, _T('%') ) == NULL) { // Just need to allocate a copy of the input string. DWORD dwSize = (_tcslen(UnexpandedString) + 1) * sizeof(TCHAR); ExpandedString = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize); if (ExpandedString == NULL) { ApiStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } else { RtlCopyMemory(ExpandedString, UnexpandedString, dwSize); } // That's all, folks! ApiStatus = NO_ERROR; // // Otherwise, is this local? Maybe we can // handle local expansion the easy (fast) way: using win32 API. // } else if (m_lpszUncServerName == NULL) { DWORD CharsRequired = wcslen(UnexpandedString)+1; do { // Clean up from previous pass. if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;} // Allocate the memory. ExpandedString = (LPTSTR) LocalAlloc(LMEM_FIXED, CharsRequired * sizeof(TCHAR)); if (ExpandedString == NULL) { ApiStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } LastAllocationSize = CharsRequired * sizeof(TCHAR); // Expand string using local env vars. CharsRequired = ExpandEnvironmentStrings(UnexpandedString,ExpandedString,LastAllocationSize / sizeof(TCHAR)); if (CharsRequired == 0) { ApiStatus = (NET_API_STATUS) GetLastError(); goto Cleanup; } } while ((CharsRequired*sizeof(TCHAR)) > LastAllocationSize); ApiStatus = NO_ERROR; // // Oh well, remote expansion required. // } else { DWORD DataType; LONG Error; UNICODE_STRING ExpandedUnicode; DWORD SizeRequired; UNICODE_STRING UnexpandedUnicode; // // Create a temporary environment, which we'll fill in and let RTL // routines do the expansion for us. // if (FALSE == NewRemoteEnvironment()) { ApiStatus = E_FAIL; goto Cleanup; } // // Loop until we have enough storage. // Expand the string. // SizeRequired = (_tcslen(UnexpandedString) + 1) * sizeof(TCHAR); // First pass, try same size RtlInitUnicodeString(&UnexpandedUnicode,(PCWSTR) UnexpandedString); do { // Clean up from previous pass. if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;} // Allocate the memory. ExpandedString = (LPTSTR) LocalAlloc(LMEM_FIXED, SizeRequired); if (ExpandedString == NULL) { ApiStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } LastAllocationSize = SizeRequired; ExpandedUnicode.MaximumLength = (USHORT)SizeRequired; ExpandedUnicode.Buffer = ExpandedString; NtStatus = RtlExpandEnvironmentStrings_U( m_pEnvironment, // env to use &UnexpandedUnicode, // source &ExpandedUnicode, // dest (PULONG) &SizeRequired ); // dest size needed next time. if ( NtStatus == STATUS_BUFFER_TOO_SMALL ) { continue; // try again with larger buffer. } else if ( !NT_SUCCESS( NtStatus ) ) { ApiStatus = E_FAIL;; goto Cleanup; } else { break; // All done. } } while (SizeRequired > LastAllocationSize); ApiStatus = NO_ERROR; } Cleanup: if (ApiStatus == NO_ERROR) { *ValueBufferPtr = ExpandedString; } else { *ValueBufferPtr = NULL; if (ExpandedString){LocalFree(ExpandedString);ExpandedString = NULL;} } return (ApiStatus); } BOOL CRemoteExpandEnvironmentStrings::BuildEnvironmentPath(void **pEnv, LPTSTR lpPathVariable, LPTSTR lpPathValue) { NTSTATUS Status; UNICODE_STRING Name; UNICODE_STRING Value; WCHAR lpTemp[1025]; DWORD cb; if (!*pEnv) { return(FALSE); } RtlInitUnicodeString(&Name, lpPathVariable); cb = 1024; Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR)); if (!Value.Buffer) { return(FALSE); } Value.Length = (USHORT)(sizeof(WCHAR) * cb); Value.MaximumLength = (USHORT)(sizeof(WCHAR) * cb); Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value); if (!NT_SUCCESS(Status)) { LocalFree(Value.Buffer); Value.Length = 0; *lpTemp = 0; } if (Value.Length) { lstrcpy(lpTemp, Value.Buffer); if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') ) { lstrcat(lpTemp, TEXT(";")); } LocalFree(Value.Buffer); } if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb)) { lstrcat(lpTemp, lpPathValue); RtlInitUnicodeString(&Value, lpTemp); Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value); } if (NT_SUCCESS(Status)) { return(TRUE); } return(FALSE); } DWORD CRemoteExpandEnvironmentStrings::ExpandUserEnvironmentStrings(void *pEnv, LPTSTR lpSrc, LPTSTR lpDst, DWORD nSize) { NTSTATUS Status; UNICODE_STRING Source, Destination; ULONG Length; RtlInitUnicodeString( &Source, lpSrc ); Destination.Buffer = lpDst; Destination.Length = 0; Destination.MaximumLength = (USHORT)(nSize* sizeof(WCHAR)); Length = 0; Status = RtlExpandEnvironmentStrings_U(pEnv, (PUNICODE_STRING)&Source, (PUNICODE_STRING)&Destination, &Length ); if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) { return( Length ); } else { return( 0 ); } } BOOL CRemoteExpandEnvironmentStrings::SetUserEnvironmentVariable(void **pEnv, LPTSTR lpVariable, LPTSTR lpValue, BOOL bOverwrite) { NTSTATUS Status; UNICODE_STRING Name; UNICODE_STRING Value; DWORD cb; TCHAR szValue[1024]; if (!*pEnv || !lpVariable || !*lpVariable) { return(FALSE); } RtlInitUnicodeString(&Name, lpVariable); cb = 1024; Value.Buffer = (PTCHAR)LocalAlloc(LPTR, cb*sizeof(WCHAR)); if (Value.Buffer) { Value.Length = (USHORT)cb; Value.MaximumLength = (USHORT)cb; Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value); LocalFree(Value.Buffer); if (NT_SUCCESS(Status) && !bOverwrite) { return(TRUE); } } if (lpValue && *lpValue) { // // Special case TEMP and TMP and shorten the path names // if ((!_tcsicmp(lpVariable, TEXT("TEMP"))) || (!_tcsicmp(lpVariable, TEXT("TMP")))) { if (!GetShortPathName (lpValue, szValue, 1024)) { lstrcpyn (szValue, lpValue, 1024); } } else { lstrcpyn (szValue, lpValue, 1024); } RtlInitUnicodeString(&Value, szValue); Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value); } else { Status = RtlSetEnvironmentVariable( pEnv, &Name, NULL); } return NT_SUCCESS(Status); } // Reads the system environment variables from the registry // and adds them to the environment block at pEnv. BOOL CRemoteExpandEnvironmentStrings::SetEnvironmentVariables(void **pEnv) { WCHAR lpValueName[MAX_PATH]; LPBYTE lpDataBuffer; DWORD cbDataBuffer; LPBYTE lpData; LPTSTR lpExpandedValue = NULL; DWORD cbValueName = MAX_PATH; DWORD cbData; DWORD dwType; DWORD dwIndex = 0; HKEY hkey; BOOL bResult; HKEY RootKey = DEFAULT_ROOT_KEY; if (ERROR_SUCCESS != RegConnectRegistry((LPTSTR) m_lpszUncServerName,DEFAULT_ROOT_KEY,& RootKey )) { return(FALSE); } if (RegOpenKeyExW(RootKey,REG_PATH_TO_ENV,REG_OPTION_NON_VOLATILE,KEY_READ,& hkey)) { return(FALSE); } cbDataBuffer = 4096; lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cbDataBuffer*sizeof(WCHAR)); if (lpDataBuffer == NULL) { RegCloseKey(hkey); return(FALSE); } lpData = lpDataBuffer; cbData = cbDataBuffer; bResult = TRUE; while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType, lpData, &cbData)) { if (cbValueName) { // // Limit environment variable length // lpData[MAX_ENV_VALUE_LEN-1] = TEXT('\0'); if (dwType == REG_SZ) { // // The path variables PATH, LIBPATH and OS2LIBPATH must have // their values apppended to the system path. // if ( !_tcsicmp(lpValueName, PATH_VARIABLE) || !_tcsicmp(lpValueName, LIBPATH_VARIABLE) || !_tcsicmp(lpValueName, OS2LIBPATH_VARIABLE) ) { BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpData); } else { // // the other environment variables are just set. // SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpData, TRUE); } } } dwIndex++; cbData = cbDataBuffer; cbValueName = MAX_PATH; } dwIndex = 0; cbData = cbDataBuffer; cbValueName = MAX_PATH; while (!RegEnumValue(hkey, dwIndex, lpValueName, &cbValueName, 0, &dwType, lpData, &cbData)) { if (cbValueName) { // // Limit environment variable length // lpData[MAX_ENV_VALUE_LEN-1] = TEXT('\0'); if (dwType == REG_EXPAND_SZ) { DWORD cb, cbNeeded; cb = 1024; lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR)); if (lpExpandedValue) { cbNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb); if (cbNeeded > cb) { LocalFree(lpExpandedValue); cb = cbNeeded; lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cb*sizeof(WCHAR)); if (lpExpandedValue) { ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cb); } } } if (lpExpandedValue == NULL) { bResult = FALSE; break; } // // The path variables PATH, LIBPATH and OS2LIBPATH must have // their values apppended to the system path. // if ( !_tcsicmp(lpValueName, PATH_VARIABLE) || !_tcsicmp(lpValueName, LIBPATH_VARIABLE) || !_tcsicmp(lpValueName, OS2LIBPATH_VARIABLE) ) { BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpExpandedValue); } else { // // the other environment variables are just set. // SetUserEnvironmentVariable(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE); } LocalFree(lpExpandedValue); } } dwIndex++; cbData = cbDataBuffer; cbValueName = MAX_PATH; } LocalFree(lpDataBuffer); RegCloseKey(hkey); return(bResult); } //************************************************************* // // SetEnvironmentVariableInBlock() // // Purpose: Sets the environment variable in the given block // // Parameters: pEnv - Environment block // lpVariable - Variables // lpValue - Value // bOverwrite - Overwrite // // // Return: TRUE if successful // FALSE if an error occurs // // Comments: // // History: Date Author Comment // 6/21/96 ericflo Ported // //************************************************************* BOOL CRemoteExpandEnvironmentStrings::SetEnvironmentVariableInBlock(PVOID *pEnv, LPTSTR lpVariable,LPTSTR lpValue, BOOL bOverwrite) { NTSTATUS Status; UNICODE_STRING Name, Value; DWORD cb; LPTSTR szValue = NULL; if (!*pEnv || !lpVariable || !*lpVariable) { return(FALSE); } RtlInitUnicodeString(&Name, lpVariable); cb = 1025 * sizeof(WCHAR); Value.Buffer = (PWSTR) LocalAlloc(LPTR, cb); if (Value.Buffer) { Value.Length = 0; Value.MaximumLength = (USHORT)cb; Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value); LocalFree(Value.Buffer); if ( NT_SUCCESS(Status) && !bOverwrite) { return(TRUE); } } szValue = (LPTSTR)LocalAlloc(LPTR, 1024*sizeof(TCHAR)); if (!szValue) { return FALSE; } if (lpValue && *lpValue) { // // Special case TEMP and TMP and shorten the path names // if ((!_tcsicmp(lpVariable, TEXT("TEMP"))) || (!_tcsicmp(lpVariable, TEXT("TMP")))) { if (!GetShortPathName (lpValue, szValue, 1024)) { lstrcpyn (szValue, lpValue, 1024); } } else { lstrcpyn (szValue, lpValue, 1024); } RtlInitUnicodeString(&Value, szValue); Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value); } else { Status = RtlSetEnvironmentVariable(pEnv, &Name, NULL); } LocalFree(szValue); if (NT_SUCCESS(Status)) { return(TRUE); } return(FALSE); } // Just set the environmental variables that we can // if we can't set them because of no access, no biggie DWORD CRemoteExpandEnvironmentStrings::SetOtherEnvironmentValues(void **pEnv) { DWORD dwResult = ERROR_SUCCESS; HKEY hKey = NULL; HKEY RootKey = DEFAULT_ROOT_KEY; DWORD dwType, dwSize; TCHAR szValue[MAX_ENV_VALUE_LEN + 1]; TCHAR szExpValue[MAX_ENV_VALUE_LEN + 1]; DWORD RandomValueSize = 0; LPTSTR RandomValueW = NULL; // try to connect to remote registry (or local registry if Null) dwResult = RegConnectRegistry((LPTSTR) m_lpszUncServerName,DEFAULT_ROOT_KEY,& RootKey); if (ERROR_SUCCESS != dwResult) { goto SetOtherEnvironmentValues_Exit; } dwResult = RegOpenKeyEx(RootKey,REG_PATH_TO_SYSROOT,REG_OPTION_NON_VOLATILE,KEY_READ,&hKey); if (ERROR_SUCCESS == dwResult) { dwResult = GetRegKeyMaxSizes( hKey, NULL, // don't need keyword size &RandomValueSize ); // set max value size. if (ERROR_SUCCESS != dwResult) { goto SetOtherEnvironmentValues_Exit; } RandomValueW = (LPTSTR) LocalAlloc(LMEM_FIXED, RandomValueSize); if (RandomValueW == NULL) { dwResult = ERROR_NOT_ENOUGH_MEMORY; } else { if (RegQueryValueEx(hKey,(LPTSTR)ENV_KEYWORD_SYSTEMROOT,REG_OPTION_NON_VOLATILE,&dwType,(LPBYTE) RandomValueW,&RandomValueSize) == ERROR_SUCCESS) { SetEnvironmentVariableInBlock(pEnv, ENV_KEYWORD_SYSTEMROOT, RandomValueW, TRUE); } } if (hKey) {RegCloseKey(hKey);} } dwResult = RegOpenKeyEx (RootKey, REG_PATH_TO_COMMON_FOLDERS, REG_OPTION_NON_VOLATILE, KEY_READ, &hKey); if (ERROR_SUCCESS == dwResult) { dwSize = (MAX_ENV_VALUE_LEN+1) * sizeof(TCHAR); if (RegQueryValueEx (hKey, ENV_KEYWORD_PROGRAMFILESDIR, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) { ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1)); SetEnvironmentVariableInBlock(pEnv, PROGRAMFILES_VARIABLE, szExpValue, TRUE); } dwSize = (MAX_ENV_VALUE_LEN+1) * sizeof(TCHAR); if (RegQueryValueEx (hKey, ENV_KEYWORD_COMMONFILESDIR, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) { ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1)); SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILES_VARIABLE, szExpValue, TRUE); } dwSize = (MAX_ENV_VALUE_LEN+1)*sizeof(TCHAR); if (RegQueryValueEx (hKey, ENV_KEYWORD_PROGRAMFILESDIR_X86, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) { ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1)); SetEnvironmentVariableInBlock(pEnv, PROGRAMFILESX86_VARIABLE, szExpValue, TRUE); } dwSize = (MAX_ENV_VALUE_LEN+1)*sizeof(TCHAR); if (RegQueryValueEx (hKey, ENV_KEYWORD_COMMONFILESDIR_X86, NULL, &dwType,(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) { ExpandEnvironmentStrings (szValue, szExpValue, (MAX_ENV_VALUE_LEN+1)); SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILESX86_VARIABLE, szExpValue, TRUE); } } SetOtherEnvironmentValues_Exit: if (RootKey != DEFAULT_ROOT_KEY) {RegCloseKey(RootKey);} if (hKey) {RegCloseKey(hKey);} return dwResult; }