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
984 lines
29 KiB
#include "stdafx.h"
|
|
#include "RemoteEnv.h"
|
|
#include "common.h"
|
|
#include <strsafe.h>
|
|
#include "cryptpass.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;
|
|
m_lpszUserName = NULL;
|
|
m_lpszUserPasswordEncrypted = NULL;
|
|
m_cbUserPasswordEncrypted = 0;
|
|
return;
|
|
}
|
|
|
|
CRemoteExpandEnvironmentStrings::~CRemoteExpandEnvironmentStrings()
|
|
{
|
|
DeleteRemoteEnvironment();
|
|
|
|
if (m_lpszUncServerName)
|
|
{
|
|
LocalFree(m_lpszUncServerName);
|
|
m_lpszUncServerName = NULL;
|
|
}
|
|
if (m_lpszUserName)
|
|
{
|
|
LocalFree(m_lpszUserName);
|
|
m_lpszUserName = NULL;
|
|
}
|
|
if (m_lpszUserPasswordEncrypted)
|
|
{
|
|
if (m_cbUserPasswordEncrypted > 0)
|
|
{
|
|
// erase any password we may have in memory -- even though it's encrypted in memory
|
|
SecureZeroMemory(m_lpszUserPasswordEncrypted,m_cbUserPasswordEncrypted);
|
|
}
|
|
LocalFree(m_lpszUserPasswordEncrypted);
|
|
}
|
|
m_lpszUserPasswordEncrypted = NULL;
|
|
m_cbUserPasswordEncrypted = 0;
|
|
|
|
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)
|
|
{
|
|
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
if (_tcsicmp(psz,_T("")) == 0)
|
|
{
|
|
// it's empty,
|
|
// yeah it's local machine
|
|
return TRUE;
|
|
}
|
|
|
|
// get the actual name of the local machine
|
|
if (!GetComputerName(szComputerName, &cbComputerName))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// compare and return
|
|
if (0 == _tcsicmp(szComputerName, psz))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
CRemoteExpandEnvironmentStrings::SetUserName(IN LPCTSTR szUserName)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
DWORD dwSize = 0;
|
|
LPTSTR lpszUserNameOriginal = NULL;
|
|
|
|
// free any previous thing we had...
|
|
if (m_lpszUserName)
|
|
{
|
|
// Make a copy of it before we delete it
|
|
dwSize = (_tcslen(m_lpszUserName) + 1) * sizeof(TCHAR);
|
|
lpszUserNameOriginal = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
|
|
if (lpszUserNameOriginal)
|
|
{
|
|
StringCbCopy(lpszUserNameOriginal,dwSize,m_lpszUserName);
|
|
}
|
|
|
|
// free up anything we had before
|
|
LocalFree(m_lpszUserName);
|
|
m_lpszUserName = NULL;
|
|
}
|
|
|
|
if (_tcsicmp(szUserName,_T("")) == 0)
|
|
{
|
|
bReturn = TRUE;
|
|
goto SetUserName_Exit;
|
|
}
|
|
|
|
dwSize = (_tcslen(szUserName) + 1 + 2) * sizeof(TCHAR);
|
|
m_lpszUserName = (LPTSTR) LocalAlloc(LMEM_ZEROINIT,dwSize);
|
|
if (m_lpszUserName)
|
|
{
|
|
StringCbCopy(m_lpszUserName,dwSize,szUserName);
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
SetUserName_Exit:
|
|
if (lpszUserNameOriginal)
|
|
{LocalFree(lpszUserNameOriginal);lpszUserNameOriginal=NULL;}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CRemoteExpandEnvironmentStrings::SetUserPassword(IN LPCTSTR szUserPassword)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
// free any previous thing we had...
|
|
if (m_lpszUserPasswordEncrypted)
|
|
{
|
|
// free up anything we had before
|
|
if (m_cbUserPasswordEncrypted > 0)
|
|
{
|
|
SecureZeroMemory(m_lpszUserPasswordEncrypted,m_cbUserPasswordEncrypted);
|
|
}
|
|
LocalFree(m_lpszUserPasswordEncrypted);
|
|
m_lpszUserPasswordEncrypted = NULL;
|
|
m_cbUserPasswordEncrypted = 0;
|
|
}
|
|
|
|
if (_tcsicmp(szUserPassword,_T("")) == 0)
|
|
{
|
|
bReturn = TRUE;
|
|
goto SetUserPassword_Exit;
|
|
}
|
|
|
|
// encrypt the password in memory (CryptProtectMemory)
|
|
// this way if the process get's paged out to the swapfile,
|
|
// the password won't be in clear text.
|
|
if (SUCCEEDED(EncryptMemoryPassword((LPWSTR) szUserPassword,&m_lpszUserPasswordEncrypted,&m_cbUserPasswordEncrypted)))
|
|
{
|
|
bReturn = TRUE;
|
|
goto SetUserPassword_Exit;
|
|
}
|
|
|
|
SetUserPassword_Exit:
|
|
return bReturn;
|
|
}
|
|
|
|
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)
|
|
{
|
|
StringCbCopy(lpszUncServerNameOriginal,dwSize,m_lpszUncServerName);
|
|
}
|
|
|
|
// free up anything we had before
|
|
LocalFree(m_lpszUncServerName);
|
|
m_lpszUncServerName = NULL;
|
|
}
|
|
|
|
if (_tcsicmp(szMachineName,_T("")) == 0)
|
|
{
|
|
bReturn = TRUE;
|
|
goto SetMachineName_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 SetMachineName_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('\\'))
|
|
{
|
|
StringCbCopy(m_lpszUncServerName,dwSize,szMachineName);
|
|
}
|
|
else
|
|
{
|
|
StringCbCopy(m_lpszUncServerName,dwSize,_T("\\\\"));
|
|
StringCbCat(m_lpszUncServerName,dwSize,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();
|
|
}
|
|
|
|
SetMachineName_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
|
|
{
|
|
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 = ERROR_NOT_ENOUGH_MEMORY;
|
|
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 = ERROR_NOT_ENOUGH_MEMORY;
|
|
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)
|
|
{
|
|
StringCbCopy(lpTemp,sizeof(lpTemp),Value.Buffer);
|
|
if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') )
|
|
{
|
|
StringCbCat(lpTemp,sizeof(lpTemp),TEXT(";"));
|
|
}
|
|
LocalFree(Value.Buffer);
|
|
}
|
|
if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cb))
|
|
{
|
|
StringCbCat(lpTemp,sizeof(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 ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
|
|
(!lstrcmpi(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 any of this fails...
|
|
// we should try to use the username/userpassword to connect to the server
|
|
// and try it again...
|
|
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 ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
|
|
!lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
|
|
!lstrcmpi(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 ( !lstrcmpi(lpValueName, PATH_VARIABLE) ||
|
|
!lstrcmpi(lpValueName, LIBPATH_VARIABLE) ||
|
|
!lstrcmpi(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 ((!lstrcmpi(lpVariable, TEXT("TEMP"))) ||
|
|
(!lstrcmpi(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;
|
|
|
|
// If any of this fails...
|
|
// we should try to use the username/userpassword to connect to the server
|
|
// and try it again...
|
|
|
|
// 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;
|
|
}
|