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.
1995 lines
54 KiB
1995 lines
54 KiB
//*************************************************************
|
|
// File name: envvar.c
|
|
//
|
|
// Description: Contains the environment variable functions
|
|
//
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1996
|
|
// All rights reserved
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "uenv.h"
|
|
#include "strsafe.h"
|
|
|
|
//
|
|
// Max environment variable length
|
|
//
|
|
|
|
#define MAX_VALUE_LEN 1024
|
|
|
|
//
|
|
// Environment variables
|
|
//
|
|
|
|
#define COMPUTERNAME_VARIABLE TEXT("COMPUTERNAME")
|
|
#define HOMEDRIVE_VARIABLE TEXT("HOMEDRIVE")
|
|
#define HOMESHARE_VARIABLE TEXT("HOMESHARE")
|
|
#define HOMEPATH_VARIABLE TEXT("HOMEPATH")
|
|
#define SYSTEMDRIVE_VARIABLE TEXT("SystemDrive")
|
|
#define SYSTEMROOT_VARIABLE TEXT("SystemRoot")
|
|
#define USERNAME_VARIABLE TEXT("USERNAME")
|
|
#define USERDOMAIN_VARIABLE TEXT("USERDOMAIN")
|
|
#define USERDNSDOMAIN_VARIABLE TEXT("USERDNSDOMAIN")
|
|
#define USERPROFILE_VARIABLE TEXT("USERPROFILE")
|
|
#define ALLUSERSPROFILE_VARIABLE TEXT("ALLUSERSPROFILE")
|
|
#define PATH_VARIABLE TEXT("Path")
|
|
#define LIBPATH_VARIABLE TEXT("LibPath")
|
|
#define OS2LIBPATH_VARIABLE TEXT("Os2LibPath")
|
|
#define PROGRAMFILES_VARIABLE TEXT("ProgramFiles")
|
|
#define COMMONPROGRAMFILES_VARIABLE TEXT("CommonProgramFiles")
|
|
#if defined(WX86) || defined(_WIN64)
|
|
#define PROGRAMFILESX86_VARIABLE TEXT("ProgramFiles(x86)")
|
|
#define COMMONPROGRAMFILESX86_VARIABLE TEXT("CommonProgramFiles(x86)")
|
|
#endif
|
|
#define USER_ENV_SUBKEY TEXT("Environment")
|
|
#define USER_VOLATILE_ENV_SUBKEY TEXT("Volatile Environment")
|
|
|
|
//
|
|
// Parsing information for autoexec.bat
|
|
//
|
|
#define AUTOEXECPATH_VARIABLE TEXT("AutoexecPath")
|
|
#define PARSE_AUTOEXEC_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
|
|
#define PARSE_AUTOEXEC_ENTRY TEXT("ParseAutoexec")
|
|
#define PARSE_AUTOEXEC_DEFAULT TEXT("1")
|
|
#define MAX_PARSE_AUTOEXEC_BUFFER 2
|
|
|
|
|
|
#define SYS_ENVVARS TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment")
|
|
|
|
BOOL UpdateSystemEnvironment(PVOID *pEnv);
|
|
BOOL GetUserNameAndDomain(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain);
|
|
BOOL GetUserNameAndDomainSlowly(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain);
|
|
LPTSTR GetUserDNSDomainName(LPTSTR lpDomain, HANDLE hUserToken);
|
|
LONG GetHKeyCU(HANDLE hToken, HKEY *hKeyCU);
|
|
BOOL ProcessAutoexec(PVOID *pEnv);
|
|
BOOL AppendNTPathWithAutoexecPath(PVOID *pEnv, LPTSTR lpPathVariable, LPTSTR lpAutoexecPath);
|
|
BOOL SetEnvironmentVariables(PVOID *pEnv, LPTSTR lpRegSubKey, HKEY hKeyCU);
|
|
#ifdef _X86_
|
|
BOOL IsPathIncludeRemovable(LPTSTR lpValue);
|
|
#endif
|
|
|
|
|
|
__inline BOOL SafeGetEnvironmentVariable(LPCTSTR lpName, LPTSTR lpBuffer, DWORD nSize)
|
|
{
|
|
DWORD dwRet = GetEnvironmentVariable(lpName, lpBuffer, nSize);
|
|
return (dwRet > 0) && (dwRet < nSize);
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateEnvironmentBlock()
|
|
//
|
|
// Purpose: Creates the environment variables for the
|
|
// specificed hToken. If hToken is NULL, the
|
|
// environment block will only contain system
|
|
// variables.
|
|
//
|
|
// Parameters: pEnv - Receives the environment block
|
|
// hToken - User's token or NULL
|
|
// bInherit - Inherit the current process environment
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if not
|
|
//
|
|
// Comments: The pEnv value must be destroyed by
|
|
// calling DestroyEnvironmentBlock
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/19/96 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateEnvironmentBlock (LPVOID *pEnv, HANDLE hToken, BOOL bInherit)
|
|
{
|
|
LPTSTR szBuffer = NULL;
|
|
LPTSTR szValue = NULL;
|
|
LPTSTR szExpValue = NULL;
|
|
DWORD dwBufferSize = MAX_PATH+1;
|
|
NTSTATUS Status;
|
|
LPTSTR UserName = NULL;
|
|
LPTSTR UserDomain = NULL;
|
|
LPTSTR UserDNSDomain = NULL;
|
|
HKEY hKey, hKeyCU;
|
|
DWORD dwDisp, dwType, dwSize;
|
|
TCHAR szParseAutoexec[MAX_PARSE_AUTOEXEC_BUFFER];
|
|
LONG dwError;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
//
|
|
// Arg check
|
|
//
|
|
|
|
if (!pEnv) {
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
goto Exit;
|
|
}
|
|
|
|
Status = RtlCreateEnvironment((BOOLEAN)bInherit, pEnv);
|
|
if (!NT_SUCCESS(Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for Local variables to avoid stack overflow
|
|
//
|
|
|
|
szBuffer = (LPTSTR)LocalAlloc(LPTR, (MAX_PATH+1)*sizeof(TCHAR));
|
|
if (!szBuffer) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
|
|
goto Exit;
|
|
}
|
|
|
|
szValue = (LPTSTR)LocalAlloc(LPTR, (MAX_VALUE_LEN+1)*sizeof(TCHAR));
|
|
if (!szValue) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
|
|
goto Exit;
|
|
}
|
|
|
|
szExpValue = (LPTSTR)LocalAlloc(LPTR, (MAX_VALUE_LEN+1)*sizeof(TCHAR));
|
|
if (!szExpValue) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Out of memory")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// First start by getting the systemroot and systemdrive values and
|
|
// setting it in the new environment.
|
|
//
|
|
|
|
if ( SafeGetEnvironmentVariable(SYSTEMROOT_VARIABLE, szBuffer, dwBufferSize) )
|
|
{
|
|
SetEnvironmentVariableInBlock(pEnv, SYSTEMROOT_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
if ( SafeGetEnvironmentVariable(SYSTEMDRIVE_VARIABLE, szBuffer, dwBufferSize) )
|
|
{
|
|
SetEnvironmentVariableInBlock(pEnv, SYSTEMDRIVE_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// Set the all users profile location.
|
|
//
|
|
|
|
dwBufferSize = MAX_PATH+1;
|
|
if (GetAllUsersProfileDirectory(szBuffer, &dwBufferSize)) {
|
|
SetEnvironmentVariableInBlock(pEnv, ALLUSERSPROFILE_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// We must examine the registry directly to pull out
|
|
// the system environment variables, because they
|
|
// may have changed since the system was booted.
|
|
//
|
|
|
|
if (!UpdateSystemEnvironment(pEnv)) {
|
|
RtlDestroyEnvironment(*pEnv);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Set the computername
|
|
//
|
|
|
|
dwBufferSize = MAX_PATH+1;
|
|
if (GetComputerName (szBuffer, &dwBufferSize)) {
|
|
SetEnvironmentVariableInBlock(pEnv, COMPUTERNAME_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// Set the default user profile location
|
|
//
|
|
|
|
dwBufferSize = MAX_PATH+1;
|
|
if (GetDefaultUserProfileDirectory(szBuffer, &dwBufferSize)) {
|
|
SetEnvironmentVariableInBlock(pEnv, USERPROFILE_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// Set the Program Files environment variable
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion"),
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
|
|
if (RegQueryValueEx (hKey, TEXT("ProgramFilesDir"), NULL, &dwType,
|
|
(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
if (SUCCEEDED(SafeExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1))))
|
|
SetEnvironmentVariableInBlock(pEnv, PROGRAMFILES_VARIABLE, szExpValue, TRUE);
|
|
}
|
|
|
|
dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
|
|
if (RegQueryValueEx (hKey, TEXT("CommonFilesDir"), NULL, &dwType,
|
|
(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
if (SUCCEEDED(SafeExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1))))
|
|
SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILES_VARIABLE, szExpValue, TRUE);
|
|
}
|
|
|
|
#if defined(WX86) || defined(_WIN64)
|
|
dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
|
|
if (RegQueryValueEx (hKey, TEXT("ProgramFilesDir (x86)"), NULL, &dwType,
|
|
(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
if (SUCCEEDED(SafeExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1))))
|
|
SetEnvironmentVariableInBlock(pEnv, PROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
|
|
}
|
|
|
|
dwSize = (MAX_VALUE_LEN+1)*sizeof(TCHAR);
|
|
if (RegQueryValueEx (hKey, TEXT("CommonFilesDir (x86)"), NULL, &dwType,
|
|
(LPBYTE) szValue, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
if (SUCCEEDED(SafeExpandEnvironmentStrings (szValue, szExpValue, (MAX_VALUE_LEN+1))))
|
|
SetEnvironmentVariableInBlock(pEnv, COMMONPROGRAMFILESX86_VARIABLE, szExpValue, TRUE);
|
|
}
|
|
#endif
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
//
|
|
// If hToken is NULL, we can exit now since the caller only wants
|
|
// system environment variables.
|
|
//
|
|
|
|
if (!hToken) {
|
|
bRetVal = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the HKEY_CURRENT_USER for this token.
|
|
//
|
|
|
|
dwError = GetHKeyCU(hToken, &hKeyCU);
|
|
|
|
//
|
|
// if the hive is not found assume that the caller just needs the system attribute.
|
|
//
|
|
|
|
if ((!hKeyCU) && (dwError == ERROR_FILE_NOT_FOUND)) {
|
|
bRetVal = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!hKeyCU) {
|
|
RtlDestroyEnvironment(*pEnv);
|
|
DebugMsg((DM_WARNING, TEXT("CreateEnvironmentBlock: Failed to open HKEY_CURRENT_USER, error = %d"), dwError));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Set the user's name and domain.
|
|
//
|
|
|
|
if (!GetUserNameAndDomain(hToken, &UserName, &UserDomain)) {
|
|
GetUserNameAndDomainSlowly(hToken, &UserName, &UserDomain);
|
|
}
|
|
UserDNSDomain = GetUserDNSDomainName(UserDomain, hToken);
|
|
SetEnvironmentVariableInBlock( pEnv, USERNAME_VARIABLE, UserName, TRUE);
|
|
SetEnvironmentVariableInBlock( pEnv, USERDOMAIN_VARIABLE, UserDomain, TRUE);
|
|
SetEnvironmentVariableInBlock( pEnv, USERDNSDOMAIN_VARIABLE, UserDNSDomain, TRUE);
|
|
LocalFree(UserName);
|
|
LocalFree(UserDomain);
|
|
LocalFree(UserDNSDomain);
|
|
|
|
|
|
//
|
|
// Set the user's profile location.
|
|
//
|
|
|
|
dwBufferSize = MAX_PATH+1;
|
|
if (GetUserProfileDirectory(hToken, szBuffer, &dwBufferSize)) {
|
|
SetEnvironmentVariableInBlock(pEnv, USERPROFILE_VARIABLE, szBuffer, TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// Process autoexec.bat
|
|
//
|
|
|
|
StringCchCopy (szParseAutoexec, ARRAYSIZE(szParseAutoexec), PARSE_AUTOEXEC_DEFAULT);
|
|
|
|
if (RegCreateKeyEx (hKeyCU, PARSE_AUTOEXEC_KEY, 0, 0,
|
|
REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
|
|
|
|
|
|
//
|
|
// Query the current value. If it doesn't exist, then add
|
|
// the entry for next time.
|
|
//
|
|
|
|
dwBufferSize = sizeof (TCHAR) * MAX_PARSE_AUTOEXEC_BUFFER;
|
|
if (RegQueryValueEx (hKey, PARSE_AUTOEXEC_ENTRY, NULL, &dwType,
|
|
(LPBYTE) szParseAutoexec, &dwBufferSize)
|
|
!= ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Set the default value
|
|
//
|
|
|
|
RegSetValueEx (hKey, PARSE_AUTOEXEC_ENTRY, 0, REG_SZ,
|
|
(LPBYTE) szParseAutoexec,
|
|
sizeof (TCHAR) * lstrlen (szParseAutoexec) + 1);
|
|
}
|
|
|
|
//
|
|
// Close key
|
|
//
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Process autoexec if appropriate
|
|
//
|
|
|
|
if (szParseAutoexec[0] == TEXT('1')) {
|
|
ProcessAutoexec(pEnv);
|
|
}
|
|
|
|
|
|
//
|
|
// Set User environment variables.
|
|
//
|
|
SetEnvironmentVariables(pEnv, USER_ENV_SUBKEY, hKeyCU);
|
|
|
|
|
|
//
|
|
// Set User volatile environment variables.
|
|
//
|
|
SetEnvironmentVariables(pEnv, USER_VOLATILE_ENV_SUBKEY, hKeyCU);
|
|
|
|
|
|
//
|
|
// Merge the paths
|
|
//
|
|
|
|
AppendNTPathWithAutoexecPath(pEnv, PATH_VARIABLE, AUTOEXECPATH_VARIABLE);
|
|
|
|
|
|
RegCloseKey (hKeyCU);
|
|
|
|
bRetVal = TRUE;
|
|
|
|
Exit:
|
|
|
|
if (szBuffer) {
|
|
LocalFree(szBuffer);
|
|
}
|
|
|
|
if (szValue) {
|
|
LocalFree(szValue);
|
|
}
|
|
|
|
if (szExpValue) {
|
|
LocalFree(szExpValue);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// DestroyEnvironmentBlock()
|
|
//
|
|
// Purpose: Frees the environment block created by
|
|
// CreateEnvironmentBlock
|
|
//
|
|
// Parameters: lpEnvironment - Pointer to variables
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/19/96 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI DestroyEnvironmentBlock (LPVOID lpEnvironment)
|
|
{
|
|
|
|
if (!lpEnvironment) {
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
RtlDestroyEnvironment(lpEnvironment);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// UpdateSystemEnvironment()
|
|
//
|
|
// Purpose: Reads the system environment variables from the
|
|
// registry.
|
|
//
|
|
// Parameters: pEnv - Environment block pointer
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/21/96 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL UpdateSystemEnvironment(PVOID *pEnv)
|
|
{
|
|
|
|
HKEY KeyHandle = NULL;
|
|
DWORD Result;
|
|
DWORD ValueNameLength;
|
|
DWORD Type;
|
|
DWORD DataLength;
|
|
DWORD cValues; /* address of buffer for number of value identifiers */
|
|
DWORD chMaxValueName; /* address of buffer for longest value name length */
|
|
DWORD cbMaxValueData; /* address of buffer for longest value data length */
|
|
FILETIME FileTime;
|
|
PTCHAR ValueName = NULL;
|
|
PTCHAR ValueData = NULL;
|
|
DWORD i;
|
|
BOOL Bool;
|
|
PTCHAR ExpandedValue;
|
|
BOOL rc = TRUE;
|
|
|
|
Result = RegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
SYS_ENVVARS,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&KeyHandle
|
|
);
|
|
|
|
if ( Result != ERROR_SUCCESS ) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: RegOpenKeyEx failed, error = %d"),Result));
|
|
return( TRUE );
|
|
}
|
|
|
|
Result = RegQueryInfoKey(
|
|
KeyHandle,
|
|
NULL, /* address of buffer for class string */
|
|
NULL, /* address of size of class string buffer */
|
|
NULL, /* reserved */
|
|
NULL, /* address of buffer for number of subkeys */
|
|
NULL, /* address of buffer for longest subkey */
|
|
NULL, /* address of buffer for longest class string length */
|
|
&cValues, /* address of buffer for number of value identifiers */
|
|
&chMaxValueName, /* address of buffer for longest value name length */
|
|
&cbMaxValueData, /* address of buffer for longest value data length */
|
|
NULL, /* address of buffer for descriptor length */
|
|
&FileTime /* address of buffer for last write time */
|
|
);
|
|
|
|
if ( Result != NO_ERROR && Result != ERROR_MORE_DATA ) {
|
|
DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: RegQueryInfoKey failed, error = %d"),Result));
|
|
rc = TRUE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// No need to adjust the datalength for TCHAR issues
|
|
//
|
|
|
|
ValueData = LocalAlloc(LPTR, cbMaxValueData);
|
|
|
|
if ( ValueData == NULL ) {
|
|
rc = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// The maximum value name length comes back in characters, convert to bytes
|
|
// before allocating storage. Allow for trailing NULL also.
|
|
//
|
|
|
|
ValueName = LocalAlloc(LPTR, (++chMaxValueName) * sizeof( TCHAR ) );
|
|
|
|
if ( ValueName == NULL ) {
|
|
rc = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// To exit from here on, set rc and jump to Cleanup
|
|
//
|
|
|
|
for (i=0; i<cValues ; i++) {
|
|
|
|
ValueNameLength = chMaxValueName;
|
|
DataLength = cbMaxValueData;
|
|
|
|
Result = RegEnumValue (
|
|
KeyHandle,
|
|
i,
|
|
ValueName,
|
|
&ValueNameLength, // Size in TCHARs
|
|
NULL,
|
|
&Type,
|
|
(LPBYTE)ValueData,
|
|
&DataLength // Size in bytes
|
|
);
|
|
|
|
if ( Result != ERROR_SUCCESS ) {
|
|
|
|
//
|
|
// Problem getting the value. We can either try
|
|
// the rest or punt completely.
|
|
//
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If the buffer size is greater than the max allowed,
|
|
// terminate the string at MAX_VALUE_LEN - 1.
|
|
//
|
|
|
|
if (DataLength >= (MAX_VALUE_LEN * sizeof(TCHAR))) {
|
|
ValueData[MAX_VALUE_LEN-1] = TEXT('\0');
|
|
}
|
|
|
|
switch ( Type ) {
|
|
case REG_SZ:
|
|
{
|
|
|
|
Bool = SetEnvironmentVariableInBlock(
|
|
pEnv,
|
|
ValueName,
|
|
ValueData,
|
|
TRUE
|
|
);
|
|
|
|
if ( !Bool ) {
|
|
DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: Failed to set environment variable <%s> to <%s> with %d."),
|
|
ValueName, ValueData, GetLastError()));
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// To exit from here on, set rc and jump to Cleanup
|
|
//
|
|
|
|
for (i=0; i<cValues ; i++) {
|
|
|
|
ValueNameLength = chMaxValueName;
|
|
DataLength = cbMaxValueData;
|
|
|
|
Result = RegEnumValue (
|
|
KeyHandle,
|
|
i,
|
|
ValueName,
|
|
&ValueNameLength, // Size in TCHARs
|
|
NULL,
|
|
&Type,
|
|
(LPBYTE)ValueData,
|
|
&DataLength // Size in bytes
|
|
);
|
|
|
|
if ( Result != ERROR_SUCCESS ) {
|
|
|
|
//
|
|
// Problem getting the value. We can either try
|
|
// the rest or punt completely.
|
|
//
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If the buffer size is greater than the max allowed,
|
|
// terminate the string at MAX_VALUE_LEN - 1.
|
|
//
|
|
|
|
if (DataLength >= (MAX_VALUE_LEN * sizeof(TCHAR))) {
|
|
ValueData[MAX_VALUE_LEN-1] = TEXT('\0');
|
|
}
|
|
|
|
switch ( Type ) {
|
|
case REG_EXPAND_SZ:
|
|
{
|
|
|
|
ExpandedValue = AllocAndExpandEnvironmentStrings( ValueData );
|
|
|
|
Bool = SetEnvironmentVariableInBlock(
|
|
pEnv,
|
|
ValueName,
|
|
ExpandedValue,
|
|
TRUE
|
|
);
|
|
|
|
LocalFree( ExpandedValue );
|
|
|
|
if ( !Bool ) {
|
|
DebugMsg((DM_WARNING, TEXT("UpdateSystemEnvironment: Failed to set environment variable <%s> to <%s> with %d."),
|
|
ValueName, ValueData, GetLastError()));
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (KeyHandle)
|
|
RegCloseKey(KeyHandle);
|
|
|
|
if (ValueName)
|
|
LocalFree( ValueName );
|
|
|
|
if (ValueData)
|
|
LocalFree( ValueData );
|
|
|
|
return( rc );
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetUserNameAndDomain()
|
|
//
|
|
// Purpose: Gets the user's name and domain
|
|
//
|
|
// Parameters: hToken - User's token
|
|
// UserName - Receives pointer to user's name
|
|
// UserDomain - Receives pointer to user's domain
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/21/96 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL GetUserNameAndDomain(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
LPTSTR lpTemp, lpDomain = NULL;
|
|
LPTSTR lpUserName, lpUserDomain;
|
|
HANDLE hOldToken;
|
|
DWORD dwSize;
|
|
|
|
|
|
//
|
|
// Impersonate the user
|
|
//
|
|
|
|
if (!ImpersonateUser(hToken, &hOldToken)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserNameAndDomain Failed to impersonate user")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the username in NT4 format
|
|
//
|
|
|
|
lpDomain = MyGetUserNameEx (NameSamCompatible);
|
|
|
|
RevertToUser(&hOldToken);
|
|
|
|
if (!lpDomain) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain: MyGetUserNameEx failed for NT4 style name with %d"),
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Look for the \ between the domain and username and replace
|
|
// it with a NULL
|
|
//
|
|
|
|
lpTemp = lpDomain;
|
|
|
|
while (*lpTemp && ((*lpTemp) != TEXT('\\')))
|
|
lpTemp++;
|
|
|
|
|
|
if (*lpTemp != TEXT('\\')) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to find slash in NT4 style name: <%s>"),
|
|
lpDomain));
|
|
goto Exit;
|
|
}
|
|
|
|
*lpTemp = TEXT('\0');
|
|
lpTemp++;
|
|
|
|
|
|
//
|
|
// Allocate space for the results
|
|
//
|
|
|
|
dwSize = lstrlen(lpTemp) + 1;
|
|
lpUserName = LocalAlloc (LPTR, dwSize * sizeof(TCHAR));
|
|
|
|
if (!lpUserName) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to allocate memory with %d"),
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
StringCchCopy (lpUserName, dwSize, lpTemp);
|
|
|
|
|
|
dwSize = lstrlen(lpDomain) + 1;
|
|
lpUserDomain = LocalAlloc (LPTR, dwSize * sizeof(TCHAR));
|
|
|
|
if (!lpUserDomain) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserNameAndDomain Failed to allocate memory with %d"),
|
|
GetLastError()));
|
|
LocalFree (lpUserName);
|
|
goto Exit;
|
|
}
|
|
|
|
StringCchCopy (lpUserDomain, dwSize, lpDomain);
|
|
|
|
|
|
//
|
|
// Save the results in the outbound arguments
|
|
//
|
|
|
|
*UserName = lpUserName;
|
|
*UserDomain = lpUserDomain;
|
|
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
|
|
if (lpDomain) {
|
|
LocalFree (lpDomain);
|
|
}
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetUserNameAndDomainSlowly()
|
|
//
|
|
// Purpose: Gets the user's name and domain from a DC
|
|
//
|
|
// Parameters: hToken - User's token
|
|
// UserName - Receives pointer to user's name
|
|
// UserDomain - Receives pointer to user's domain
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/21/96 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL GetUserNameAndDomainSlowly(HANDLE hToken, LPTSTR *UserName, LPTSTR *UserDomain)
|
|
{
|
|
LPTSTR lpUserName = NULL;
|
|
LPTSTR lpUserDomain = NULL;
|
|
DWORD cbAccountName = 0;
|
|
DWORD cbUserDomain = 0;
|
|
SID_NAME_USE SidNameUse;
|
|
BOOL bRet = FALSE;
|
|
PSID pSid;
|
|
|
|
|
|
//
|
|
// Get the user's sid
|
|
//
|
|
|
|
pSid = GetUserSid (hToken);
|
|
|
|
if (!pSid) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the space needed for the User name and the Domain name
|
|
//
|
|
if (!LookupAccountSid(NULL,
|
|
pSid,
|
|
NULL, &cbAccountName,
|
|
NULL, &cbUserDomain,
|
|
&SidNameUse
|
|
) ) {
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
lpUserName = (LPTSTR)LocalAlloc(LPTR, cbAccountName*sizeof(TCHAR));
|
|
if (!lpUserName) {
|
|
goto Error;
|
|
}
|
|
|
|
lpUserDomain = (LPTSTR)LocalAlloc(LPTR, cbUserDomain*sizeof(WCHAR));
|
|
if (!lpUserDomain) {
|
|
LocalFree(lpUserName);
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Now get the user name and domain name
|
|
//
|
|
if (!LookupAccountSid(NULL,
|
|
pSid,
|
|
lpUserName, &cbAccountName,
|
|
lpUserDomain, &cbUserDomain,
|
|
&SidNameUse
|
|
) ) {
|
|
|
|
LocalFree(lpUserName);
|
|
LocalFree(lpUserDomain);
|
|
goto Error;
|
|
}
|
|
|
|
*UserName = lpUserName;
|
|
*UserDomain = lpUserDomain;
|
|
bRet = TRUE;
|
|
|
|
Error:
|
|
DeleteUserSid (pSid);
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetUserDNSDomainName()
|
|
//
|
|
// Purpose: Gets the DNS domain name for the user
|
|
//
|
|
// Parameters: lpDomain - User's flat domain name
|
|
// hUserToken - User's token
|
|
//
|
|
//
|
|
// Return: DNS domain name if successful
|
|
// NULL if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
LPTSTR GetUserDNSDomainName(LPTSTR lpDomain, HANDLE hUserToken)
|
|
{
|
|
LPTSTR lpDnsDomain = NULL, lpTemp = NULL;
|
|
DWORD dwBufferSize;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
INT iRole;
|
|
HANDLE hOldToken;
|
|
BOOL bResult = FALSE;
|
|
|
|
|
|
//
|
|
// Check if this machine is running standalone, if so, there won't be
|
|
// a DNS domain name
|
|
//
|
|
|
|
if (!GetMachineRole (&iRole)) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: Failed to get the role of the computer.")));
|
|
return NULL;
|
|
}
|
|
|
|
if (iRole == 0) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Computer is running standalone. No DNS domain name available.")));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the computer name to see if the user logged on locally
|
|
//
|
|
|
|
dwBufferSize = ARRAYSIZE(szBuffer);
|
|
|
|
if (GetComputerName (szBuffer, &dwBufferSize)) {
|
|
if (!lstrcmpi(lpDomain, szBuffer)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Local user account. No DNS domain name available.")));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (LoadString (g_hDllInstance, IDS_NT_AUTHORITY, szBuffer, ARRAYSIZE(szBuffer))) {
|
|
if (!lstrcmpi(lpDomain, szBuffer)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Domain name is NT Authority. No DNS domain name available.")));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (LoadString (g_hDllInstance, IDS_BUILTIN, szBuffer, ARRAYSIZE(szBuffer))) {
|
|
if (!lstrcmpi(lpDomain, szBuffer)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Domain name is BuiltIn. No DNS domain name available.")));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Impersonate the user
|
|
//
|
|
|
|
if (!ImpersonateUser(hUserToken, &hOldToken)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetUserDNSDomainName: Failed to impersonate user")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the username in DnsDomainName format
|
|
//
|
|
|
|
lpDnsDomain = MyGetUserNameEx (NameDnsDomain);
|
|
|
|
RevertToUser(&hOldToken);
|
|
|
|
if (!lpDnsDomain) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: MyGetUserNameEx failed for NameDnsDomain style name with %d"),
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Look for the \ between the domain and username and replace
|
|
// it with a NULL
|
|
//
|
|
|
|
lpTemp = lpDnsDomain;
|
|
|
|
while (*lpTemp && (*lpTemp != TEXT('\\')))
|
|
lpTemp++;
|
|
|
|
|
|
if (*lpTemp != TEXT('\\')) {
|
|
DebugMsg((DM_WARNING, TEXT("GetUserDNSDomainName: Failed to find slash in NameDnsDomain style name: <%s>"),
|
|
lpDnsDomain));
|
|
goto Exit;
|
|
}
|
|
|
|
*lpTemp = TEXT('\0');
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
|
|
if (!bResult && lpDnsDomain) {
|
|
LocalFree(lpDnsDomain);
|
|
lpDnsDomain = NULL;
|
|
}
|
|
|
|
return lpDnsDomain;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetHKeyCU()
|
|
//
|
|
// Purpose: Get HKEY_CURRENT_USER for the given hToken
|
|
//
|
|
// Parameters: hToken - token handle
|
|
//
|
|
// Return: hKey if successful
|
|
// NULL if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/21/96 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
LONG GetHKeyCU(HANDLE hToken, HKEY *hKeyCU)
|
|
{
|
|
LPTSTR lpSidString;
|
|
LONG dwError;
|
|
|
|
|
|
*hKeyCU = NULL;
|
|
|
|
lpSidString = GetSidString (hToken);
|
|
|
|
if (!lpSidString) {
|
|
return GetLastError();
|
|
}
|
|
|
|
dwError = RegOpenKeyEx (HKEY_USERS, lpSidString, 0, KEY_READ, hKeyCU);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
DebugMsg((DM_VERBOSE, TEXT("GetHkeyCU: RegOpenKey failed with error %d"), dwError));
|
|
|
|
DeleteSidString(lpSidString);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ProcessAutoexecPath
|
|
*
|
|
* Creates AutoexecPath environment variable using autoexec.bat
|
|
* LpValue may be freed by this routine.
|
|
*
|
|
* History:
|
|
* 06-02-92 Johannec Created.
|
|
*
|
|
\***************************************************************************/
|
|
LPTSTR ProcessAutoexecPath(PVOID pEnv, LPTSTR lpValue, DWORD cb)
|
|
{
|
|
LPTSTR lpt;
|
|
LPTSTR lpStart;
|
|
LPTSTR lpPath;
|
|
DWORD ccht;
|
|
UNICODE_STRING Name;
|
|
UNICODE_STRING Value;
|
|
BOOL bPrevAutoexecPath;
|
|
WCHAR ch;
|
|
DWORD dwTemp, dwCount = 0;
|
|
|
|
ccht = 1024;
|
|
lpt = (LPTSTR)LocalAlloc(LPTR, ccht*sizeof(WCHAR));
|
|
if (!lpt) {
|
|
return(lpValue);
|
|
}
|
|
*lpt = 0;
|
|
lpStart = lpValue;
|
|
|
|
RtlInitUnicodeString(&Name, AUTOEXECPATH_VARIABLE);
|
|
Value.Buffer = (PWCHAR)LocalAlloc(LPTR, ccht*sizeof(WCHAR));
|
|
if (!Value.Buffer) {
|
|
goto Fail;
|
|
}
|
|
|
|
while (NULL != (lpPath = wcsstr (lpValue, TEXT("%")))) {
|
|
if (!_wcsnicmp(lpPath+1, TEXT("PATH%"), 5)) {
|
|
//
|
|
// check if we have an autoexecpath already set, if not just remove
|
|
// the %path%
|
|
//
|
|
Value.Length = (USHORT)ccht * sizeof(WCHAR);
|
|
Value.MaximumLength = (USHORT)ccht * sizeof(WCHAR);
|
|
bPrevAutoexecPath = (BOOL)!RtlQueryEnvironmentVariable_U(pEnv, &Name, &Value);
|
|
|
|
*lpPath = 0;
|
|
dwTemp = dwCount + lstrlen (lpValue);
|
|
if (dwTemp < ccht) {
|
|
StringCchCat(lpt, ccht, lpValue);
|
|
dwCount = dwTemp;
|
|
}
|
|
if (bPrevAutoexecPath) {
|
|
dwTemp = dwCount + lstrlen (Value.Buffer);
|
|
if (dwTemp < ccht) {
|
|
StringCchCat(lpt, ccht, Value.Buffer);
|
|
dwCount = dwTemp;
|
|
}
|
|
}
|
|
|
|
*lpPath++ = TEXT('%');
|
|
lpPath += 5; // go passed %path%
|
|
lpValue = lpPath;
|
|
}
|
|
else {
|
|
lpPath = wcsstr(lpPath+1, TEXT("%"));
|
|
if (!lpPath) {
|
|
lpStart = NULL;
|
|
goto Fail;
|
|
}
|
|
lpPath++;
|
|
ch = *lpPath;
|
|
*lpPath = 0;
|
|
dwTemp = dwCount + lstrlen (lpValue);
|
|
if (dwTemp < ccht) {
|
|
StringCchCat(lpt, ccht, lpValue);
|
|
dwCount = dwTemp;
|
|
}
|
|
*lpPath = ch;
|
|
lpValue = lpPath;
|
|
}
|
|
}
|
|
|
|
if (*lpValue) {
|
|
dwTemp = dwCount + lstrlen (lpValue);
|
|
if (dwTemp < ccht) {
|
|
StringCchCat(lpt, ccht, lpValue);
|
|
dwCount = dwTemp;
|
|
}
|
|
}
|
|
|
|
LocalFree(Value.Buffer);
|
|
LocalFree(lpStart);
|
|
|
|
return(lpt);
|
|
Fail:
|
|
LocalFree(lpt);
|
|
return(lpStart);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ProcessCommand
|
|
*
|
|
* History:
|
|
* 01-24-92 Johannec Created.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL ProcessCommand(LPSTR lpStart, PVOID *pEnv)
|
|
{
|
|
LPTSTR lpt, lptt;
|
|
LPTSTR lpVariable;
|
|
LPTSTR lpValue;
|
|
LPTSTR lpExpandedValue = NULL;
|
|
WCHAR c;
|
|
DWORD cch, cchNeeded;
|
|
LPTSTR lpu;
|
|
DWORD cchVariable, cchValue;
|
|
|
|
//
|
|
// convert to Unicode
|
|
//
|
|
lpu = (LPTSTR)LocalAlloc(LPTR, (cch=lstrlenA(lpStart)+1)*sizeof(WCHAR));
|
|
|
|
if (!lpu) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!MultiByteToWideChar(CP_OEMCP, 0, lpStart, -1, lpu, cch)) {
|
|
LocalFree(lpu);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Find environment variable.
|
|
//
|
|
for (lpt = lpu; *lpt && *lpt == TEXT(' '); lpt++) //skip spaces
|
|
;
|
|
|
|
if (!*lpt) {
|
|
LocalFree (lpu);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
lptt = lpt;
|
|
for (; *lpt && *lpt != TEXT(' ') && *lpt != TEXT('='); lpt++) //find end of variable name
|
|
;
|
|
|
|
c = *lpt;
|
|
*lpt = 0;
|
|
cchVariable = lstrlen(lptt) + 1;
|
|
lpVariable = (LPTSTR)LocalAlloc(LPTR, cchVariable*sizeof(WCHAR));
|
|
if (!lpVariable) {
|
|
LocalFree (lpu);
|
|
return(FALSE);
|
|
}
|
|
|
|
StringCchCopy(lpVariable, cchVariable, lptt);
|
|
*lpt = c;
|
|
|
|
//
|
|
// Find environment variable value.
|
|
//
|
|
for (; *lpt && (*lpt == TEXT(' ') || *lpt == TEXT('=')); lpt++)
|
|
;
|
|
|
|
if (!*lpt) {
|
|
// if we have a blank path statement in the autoexec file,
|
|
// then we don't want to pass "PATH" as the environment
|
|
// variable because it trashes the system's PATH. Instead
|
|
// we want to change the variable AutoexecPath. This would have
|
|
// be handled below if a value had been assigned to the
|
|
// environment variable.
|
|
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, PATH_VARIABLE, -1) == CSTR_EQUAL)
|
|
{
|
|
SetEnvironmentVariableInBlock(pEnv, AUTOEXECPATH_VARIABLE, TEXT(""), TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetEnvironmentVariableInBlock(pEnv, lpVariable, TEXT(""), TRUE);
|
|
}
|
|
LocalFree (lpVariable);
|
|
LocalFree (lpu);
|
|
return(FALSE);
|
|
}
|
|
|
|
lptt = lpt;
|
|
for (; *lpt; lpt++) //find end of varaible value
|
|
;
|
|
|
|
c = *lpt;
|
|
*lpt = 0;
|
|
cchValue = lstrlen(lptt) + 1;
|
|
lpValue = (LPTSTR)LocalAlloc(LPTR, cchValue*sizeof(WCHAR));
|
|
if (!lpValue) {
|
|
LocalFree (lpu);
|
|
LocalFree(lpVariable);
|
|
return(FALSE);
|
|
}
|
|
|
|
StringCchCopy(lpValue, cchValue, lptt);
|
|
*lpt = c;
|
|
|
|
#ifdef _X86_
|
|
// NEC98
|
|
//
|
|
// If the path includes removable drive,
|
|
// it is assumed that the drive assignment has changed from DOS.
|
|
//
|
|
if (IsNEC_98 &&
|
|
(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, PATH_VARIABLE, -1) == CSTR_EQUAL) &&
|
|
IsPathIncludeRemovable(lpValue))
|
|
{
|
|
LocalFree (lpu);
|
|
LocalFree(lpVariable);
|
|
LocalFree(lpValue);
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
|
|
cch = 1024;
|
|
lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (lpExpandedValue) {
|
|
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, PATH_VARIABLE, -1) == CSTR_EQUAL)
|
|
{
|
|
lpValue = ProcessAutoexecPath(*pEnv, lpValue, (lstrlen(lpValue)+1)*sizeof(WCHAR));
|
|
}
|
|
cchNeeded = ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cch);
|
|
if (cchNeeded > cch) {
|
|
LocalFree(lpExpandedValue);
|
|
cch = cchNeeded;
|
|
lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (lpExpandedValue) {
|
|
ExpandUserEnvironmentStrings(*pEnv, lpValue, lpExpandedValue, cch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!lpExpandedValue) {
|
|
lpExpandedValue = lpValue;
|
|
}
|
|
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, PATH_VARIABLE, -1) == CSTR_EQUAL)
|
|
{
|
|
SetEnvironmentVariableInBlock(pEnv, AUTOEXECPATH_VARIABLE, lpExpandedValue, TRUE);
|
|
}
|
|
else {
|
|
SetEnvironmentVariableInBlock(pEnv, lpVariable, lpExpandedValue, FALSE);
|
|
}
|
|
|
|
if (lpExpandedValue != lpValue) {
|
|
LocalFree(lpExpandedValue);
|
|
}
|
|
LocalFree(lpVariable);
|
|
LocalFree(lpValue);
|
|
LocalFree (lpu);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ProcessSetCommand
|
|
*
|
|
* History:
|
|
* 01-24-92 Johannec Created.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL ProcessSetCommand(LPSTR lpStart, PVOID *pEnv)
|
|
{
|
|
LPSTR lpt;
|
|
|
|
//
|
|
// Find environment variable.
|
|
//
|
|
for (lpt = lpStart; *lpt && *lpt != TEXT(' '); lpt++)
|
|
;
|
|
|
|
if (!*lpt)
|
|
return(FALSE);
|
|
|
|
return (ProcessCommand(lpt, pEnv));
|
|
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ProcessAutoexec
|
|
*
|
|
* History:
|
|
* 01-24-92 Johannec Created.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL
|
|
ProcessAutoexec(
|
|
PVOID *pEnv
|
|
)
|
|
{
|
|
HANDLE fh = NULL;
|
|
DWORD dwFileSize;
|
|
DWORD dwBytesRead;
|
|
CHAR *lpBuffer = NULL;
|
|
CHAR *token;
|
|
CHAR Seps[] = "&\n\r"; // Seperators for tokenizing autoexec.bat
|
|
BOOL Status = FALSE;
|
|
TCHAR szAutoExecBat [] = TEXT("c:\\autoexec.bat");
|
|
#ifdef _X86_
|
|
TCHAR szTemp[3];
|
|
#endif
|
|
UINT uiErrMode;
|
|
|
|
|
|
// There is a case where the OS might not be booting from drive
|
|
// C, so we can not assume that the autoexec.bat file is on c:\.
|
|
// Set the error mode so the user doesn't see the critical error
|
|
// popup and attempt to open the file on c:\.
|
|
|
|
uiErrMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
|
|
|
#ifdef _X86_
|
|
if (IsNEC_98) {
|
|
if (GetEnvironmentVariable (TEXT("SystemDrive"), szTemp, 3)) {
|
|
szAutoExecBat[0] = szTemp[0];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// if autoexec.bat is encrypted then ignore it as it creates cyclic-dependency
|
|
// and don't allow any user to logon
|
|
|
|
if (GetFileAttributes(szAutoExecBat) & FILE_ATTRIBUTE_ENCRYPTED) {
|
|
SetErrorMode(uiErrMode);
|
|
goto Exit;
|
|
}
|
|
|
|
fh = CreateFile (szAutoExecBat, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
SetErrorMode (uiErrMode);
|
|
|
|
if (fh == INVALID_HANDLE_VALUE) {
|
|
goto Exit; //could not open autoexec.bat file, we're done.
|
|
}
|
|
dwFileSize = GetFileSize(fh, NULL);
|
|
if (dwFileSize == -1) {
|
|
goto Exit; // can't read the file size
|
|
}
|
|
|
|
lpBuffer = (PCHAR)LocalAlloc(LPTR, dwFileSize+1);
|
|
if (!lpBuffer) {
|
|
goto Exit;
|
|
}
|
|
|
|
Status = ReadFile(fh, lpBuffer, dwFileSize, &dwBytesRead, NULL);
|
|
if (!Status) {
|
|
goto Exit; // error reading file
|
|
}
|
|
|
|
//
|
|
// Zero terminate the buffer so we don't walk off the end
|
|
//
|
|
|
|
DmAssert(dwBytesRead <= dwFileSize);
|
|
lpBuffer[dwBytesRead] = 0;
|
|
|
|
//
|
|
// Search for SET and PATH commands
|
|
//
|
|
|
|
token = strtok(lpBuffer, Seps);
|
|
while (token != NULL) {
|
|
for (;*token && *token == ' ';token++) //skip spaces
|
|
;
|
|
if (*token == TEXT('@'))
|
|
token++;
|
|
for (;*token && *token == ' ';token++) //skip spaces
|
|
;
|
|
if (!_strnicmp(token, "Path", 4)) {
|
|
ProcessCommand(token, pEnv);
|
|
}
|
|
if (!_strnicmp(token, "SET", 3)) {
|
|
ProcessSetCommand(token, pEnv);
|
|
}
|
|
token = strtok(NULL, Seps);
|
|
}
|
|
Exit:
|
|
if (fh) {
|
|
CloseHandle(fh);
|
|
}
|
|
if (lpBuffer) {
|
|
LocalFree(lpBuffer);
|
|
}
|
|
if (!Status) {
|
|
DebugMsg((DM_WARNING, TEXT("ProcessAutoexec: Cannot process autoexec.bat.")));
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* BuildEnvironmentPath
|
|
*
|
|
*
|
|
* History:
|
|
* 2-28-92 Johannec Created
|
|
*
|
|
\***************************************************************************/
|
|
BOOL BuildEnvironmentPath(PVOID *pEnv,
|
|
LPTSTR lpPathVariable,
|
|
LPTSTR lpPathValue)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING Name;
|
|
UNICODE_STRING Value;
|
|
WCHAR lpTemp[1025];
|
|
DWORD cch;
|
|
|
|
|
|
if (!*pEnv) {
|
|
return(FALSE);
|
|
}
|
|
RtlInitUnicodeString(&Name, lpPathVariable);
|
|
cch = 1024;
|
|
Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (!Value.Buffer) {
|
|
return(FALSE);
|
|
}
|
|
Value.Length = (USHORT)(sizeof(WCHAR) * cch);
|
|
Value.MaximumLength = (USHORT)(sizeof(WCHAR) * cch);
|
|
Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
|
|
if (!NT_SUCCESS(Status)) {
|
|
LocalFree(Value.Buffer);
|
|
Value.Length = 0;
|
|
*lpTemp = 0;
|
|
}
|
|
if (Value.Length) {
|
|
StringCchCopy(lpTemp, ARRAYSIZE(lpTemp), Value.Buffer);
|
|
if ( *( lpTemp + lstrlen(lpTemp) - 1) != TEXT(';') ) {
|
|
StringCchCat(lpTemp, ARRAYSIZE(lpTemp), TEXT(";"));
|
|
}
|
|
LocalFree(Value.Buffer);
|
|
}
|
|
if (lpPathValue && ((lstrlen(lpTemp) + lstrlen(lpPathValue) + 1) < (INT)cch)) {
|
|
StringCchCat(lpTemp, ARRAYSIZE(lpTemp), lpPathValue);
|
|
|
|
RtlInitUnicodeString(&Value, lpTemp);
|
|
|
|
Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value);
|
|
}
|
|
if (NT_SUCCESS(Status)) {
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* AppendNTPathWithAutoexecPath
|
|
*
|
|
* Gets the AutoexecPath created in ProcessAutoexec, and appends it to
|
|
* the NT path.
|
|
*
|
|
* History:
|
|
* 05-28-92 Johannec Created.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL
|
|
AppendNTPathWithAutoexecPath(
|
|
PVOID *pEnv,
|
|
LPTSTR lpPathVariable,
|
|
LPTSTR lpAutoexecPath
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING Name;
|
|
UNICODE_STRING Value;
|
|
WCHAR AutoexecPathValue[1024];
|
|
DWORD cch;
|
|
BOOL Success;
|
|
|
|
if (!*pEnv) {
|
|
return(FALSE);
|
|
}
|
|
|
|
RtlInitUnicodeString(&Name, lpAutoexecPath);
|
|
cch = 1024;
|
|
Value.Buffer = (PWCHAR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (!Value.Buffer) {
|
|
return(FALSE);
|
|
}
|
|
|
|
Value.Length = (USHORT)cch*sizeof(WCHAR);
|
|
Value.MaximumLength = (USHORT)cch*sizeof(WCHAR);
|
|
Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
|
|
if (!NT_SUCCESS(Status)) {
|
|
LocalFree(Value.Buffer);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (Value.Length) {
|
|
StringCchCopy(AutoexecPathValue, ARRAYSIZE(AutoexecPathValue), Value.Buffer);
|
|
}
|
|
|
|
LocalFree(Value.Buffer);
|
|
|
|
Success = BuildEnvironmentPath(pEnv, lpPathVariable, AutoexecPathValue);
|
|
RtlSetEnvironmentVariable( pEnv, &Name, NULL);
|
|
|
|
return(Success);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetEnvironmentVariables
|
|
*
|
|
* Reads the user-defined environment variables from the user registry
|
|
* and adds them to the environment block at pEnv.
|
|
*
|
|
* History:
|
|
* 2-28-92 Johannec Created
|
|
*
|
|
\***************************************************************************/
|
|
BOOL
|
|
SetEnvironmentVariables(
|
|
PVOID *pEnv,
|
|
LPTSTR lpRegSubKey,
|
|
HKEY hKeyCU
|
|
)
|
|
{
|
|
WCHAR lpValueName[MAX_PATH];
|
|
LPBYTE lpDataBuffer;
|
|
DWORD cchDataBuffer;
|
|
LPBYTE lpData;
|
|
LPTSTR lpExpandedValue = NULL;
|
|
DWORD cchValueName = MAX_PATH;
|
|
DWORD cbData;
|
|
DWORD dwType;
|
|
DWORD dwIndex = 0;
|
|
HKEY hkey;
|
|
BOOL bResult;
|
|
|
|
if (RegOpenKeyExW(hKeyCU, lpRegSubKey, 0, KEY_READ, &hkey)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
cchDataBuffer = 4096;
|
|
lpDataBuffer = (LPBYTE)LocalAlloc(LPTR, cchDataBuffer*sizeof(WCHAR));
|
|
if (lpDataBuffer == NULL) {
|
|
RegCloseKey(hkey);
|
|
return(FALSE);
|
|
}
|
|
lpData = lpDataBuffer;
|
|
cbData = cchDataBuffer * sizeof(WCHAR);
|
|
bResult = TRUE;
|
|
while (!RegEnumValue(hkey, dwIndex, lpValueName, &cchValueName, 0, &dwType,
|
|
lpData, &cbData)) {
|
|
if (cchValueName) {
|
|
|
|
//
|
|
// Limit environment variable length
|
|
//
|
|
|
|
lpData[MAX_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 (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, PATH_VARIABLE, -1) == CSTR_EQUAL ||
|
|
CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, LIBPATH_VARIABLE, -1) == CSTR_EQUAL ||
|
|
CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, OS2LIBPATH_VARIABLE, -1) == CSTR_EQUAL ) {
|
|
|
|
BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpData);
|
|
}
|
|
else {
|
|
|
|
//
|
|
// the other environment variables are just set.
|
|
//
|
|
|
|
SetEnvironmentVariableInBlock(pEnv, lpValueName, (LPTSTR)lpData, TRUE);
|
|
}
|
|
}
|
|
}
|
|
dwIndex++;
|
|
cbData = cchDataBuffer * sizeof(WCHAR);
|
|
cchValueName = MAX_PATH;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
cbData = cchDataBuffer * sizeof(WCHAR);
|
|
cchValueName = MAX_PATH;
|
|
|
|
|
|
while (!RegEnumValue(hkey, dwIndex, lpValueName, &cchValueName, 0, &dwType,
|
|
lpData, &cbData)) {
|
|
if (cchValueName) {
|
|
|
|
//
|
|
// Limit environment variable length
|
|
//
|
|
|
|
lpData[MAX_VALUE_LEN-1] = TEXT('\0');
|
|
|
|
|
|
if (dwType == REG_EXPAND_SZ) {
|
|
DWORD cch, cchNeeded;
|
|
|
|
cch = 1024;
|
|
lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (lpExpandedValue) {
|
|
cchNeeded = ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cch);
|
|
if (cchNeeded > cch) {
|
|
LocalFree(lpExpandedValue);
|
|
cch = cchNeeded;
|
|
lpExpandedValue = (LPTSTR)LocalAlloc(LPTR, cch*sizeof(WCHAR));
|
|
if (lpExpandedValue) {
|
|
ExpandUserEnvironmentStrings(*pEnv, (LPTSTR)lpData, lpExpandedValue, cch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lpExpandedValue == NULL) {
|
|
bResult = FALSE;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// The path variables PATH, LIBPATH and OS2LIBPATH must have
|
|
// their values apppended to the system path.
|
|
//
|
|
|
|
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, PATH_VARIABLE, -1) == CSTR_EQUAL ||
|
|
CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, LIBPATH_VARIABLE, -1) == CSTR_EQUAL ||
|
|
CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpValueName, -1, OS2LIBPATH_VARIABLE, -1) == CSTR_EQUAL ) {
|
|
|
|
BuildEnvironmentPath(pEnv, lpValueName, (LPTSTR)lpExpandedValue);
|
|
}
|
|
else {
|
|
|
|
//
|
|
// the other environment variables are just set.
|
|
//
|
|
|
|
SetEnvironmentVariableInBlock(pEnv, lpValueName, (LPTSTR)lpExpandedValue, TRUE);
|
|
}
|
|
|
|
LocalFree(lpExpandedValue);
|
|
|
|
}
|
|
|
|
}
|
|
dwIndex++;
|
|
cbData = cchDataBuffer * sizeof(WCHAR);
|
|
cchValueName = MAX_PATH;
|
|
}
|
|
|
|
|
|
|
|
LocalFree(lpDataBuffer);
|
|
RegCloseKey(hkey);
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// ExpandEnvironmentStringsForUser()
|
|
//
|
|
// Purpose: Expands the source string using the environment block for the
|
|
// specified user. If hToken is null, the system environment block
|
|
// will be used (no user environment variables).
|
|
//
|
|
// Parameters: hToken - User's token (or null for system env vars)
|
|
// lpSrc - String to be expanded
|
|
// lpDest - Buffer to receive string
|
|
// dwSize - Size of dest buffer
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI ExpandEnvironmentStringsForUser(HANDLE hToken, LPCTSTR lpSrc,
|
|
LPTSTR lpDest, DWORD dwSize)
|
|
{
|
|
LPVOID pEnv;
|
|
DWORD dwNeeded;
|
|
BOOL bResult = FALSE;
|
|
|
|
|
|
//
|
|
// Arg check
|
|
//
|
|
|
|
if ( !lpDest || !lpSrc )
|
|
{
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the user's environment block
|
|
//
|
|
|
|
if (!CreateEnvironmentBlock (&pEnv, hToken, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("ExpandEnvironmentStringsForUser: CreateEnvironmentBlock failed with = %d"),
|
|
GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Expand the string
|
|
//
|
|
|
|
dwNeeded = ExpandUserEnvironmentStrings(pEnv, lpSrc, lpDest, dwSize);
|
|
|
|
if (dwNeeded && (dwNeeded < dwSize)) {
|
|
bResult = TRUE;
|
|
} else {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER );
|
|
}
|
|
|
|
|
|
//
|
|
// Free the environment block
|
|
//
|
|
|
|
DestroyEnvironmentBlock (pEnv);
|
|
|
|
|
|
return bResult;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetSystemTempDirectory()
|
|
//
|
|
// Purpose: Gets the system temp directory in short form
|
|
//
|
|
// Parameters: lpDir - Receives the directory
|
|
// lpcchSize - Size of the lpDir buffer
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI GetSystemTempDirectory(LPTSTR lpDir, LPDWORD lpcchSize)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szDirectory[MAX_PATH];
|
|
DWORD dwLength;
|
|
HKEY hKey;
|
|
LONG lResult;
|
|
DWORD dwSize, dwType;
|
|
BOOL bRetVal = FALSE;
|
|
WIN32_FILE_ATTRIBUTE_DATA fad;
|
|
HRESULT hr;
|
|
|
|
|
|
szTemp[0] = TEXT('\0');
|
|
szDirectory[0] = TEXT('\0');
|
|
|
|
//
|
|
// Look in the system environment variables
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SYS_ENVVARS, 0,
|
|
KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Check for TEMP
|
|
//
|
|
|
|
dwSize = sizeof(szTemp);
|
|
|
|
if (RegQueryValueEx (hKey, TEXT("TEMP"), NULL, &dwType,
|
|
(LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
|
|
RegCloseKey (hKey);
|
|
goto FoundTemp;
|
|
}
|
|
|
|
|
|
//
|
|
// Check for TMP
|
|
//
|
|
|
|
dwSize = sizeof(szTemp);
|
|
|
|
if (RegQueryValueEx (hKey, TEXT("TMP"), NULL, &dwType,
|
|
(LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
|
|
RegCloseKey (hKey);
|
|
goto FoundTemp;
|
|
}
|
|
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Check if %SystemRoot%\Temp exists
|
|
//
|
|
|
|
StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%SystemRoot%\\Temp"));
|
|
if (FAILED(hr = SafeExpandEnvironmentStrings (szDirectory, szTemp, ARRAYSIZE (szTemp))))
|
|
{
|
|
SetLastError(HRESULT_CODE(hr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (GetFileAttributesEx (szTemp, GetFileExInfoStandard, &fad) &&
|
|
fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
goto FoundTemp;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if %SystemDrive%\Temp exists
|
|
//
|
|
|
|
StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%SystemDrive%\\Temp"));
|
|
if (FAILED(hr = SafeExpandEnvironmentStrings (szDirectory, szTemp, ARRAYSIZE (szTemp))))
|
|
{
|
|
SetLastError(HRESULT_CODE(hr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (GetFileAttributesEx (szTemp, GetFileExInfoStandard, &fad) &&
|
|
fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
goto FoundTemp;
|
|
}
|
|
|
|
|
|
//
|
|
// Last resort is %SystemRoot%
|
|
//
|
|
|
|
StringCchCopy (szTemp, ARRAYSIZE (szTemp), TEXT("%SystemRoot%"));
|
|
|
|
|
|
|
|
FoundTemp:
|
|
|
|
if (FAILED(hr = SafeExpandEnvironmentStrings (szTemp, szDirectory, ARRAYSIZE (szDirectory))))
|
|
{
|
|
SetLastError(HRESULT_CODE(hr));
|
|
goto Exit;
|
|
}
|
|
dwLength = GetShortPathName (szDirectory, szTemp, ARRAYSIZE(szTemp));
|
|
if (dwLength > ARRAYSIZE(szTemp) || dwLength == 0)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
dwLength = lstrlen(szTemp) + 1;
|
|
|
|
if (lpDir) {
|
|
|
|
if (*lpcchSize >= dwLength) {
|
|
StringCchCopy (lpDir, *lpcchSize, szTemp);
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
} else {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
|
|
|
|
*lpcchSize = dwLength;
|
|
|
|
Exit:
|
|
return bRetVal;
|
|
}
|
|
|
|
#ifdef _X86_
|
|
BOOL
|
|
IsPathIncludeRemovable(LPTSTR lpValue)
|
|
{
|
|
LPTSTR lpt, tmp;
|
|
BOOL ret = FALSE;
|
|
WCHAR c;
|
|
DWORD cchTmp;
|
|
|
|
cchTmp = lstrlen(lpValue) + 1;
|
|
tmp = LocalAlloc(LPTR, cchTmp * sizeof(WCHAR));
|
|
if (!tmp) {
|
|
DebugMsg((DM_WARNING, TEXT("IsPathIncludeRemovable : Failed to LocalAlloc (%d)"), GetLastError()));
|
|
}
|
|
else {
|
|
StringCchCopy(tmp, cchTmp, lpValue);
|
|
|
|
lpt = tmp;
|
|
while (*lpt) {
|
|
// skip spaces
|
|
for ( ; *lpt && *lpt == TEXT(' '); lpt++)
|
|
;
|
|
|
|
// check if the drive is removable
|
|
if (lpt[0] && lpt[1] && lpt[1] == TEXT(':') && lpt[2]) { // ex) "A:\"
|
|
c = lpt[3];
|
|
lpt[3] = 0;
|
|
if (GetDriveType(lpt) == DRIVE_REMOVABLE) {
|
|
lpt[3] = c;
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
lpt[3] = c;
|
|
}
|
|
|
|
// skip to the next path
|
|
for ( ; *lpt && *lpt != TEXT(';'); lpt++)
|
|
;
|
|
if (*lpt)
|
|
lpt++;
|
|
}
|
|
LocalFree(tmp);
|
|
}
|
|
return(ret);
|
|
}
|
|
#endif
|