/*++ Copyright (c) 2000 Microsoft Corporation Module Name: env.c Abstract: Implements ISM environment variable support Author: Jim Schmidt (jimschm) 01-Mar-2000 Revision History: --*/ // // Includes // #include "pch.h" #include "ism.h" #include "ismp.h" #define DBG_ISMENV "IsmEnv" // // Strings // #define S_MEMDB_ENV_ROOT_SRC TEXT("EnvSrc") #define S_MEMDB_ENV_ROOT_DEST TEXT("EnvDest") // // Constants // // None // // Macros // // None // // Types // typedef struct { ENVENTRY_TYPE Type; UINT DataSize; BYTE Data[]; } ENVIRONMENT_ENTRY, *PENVIRONMENT_ENTRY; // // Globals // GROWBUFFER g_AppendBuffer = INIT_GROWBUFFER; // // Macro expansion list // // None // // Private function prototypes // BOOL pGetEnvironmentValue ( IN UINT Platform, IN OUT KEYHANDLE *KeyHandle, OPTIONAL IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PBYTE Data, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded, OPTIONAL OUT PENVENTRY_TYPE DataType OPTIONAL ); // // Macro expansion definition // // None // // Code // BOOL InitializeEnv ( VOID ) { return TRUE; } VOID TerminateEnv ( VOID ) { GbFree (&g_AppendBuffer); } BOOL EnvEnumerateFirstEntry ( OUT PENV_ENTRY_ENUM EnvEntryEnum, IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Pattern ) { PCTSTR pattern = NULL; PENVIRONMENT_ENTRY envEntry; UINT dataSize; BOOL result = FALSE; if (Platform == PLATFORM_CURRENT) { Platform = g_IsmCurrentPlatform; } if (Platform == PLATFORM_SOURCE) { pattern = JoinPaths (S_MEMDB_ENV_ROOT_SRC, Pattern); } else { pattern = JoinPaths (S_MEMDB_ENV_ROOT_DEST, Pattern); } ZeroMemory (EnvEntryEnum, sizeof (PENV_ENTRY_ENUM)); EnvEntryEnum->Platform = Platform; if (MemDbEnumFirst (&EnvEntryEnum->Handle, pattern, ENUMFLAG_NORMAL, 1, ENUMLEVEL_ALLLEVELS)) { envEntry = (PENVIRONMENT_ENTRY) MemDbGetUnorderedBlob (EnvEntryEnum->Handle.FullKeyName, 0, NULL); EnvEntryEnum->EnvEntryType = envEntry->Type; EnvEntryEnum->EnvEntryGroup = DuplicatePathString (EnvEntryEnum->Handle.KeyName, 0); EnvEntryEnum->EnvEntryName = _tcschr (EnvEntryEnum->EnvEntryGroup, TEXT('\\')); if (EnvEntryEnum->EnvEntryName) { *((PTSTR)(EnvEntryEnum->EnvEntryName)) = 0; EnvEntryEnum->EnvEntryName ++; } else { EnvEntryEnum->EnvEntryName = EnvEntryEnum->EnvEntryGroup; EnvEntryEnum->EnvEntryGroup = NULL; } #ifdef UNICODE EnvEntryEnum->EnvEntryDataSize = envEntry->DataSize; if (envEntry->DataSize) { EnvEntryEnum->EnvEntryData = IsmGetMemory (envEntry->DataSize); CopyMemory (EnvEntryEnum->EnvEntryData, envEntry->Data, envEntry->DataSize); } else { EnvEntryEnum->EnvEntryData = NULL; } #else if (envEntry->Type == ENVENTRY_STRING) { dataSize = SizeOfStringA ((PCSTR)envEntry->Data) * 2; EnvEntryEnum->EnvEntryData = IsmGetMemory (dataSize); ZeroMemory (EnvEntryEnum->EnvEntryData, dataSize); DirectDbcsToUnicodeN ( (PWSTR)EnvEntryEnum->EnvEntryData, (PSTR)envEntry->Data, SizeOfStringA ((PCSTR)envEntry->Data) ); EnvEntryEnum->EnvEntryDataSize = SizeOfStringW ((PWSTR)EnvEntryEnum->EnvEntryData); } else if (envEntry->Type == ENVENTRY_MULTISZ) { dataSize = SizeOfMultiSzA ((PCSTR)envEntry->Data) * 2; EnvEntryEnum->EnvEntryData = IsmGetMemory (dataSize); ZeroMemory (EnvEntryEnum->EnvEntryData, dataSize); DirectDbcsToUnicodeN ( (PWSTR)EnvEntryEnum->EnvEntryData, (PSTR)envEntry->Data, SizeOfMultiSzA ((PCSTR)envEntry->Data) ); EnvEntryEnum->EnvEntryDataSize = SizeOfMultiSzW ((PWSTR)EnvEntryEnum->EnvEntryData); } else { EnvEntryEnum->EnvEntryDataSize = envEntry->DataSize; if (envEntry->DataSize) { EnvEntryEnum->EnvEntryData = IsmGetMemory (envEntry->DataSize); CopyMemory (EnvEntryEnum->EnvEntryData, envEntry->Data, envEntry->DataSize); } else { EnvEntryEnum->EnvEntryData = NULL; } } #endif MemDbReleaseMemory (envEntry); result = TRUE; } FreePathString (pattern); return result; } BOOL EnvEnumerateNextEntry ( IN OUT PENV_ENTRY_ENUM EnvEntryEnum ) { PENVIRONMENT_ENTRY envEntry; UINT dataSize; BOOL result = FALSE; if (EnvEntryEnum->EnvEntryData) { IsmReleaseMemory (EnvEntryEnum->EnvEntryData); EnvEntryEnum->EnvEntryData = NULL; } if (EnvEntryEnum->EnvEntryGroup) { FreePathString (EnvEntryEnum->EnvEntryGroup); EnvEntryEnum->EnvEntryGroup = NULL; EnvEntryEnum->EnvEntryName = NULL; } if (EnvEntryEnum->EnvEntryName) { FreePathString (EnvEntryEnum->EnvEntryName); EnvEntryEnum->EnvEntryName = NULL; } if (MemDbEnumNext (&EnvEntryEnum->Handle)) { envEntry = (PENVIRONMENT_ENTRY) MemDbGetUnorderedBlob (EnvEntryEnum->Handle.FullKeyName, 0, NULL); EnvEntryEnum->EnvEntryType = envEntry->Type; EnvEntryEnum->EnvEntryGroup = DuplicatePathString (EnvEntryEnum->Handle.KeyName, 0); EnvEntryEnum->EnvEntryName = _tcschr (EnvEntryEnum->EnvEntryGroup, TEXT('\\')); if (EnvEntryEnum->EnvEntryName) { *((PTSTR)(EnvEntryEnum->EnvEntryName)) = 0; EnvEntryEnum->EnvEntryName ++; } else { EnvEntryEnum->EnvEntryName = EnvEntryEnum->EnvEntryGroup; EnvEntryEnum->EnvEntryGroup = NULL; } #ifdef UNICODE EnvEntryEnum->EnvEntryDataSize = envEntry->DataSize; if (envEntry->DataSize) { EnvEntryEnum->EnvEntryData = IsmGetMemory (envEntry->DataSize); CopyMemory (EnvEntryEnum->EnvEntryData, envEntry->Data, envEntry->DataSize); } else { EnvEntryEnum->EnvEntryData = NULL; } #else if (envEntry->Type == ENVENTRY_STRING) { dataSize = SizeOfStringW ((PCWSTR)envEntry->Data) * 2; EnvEntryEnum->EnvEntryData = IsmGetMemory (dataSize); ZeroMemory (EnvEntryEnum->EnvEntryData, dataSize); DirectUnicodeToDbcsN ( (PSTR)EnvEntryEnum->EnvEntryData, (PWSTR)envEntry->Data, SizeOfStringW ((PCWSTR)envEntry->Data) ); EnvEntryEnum->EnvEntryDataSize = SizeOfStringW ((PWSTR)EnvEntryEnum->EnvEntryData); } else if (envEntry->Type == ENVENTRY_MULTISZ) { dataSize = SizeOfMultiSzW ((PCWSTR)envEntry->Data) * 2; EnvEntryEnum->EnvEntryData = IsmGetMemory (dataSize); ZeroMemory (EnvEntryEnum->EnvEntryData, dataSize); DirectUnicodeToDbcsN ( (PSTR)EnvEntryEnum->EnvEntryData, (PWSTR)envEntry->Data, SizeOfMultiSzW ((PCWSTR)envEntry->Data) ); EnvEntryEnum->EnvEntryDataSize = SizeOfMultiSzW ((PWSTR)EnvEntryEnum->EnvEntryData); } else { EnvEntryEnum->EnvEntryDataSize = envEntry->DataSize; if (envEntry->DataSize) { EnvEntryEnum->EnvEntryData = IsmGetMemory (envEntry->DataSize); CopyMemory (EnvEntryEnum->EnvEntryData, envEntry->Data, envEntry->DataSize); } else { EnvEntryEnum->EnvEntryData = NULL; } } #endif MemDbReleaseMemory (envEntry); result = TRUE; } else { MemDbAbortEnum (&EnvEntryEnum->Handle); } return result; } VOID AbortEnvEnumerateEntry ( IN OUT PENV_ENTRY_ENUM EnvEntryEnum ) { if (EnvEntryEnum->EnvEntryData) { IsmReleaseMemory (EnvEntryEnum->EnvEntryData); EnvEntryEnum->EnvEntryData = NULL; } if (EnvEntryEnum->EnvEntryGroup) { FreePathString (EnvEntryEnum->EnvEntryGroup); EnvEntryEnum->EnvEntryGroup = NULL; EnvEntryEnum->EnvEntryName = NULL; } if (EnvEntryEnum->EnvEntryName) { FreePathString (EnvEntryEnum->EnvEntryName); EnvEntryEnum->EnvEntryName = NULL; } MemDbAbortEnum (&EnvEntryEnum->Handle); ZeroMemory (EnvEntryEnum, sizeof (PENV_ENTRY_ENUM)); } VOID EnvInvalidateCallbacks ( VOID ) { GROWBUFFER envBuff = INIT_GROWBUFFER; PCTSTR pattern = NULL; MEMDB_ENUM e; MULTISZ_ENUM se; BOOL toDelete = FALSE; PENVIRONMENT_ENTRY envEntry; pattern = JoinPaths (S_MEMDB_ENV_ROOT_SRC, TEXT("*")); if (MemDbEnumFirst (&e, pattern, ENUMFLAG_NORMAL, 0, ENUMLEVEL_ALLLEVELS)) { do { envEntry = (PENVIRONMENT_ENTRY) MemDbGetUnorderedBlob (e.FullKeyName, 0, NULL); if (envEntry->Type == ENVENTRY_CALLBACK) { GbMultiSzAppend (&envBuff, e.FullKeyName); toDelete = TRUE; } MemDbReleaseMemory (envEntry); } while (MemDbEnumNext (&e)); MemDbAbortEnum (&e); } if (toDelete && EnumFirstMultiSz (&se, (PCTSTR) envBuff.Buf)) { do { MemDbDeleteKey (se.CurrentString); } while (EnumNextMultiSz (&se)); } FreePathString (pattern); } VOID pEnvSave ( IN PCTSTR Pattern, IN OUT PGROWLIST GrowList ) { MEMDB_ENUM e; PENVIRONMENT_ENTRY envEntry; UINT strSize; PBYTE listStruct; if (MemDbEnumFirst (&e, Pattern, ENUMFLAG_NORMAL, 0, ENUMLEVEL_ALLLEVELS)) { do { envEntry = (PENVIRONMENT_ENTRY) MemDbGetUnorderedBlob (e.FullKeyName, 0, NULL); strSize = SizeOfString (e.FullKeyName); listStruct = PmGetMemory (g_IsmPool, strSize + sizeof (ENVIRONMENT_ENTRY) + envEntry->DataSize); CopyMemory (listStruct, e.FullKeyName, strSize); CopyMemory (listStruct + strSize, envEntry, sizeof (ENVIRONMENT_ENTRY) + envEntry->DataSize); GlAppend (GrowList, listStruct, strSize + sizeof (ENVIRONMENT_ENTRY) + envEntry->DataSize); PmReleaseMemory (g_IsmPool, listStruct); MemDbReleaseMemory (envEntry); } while (MemDbEnumNext (&e)); } } BOOL EnvSaveEnvironment ( IN OUT PGROWLIST GrowList ) { pEnvSave (S_MEMDB_ENV_ROOT_SRC TEXT("\\*"), GrowList); pEnvSave (S_MEMDB_ENV_ROOT_DEST TEXT("\\*"), GrowList); return TRUE; } BOOL EnvRestoreEnvironment ( IN PGROWLIST GrowList ) { UINT listSize, i; PBYTE listStruct; PCTSTR memdbName; PENVIRONMENT_ENTRY envEntry; listSize = GlGetSize (GrowList); for (i = 0; i < listSize; i ++) { listStruct = GlGetItem (GrowList, i); memdbName = (PCTSTR) listStruct; if (!MemDbTestKey (memdbName)) { envEntry = (PENVIRONMENT_ENTRY) (GetEndOfString ((PCTSTR) listStruct) + 1); if (!MemDbSetUnorderedBlob ( memdbName, 0, (PBYTE) envEntry, sizeof (ENVIRONMENT_ENTRY) + envEntry->DataSize )) { EngineError (); } } } return TRUE; } BOOL IsmSetEnvironmentValue ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PENVENTRY_STRUCT VariableData OPTIONAL ) { PCTSTR memdbName = NULL; BOOL result = FALSE; KEYHANDLE kh; PENVIRONMENT_ENTRY envEntry = NULL; UINT dataSize; PCVOID dataPtr; DATAHANDLE dh; BOOL destPlatform = FALSE; #ifndef UNICODE PWSTR unicodeData = NULL; #endif if ((Platform != PLATFORM_SOURCE) && (Platform != PLATFORM_DESTINATION) ) { DEBUGMSG ((DBG_ERROR, "Environment variable specified with no platform.")); return FALSE; } destPlatform = (Platform == PLATFORM_DESTINATION); __try { // // Validate arguments // if (!VariableName || !(*VariableName)) { DEBUGMSG ((DBG_ERROR, "Invalid variable name")); SetLastError (ERROR_INVALID_PARAMETER); __leave; } // // Build decorated name by joining current group with variable name, // then build memdb key // memdbName = JoinPathsInPoolEx (( NULL, destPlatform?S_MEMDB_ENV_ROOT_DEST:S_MEMDB_ENV_ROOT_SRC, Group?Group:VariableName, Group?VariableName:NULL, NULL )); kh = MemDbSetKey (memdbName); if (!kh) { DEBUGMSG ((DBG_ERROR, "Error while adding environment variable into database")); EngineError (); __leave; } MemDbDeleteUnorderedBlobByKeyHandle (kh, 0); if (VariableData->Type == ENVENTRY_STRING) { if (VariableData->EnvString == NULL) { dataSize = sizeof (TCHAR); dataPtr = TEXT(""); } else { #ifdef UNICODE dataSize = SizeOfStringW (VariableData->EnvString); dataPtr = VariableData->EnvString; #else dataSize = SizeOfStringA (VariableData->EnvString) * 2; unicodeData = IsmGetMemory (dataSize); if (unicodeData) { ZeroMemory (unicodeData, dataSize); DirectDbcsToUnicodeN ( unicodeData, VariableData->EnvString, SizeOfStringA (VariableData->EnvString) ); dataSize = SizeOfStringW (unicodeData); dataPtr = unicodeData; } else { dataSize = sizeof (WCHAR); dataPtr = L""; } #endif } } else if (VariableData->Type == ENVENTRY_MULTISZ) { if (VariableData->MultiSz == NULL) { dataSize = sizeof (TCHAR); dataPtr = TEXT(""); } else { #ifdef UNICODE dataSize = SizeOfMultiSzW (VariableData->MultiSz); dataPtr = VariableData->MultiSz; #else dataSize = SizeOfMultiSzA (VariableData->MultiSz) * 2; unicodeData = IsmGetMemory (dataSize); if (unicodeData) { ZeroMemory (unicodeData, dataSize); DirectDbcsToUnicodeN ( unicodeData, VariableData->MultiSz, SizeOfMultiSzA (VariableData->MultiSz) ); dataSize = SizeOfMultiSzW (unicodeData); dataPtr = unicodeData; } else { dataSize = sizeof (WCHAR); dataPtr = L""; } #endif } } else if (VariableData->Type == ENVENTRY_CALLBACK) { dataSize = sizeof (PENVENTRYCALLBACK); dataPtr = (&VariableData->EnvCallback); } else if (VariableData->Type == ENVENTRY_BINARY) { dataSize = VariableData->EnvBinaryDataSize; dataPtr = VariableData->EnvBinaryData; } else { DEBUGMSG ((DBG_ERROR, "Invalid variable data type")); SetLastError (ERROR_INVALID_PARAMETER); __leave; } envEntry = (PENVIRONMENT_ENTRY) MemAllocUninit (sizeof (ENVIRONMENT_ENTRY) + dataSize); envEntry->Type = VariableData->Type; envEntry->DataSize = dataSize; if (envEntry->DataSize) { CopyMemory (envEntry->Data, dataPtr, envEntry->DataSize); } dh = MemDbSetUnorderedBlob (memdbName, 0, (PBYTE) envEntry, sizeof (ENVIRONMENT_ENTRY) + envEntry->DataSize); result = (dh != 0); if (!result) { EngineError (); } } __finally { if (memdbName) { FreePathString (memdbName); memdbName = NULL; } if (envEntry) { FreeAlloc (envEntry); envEntry = NULL; } #ifndef UNICODE if (unicodeData) { IsmReleaseMemory (unicodeData); unicodeData = NULL; } #endif } return result; } BOOL IsmSetEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PCTSTR VariableValue ) { ENVENTRY_STRUCT envEntry; envEntry.Type = ENVENTRY_STRING; envEntry.EnvString = VariableValue; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } BOOL IsmSetEnvironmentMultiSz ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PCTSTR VariableValue ) { ENVENTRY_STRUCT envEntry; envEntry.Type = ENVENTRY_MULTISZ; envEntry.MultiSz = VariableValue; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } BOOL IsmAppendEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PCTSTR VariableValue ) { ENVENTRY_STRUCT envEntry; ENVENTRY_TYPE type; KEYHANDLE kh = 0; UINT multiSzNeeded; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, &multiSzNeeded, &type )) { if (type != ENVENTRY_MULTISZ) { return FALSE; } g_AppendBuffer.End = 0; GbGrow (&g_AppendBuffer, multiSzNeeded); if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, g_AppendBuffer.Buf, multiSzNeeded, NULL, NULL )) { if (g_AppendBuffer.End) { g_AppendBuffer.End -= sizeof (TCHAR); } GbMultiSzAppend (&g_AppendBuffer, VariableValue); envEntry.Type = ENVENTRY_MULTISZ; envEntry.MultiSz = (PCTSTR) g_AppendBuffer.Buf; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } } else { g_AppendBuffer.End = 0; GbMultiSzAppend (&g_AppendBuffer, VariableValue); envEntry.Type = ENVENTRY_MULTISZ; envEntry.MultiSz = (PCTSTR) g_AppendBuffer.Buf; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } return FALSE; } BOOL IsmAppendEnvironmentMultiSz ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PCTSTR VariableValue ) { ENVENTRY_STRUCT envEntry; ENVENTRY_TYPE type; KEYHANDLE kh = 0; UINT multiSzNeeded; MULTISZ_ENUM multiSzEnum; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, &multiSzNeeded, &type )) { if (type != ENVENTRY_MULTISZ) { return FALSE; } g_AppendBuffer.End = 0; GbGrow (&g_AppendBuffer, multiSzNeeded); if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, g_AppendBuffer.Buf, multiSzNeeded, NULL, NULL )) { if (g_AppendBuffer.End) { g_AppendBuffer.End -= sizeof (TCHAR); } if (EnumFirstMultiSz (&multiSzEnum, VariableValue)) { do { GbMultiSzAppend (&g_AppendBuffer, multiSzEnum.CurrentString); } while (EnumNextMultiSz (&multiSzEnum)); } envEntry.Type = ENVENTRY_MULTISZ; envEntry.MultiSz = (PCTSTR) g_AppendBuffer.Buf; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } } else { envEntry.Type = ENVENTRY_MULTISZ; envEntry.MultiSz = VariableValue; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } return FALSE; } BOOL IsmSetEnvironmentCallback ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PENVENTRYCALLBACK VariableCallback ) { ENVENTRY_STRUCT envEntry; envEntry.Type = ENVENTRY_CALLBACK; envEntry.EnvCallback = VariableCallback; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } BOOL IsmSetEnvironmentData ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, IN PCBYTE VariableData, IN UINT VariableDataSize ) { ENVENTRY_STRUCT envEntry; envEntry.Type = ENVENTRY_BINARY; envEntry.EnvBinaryData = VariableData; envEntry.EnvBinaryDataSize = VariableDataSize; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } BOOL IsmSetEnvironmentFlag ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName ) { ENVENTRY_STRUCT envEntry; envEntry.Type = ENVENTRY_BINARY; envEntry.EnvBinaryData = NULL; envEntry.EnvBinaryDataSize = 0; return IsmSetEnvironmentValue ( Platform, Group, VariableName, &envEntry ); } BOOL pGetEnvironmentValue ( IN MIG_PLATFORMTYPEID Platform, IN OUT KEYHANDLE *KeyHandle, OPTIONAL IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PBYTE Data, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded, OPTIONAL OUT PENVENTRY_TYPE DataType OPTIONAL ) { PCTSTR memdbName = NULL; BOOL result = FALSE; KEYHANDLE kh = 0; PENVIRONMENT_ENTRY envEntry; UINT sizeNeeded; GROWBUFFER tempBuffer = INIT_GROWBUFFER; BOOL destPlatform = FALSE; UINT dataSize; #ifndef UNICODE PSTR ansiData = NULL; #endif if ((Platform != PLATFORM_SOURCE) && (Platform != PLATFORM_DESTINATION) ) { DEBUGMSG ((DBG_ERROR, "Environment variable specified with no platform.")); return FALSE; } destPlatform = (Platform == PLATFORM_DESTINATION); __try { // // IsmGetEnvironmentValue will call this worker with KeyHandle set to NULL, but // IsmGetEnvironmentString will call this worker with a valid KeyHandle. This // is done to eliminate double-validation and double-lookup of the memdb key. // if (!KeyHandle || !(*KeyHandle)) { // // Validate arguments // if (!VariableName || !(*VariableName)) { DEBUGMSG ((DBG_ERROR, "Can't get value of invalid variable name")); SetLastError (ERROR_INVALID_PARAMETER); __leave; } memdbName = JoinPathsInPoolEx (( NULL, destPlatform?S_MEMDB_ENV_ROOT_DEST:S_MEMDB_ENV_ROOT_SRC, Group?Group:VariableName, Group?VariableName:NULL, NULL )); kh = MemDbGetHandleFromKey (memdbName); if (KeyHandle) { *KeyHandle = kh; } } else { kh = *KeyHandle; } // // If no variable exists, return FALSE // if (!kh) { SetLastError (ERROR_SUCCESS); __leave; } // // Otherwise get the binary data // envEntry = NULL; if (!MemDbGetUnorderedBlobByKeyHandleEx (kh, 0, &tempBuffer, &sizeNeeded)) { // // No variable exists, return FALSE // if (DataSizeNeeded) { *DataSizeNeeded = 0; } if (DataType) { *DataType = ENVENTRY_NONE; } SetLastError (ERROR_SUCCESS); __leave; } envEntry = (PENVIRONMENT_ENTRY) tempBuffer.Buf; if (DataType) { *DataType = envEntry->Type; } #ifdef UNICODE if (DataSizeNeeded) { *DataSizeNeeded = envEntry->DataSize; } if (DataSize) { if (DataSize < envEntry->DataSize) { SetLastError (ERROR_INSUFFICIENT_BUFFER); } else { CopyMemory (Data, envEntry->Data, envEntry->DataSize); } } #else if (envEntry->Type == ENVENTRY_STRING) { dataSize = SizeOfStringW ((PCWSTR)envEntry->Data); ansiData = IsmGetMemory (dataSize); if (ansiData) { ZeroMemory (ansiData, dataSize); DirectUnicodeToDbcsN ( ansiData, (PWSTR)envEntry->Data, SizeOfStringW ((PCWSTR)envEntry->Data) ); dataSize = SizeOfStringA (ansiData); if (DataSizeNeeded) { *DataSizeNeeded = dataSize; } if (DataSize) { if (DataSize < dataSize) { SetLastError (ERROR_INSUFFICIENT_BUFFER); } else { CopyMemory (Data, ansiData, dataSize); } } IsmReleaseMemory (ansiData); ansiData = NULL; } } else if (envEntry->Type == ENVENTRY_MULTISZ) { dataSize = SizeOfMultiSzW ((PCWSTR)envEntry->Data); ansiData = IsmGetMemory (dataSize); if (ansiData) { ZeroMemory (ansiData, dataSize); DirectUnicodeToDbcsN ( ansiData, (PWSTR)envEntry->Data, SizeOfMultiSzW ((PCWSTR)envEntry->Data) ); dataSize = SizeOfMultiSzA (ansiData); if (DataSizeNeeded) { *DataSizeNeeded = dataSize; } if (DataSize) { if (DataSize < dataSize) { SetLastError (ERROR_INSUFFICIENT_BUFFER); } else { CopyMemory (Data, ansiData, dataSize); } } IsmReleaseMemory (ansiData); ansiData = NULL; } } else { if (DataSizeNeeded) { *DataSizeNeeded = envEntry->DataSize; } if (DataSize) { if (DataSize < envEntry->DataSize) { SetLastError (ERROR_INSUFFICIENT_BUFFER); } else { CopyMemory (Data, envEntry->Data, envEntry->DataSize); } } } #endif result = TRUE; } __finally { if (memdbName) { FreePathString (memdbName); memdbName = NULL; } GbFree (&tempBuffer); } return result; } BOOL IsmGetEnvironmentValue ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PBYTE Data, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded, OPTIONAL OUT PENVENTRY_TYPE DataType OPTIONAL ) { return pGetEnvironmentValue ( Platform, NULL, Group, VariableName, Data, DataSize, DataSizeNeeded, DataType ); } BOOL IsmGetEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PTSTR VariableValue, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded OPTIONAL ) { KEYHANDLE kh = 0; ENVENTRY_TYPE type; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, NULL, &type )) { if (type != ENVENTRY_STRING) { return FALSE; } if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, (PBYTE) VariableValue, DataSize, DataSizeNeeded, NULL )) { return TRUE; } } return FALSE; } BOOL IsmGetEnvironmentMultiSz ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PTSTR VariableValue, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded OPTIONAL ) { KEYHANDLE kh = 0; ENVENTRY_TYPE type; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, NULL, &type )) { if (type != ENVENTRY_MULTISZ) { return FALSE; } if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, (PBYTE) VariableValue, DataSize, DataSizeNeeded, NULL )) { return TRUE; } } return FALSE; } BOOL IsmGetEnvironmentCallback ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PENVENTRYCALLBACK *VariableCallback OPTIONAL ) { KEYHANDLE kh = 0; ENVENTRY_TYPE type; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, NULL, &type )) { if (type != ENVENTRY_CALLBACK) { return FALSE; } if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, (PBYTE)VariableCallback, sizeof (PENVENTRYCALLBACK), NULL, NULL )) { return TRUE; } } return FALSE; } BOOL IsmGetEnvironmentData ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName, OUT PBYTE VariableData, OPTIONAL IN UINT DataSize, OUT PUINT DataSizeNeeded OPTIONAL ) { KEYHANDLE kh = 0; ENVENTRY_TYPE type; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, NULL, &type )) { if (type != ENVENTRY_BINARY) { return FALSE; } if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, VariableData, DataSize, DataSizeNeeded, NULL )) { return TRUE; } } return FALSE; } BOOL IsmIsEnvironmentFlagSet ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName ) { KEYHANDLE kh = 0; if (pGetEnvironmentValue ( Platform, &kh, Group, VariableName, NULL, 0, NULL, NULL )) { return TRUE; } return FALSE; } BOOL IsmDeleteEnvironmentVariable ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR VariableName ) { BOOL result = FALSE; PCTSTR memdbName = NULL; BOOL destPlatform = FALSE; if ((Platform != PLATFORM_SOURCE) && (Platform != PLATFORM_DESTINATION) ) { DEBUGMSG ((DBG_ERROR, "Environment variable specified with no platform.")); return FALSE; } destPlatform = (Platform == PLATFORM_DESTINATION); __try { // // Validate arguments // if (!(*VariableName)) { DEBUGMSG ((DBG_ERROR, "Invalid variable name")); SetLastError (ERROR_INVALID_PARAMETER); __leave; } // // Build decorated name by joining current group with variable name, // then build memdb key // memdbName = JoinPathsInPoolEx (( NULL, destPlatform?S_MEMDB_ENV_ROOT_DEST:S_MEMDB_ENV_ROOT_SRC, Group?Group:VariableName, Group?VariableName:NULL, NULL )); // // Now delete the memdb key // result = MemDbDeleteKey (memdbName); } __finally { if (memdbName) { FreePathString (memdbName); memdbName = NULL; } } return result; } BOOL pGetEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR EnvString, OUT PTSTR EnvValue, OPTIONAL IN UINT EnvValueSize, OUT PUINT EnvValueSizeNeeded, OPTIONAL IN PCTSTR EnvStringContext OPTIONAL ) { KEYHANDLE kh = 0; ENVENTRY_TYPE type; PENVENTRYCALLBACK callback = NULL; TCHAR buffer[1024]; UINT sizeNeeded; if (pGetEnvironmentValue ( Platform, &kh, Group, EnvString, (PBYTE) buffer, sizeof (buffer), &sizeNeeded, &type )) { if (type == ENVENTRY_STRING) { if (!EnvValue) { if (EnvValueSizeNeeded) { *EnvValueSizeNeeded = sizeNeeded; } return TRUE; } if ((sizeNeeded <= sizeof (buffer)) && (sizeNeeded <= EnvValueSize)) { StringCopy (EnvValue, buffer); if (EnvValueSizeNeeded) { *EnvValueSizeNeeded = sizeNeeded; } return TRUE; } return pGetEnvironmentValue ( Platform, &kh, Group, EnvString, (PBYTE)EnvValue, EnvValueSize, EnvValueSizeNeeded, NULL ); } else if (type == ENVENTRY_CALLBACK) { if (sizeNeeded == sizeof (PENVENTRYCALLBACK)) { callback = (PENVENTRYCALLBACK) buffer; return callback ( EnvString, EnvValue, EnvValueSize, EnvValueSizeNeeded, EnvStringContext ); } } return FALSE; } return FALSE; } PCTSTR TrackedIsmExpandEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR SrcString, IN PCTSTR Context TRACKING_DEF ) { UINT ch; PTSTR strCopy; PTSTR srcString; PTSTR envBegin = NULL; PTSTR envStrBegin; PTSTR envEnd; CHARTYPE savedCh; BOOL envMode = FALSE; UINT strSize; UINT maxSize; GROWBUFFER envBuff = INIT_GROWBUFFER; PCTSTR result = NULL; TRACK_ENTER(); strCopy = PmDuplicateString (g_IsmPool, SrcString); srcString = strCopy; while (*srcString) { ch = _tcsnextc (srcString); if (ch == TEXT('%')) { if (envMode) { envEnd = srcString; envStrBegin = _tcsinc (envBegin); savedCh = *envEnd; *envEnd = 0; maxSize = (UINT) ((envBuff.Size - envBuff.End) * sizeof (TCHAR)); if (pGetEnvironmentString (Platform, Group, envStrBegin, (PTSTR) (envBuff.Buf + envBuff.End), maxSize, &strSize, Context)) { if (maxSize < strSize) { pGetEnvironmentString (Platform, Group, envStrBegin, (PTSTR) GbGrow (&envBuff, strSize), strSize, &strSize, Context); } else { envBuff.End += strSize; } if (strSize) { //we know that the routine above also adds the terminating null character //so we need to pull it out. envBuff.End -= sizeof (TCHAR); } *envEnd = (TCHAR) savedCh; } else { *envEnd = (TCHAR) savedCh; envEnd = _tcsinc (envEnd); strSize = (UINT) ((envEnd - envBegin) * sizeof (TCHAR)); CopyMemory (GbGrow (&envBuff, strSize), envBegin, strSize); } envMode = FALSE; } else { envBegin = srcString; envMode = TRUE; } srcString = _tcsinc (srcString); } else { envEnd = _tcsinc (srcString); if (!envMode) { strSize = (UINT) ((envEnd - srcString) * sizeof (TCHAR)); CopyMemory (GbGrow (&envBuff, strSize), srcString, strSize); } srcString = envEnd; } } if (envMode && envBegin) { strSize = (UINT) ((srcString - envBegin) * sizeof (TCHAR)); CopyMemory (GbGrow (&envBuff, strSize), envBegin, strSize); } CopyMemory (GbGrow (&envBuff, sizeof (TCHAR)), srcString, sizeof (TCHAR)); PmReleaseMemory (g_IsmPool, strCopy); result = PmDuplicateString (g_IsmPool, (PCTSTR) envBuff.Buf); GbFree (&envBuff); TRACK_LEAVE(); return result; } BOOL pDoesEnvExistOnOtherPlatform ( IN PCTSTR Group, IN PCTSTR VariableName, IN MIG_PLATFORMTYPEID Platform ) { BOOL result = FALSE; if (Platform == PLATFORM_SOURCE) { Platform = PLATFORM_DESTINATION; } else { Platform = PLATFORM_SOURCE; } result = pGetEnvironmentValue ( Platform, NULL, Group, VariableName, NULL, 0, NULL, NULL ); return result; } PCTSTR TrackedIsmCompressEnvironmentString ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Group, OPTIONAL IN PCTSTR SrcString, IN PCTSTR Context, IN BOOL MustExistOnOtherPlatform TRACKING_DEF ) { ENV_ENTRY_ENUM envEntryEnum; PCTSTR pattern = NULL; BOOL match = FALSE; DWORD matchLen = 0; DWORD matchLenTmp; PCTSTR envWack = NULL; PCTSTR varName = NULL; PCTSTR varValue = NULL; DWORD resultSize; PTSTR result = NULL; TRACK_ENTER(); // let's enumerate all environment variables pattern = JoinPathsInPoolEx (( NULL, Group?Group:TEXT("*"), Group?TEXT("*"):NULL, NULL )); if (EnvEnumerateFirstEntry ( &envEntryEnum, Platform, pattern )) { do { switch (envEntryEnum.EnvEntryType) { case ENVENTRY_STRING: match = FALSE; if (StringIMatch (SrcString, (PCTSTR)envEntryEnum.EnvEntryData)) { match = TRUE; } if (!match) { envWack = JoinPaths (SrcString, TEXT("\\")); if (envWack) { if (StringIMatch (envWack, (PCTSTR)envEntryEnum.EnvEntryData)) { match = TRUE; } FreePathString (envWack); } } if (!match) { envWack = JoinPaths ((PCTSTR)envEntryEnum.EnvEntryData, TEXT("\\")); if (envWack) { if (StringIPrefix (SrcString, envWack)) { match = TRUE; } } FreePathString (envWack); } if (match) { // we have a match, let's see how big is the match and, // if we need to, write down the env variable and its value matchLenTmp = ByteCount ((PCTSTR)envEntryEnum.EnvEntryData); if (matchLenTmp > matchLen) { // Let's check if this env variable must exist on the other platform if (!MustExistOnOtherPlatform || (pDoesEnvExistOnOtherPlatform (Group, envEntryEnum.EnvEntryName, Platform)) ) { matchLen = matchLenTmp; if (varName) { IsmReleaseMemory (varName); } if (varValue) { IsmReleaseMemory (varValue); } varName = IsmDuplicateString (envEntryEnum.EnvEntryName); varValue = IsmDuplicateString ((PCTSTR)envEntryEnum.EnvEntryData); } } } break; default: break; } } while (EnvEnumerateNextEntry (&envEntryEnum)); } if (matchLen && varName && varValue) { resultSize = ByteCount (TEXT("%")) + ByteCount (varName) + ByteCount (TEXT("%")) + ByteCount (SrcString) - matchLen + 2 * sizeof (TCHAR); result = (PTSTR)IsmGetMemory (resultSize); if (result) { StringCopy (result, TEXT("%")); StringCat (result, varName); StringCat (result, TEXT("%")); StringCat (result, (PCTSTR)((PBYTE)SrcString + matchLen)); } } TRACK_LEAVE(); return result; } BOOL IsmSetTransportVariable ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Section, IN PCTSTR Key, IN PCTSTR KeyData ) { PCTSTR variable; BOOL result = FALSE; if (!Section || !Key || !KeyData) { DEBUGMSG ((DBG_ERROR, "Section, key and key data are required for IsmSetTransportVariable")); return FALSE; } variable = JoinPaths (Section, Key); result = IsmSetEnvironmentString (Platform, S_TRANSPORT_PREFIX, variable, KeyData); FreePathString (variable); return result; } BOOL IsmGetTransportVariable ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Section, IN PCTSTR Key, OUT PTSTR KeyData, OPTIONAL IN UINT KeyDataBufferSizeInBytes ) { PCTSTR variable; BOOL result = FALSE; if (!Section || !Key) { DEBUGMSG ((DBG_ERROR, "Section, key and key data are required for IsmSetTransportVariable")); return FALSE; } variable = JoinPaths (Section, Key); result = IsmGetEnvironmentString ( Platform, S_TRANSPORT_PREFIX, variable, KeyData, KeyDataBufferSizeInBytes, NULL ); FreePathString (variable); return result; }