|
|
// Copyright (c) 2001 Microsoft Corporation, All Rights Reserved
#include "precomp.h"
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <objbase.h>
#include "profilestring.h"
#include "profilestringimpl.h"
/////////////////////////////////////////////////////////////////////////////////////////
// TOOLS
/////////////////////////////////////////////////////////////////////////////////////////
DWORD WMIREG_GetBaseFileName ( IN LPCWSTR FileName, OUT LPWSTR* BaseFileName ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( FileName && BaseFileName ) { *BaseFileName = NULL;
LPWSTR wsz = NULL; wsz = const_cast < LPWSTR > ( FileName ) + wcslen ( FileName );
while ( --wsz > FileName ) { if ( *wsz == OBJ_NAME_PATH_SEPARATOR || *wsz == L'/' || *wsz == L':' ) { wsz++; break; } }
if ( wsz ) { try { if ( ( *BaseFileName = new WCHAR [ wcslen ( wsz ) + 1 ] ) != NULL ) { wcscpy ( *BaseFileName, wsz ); Status = ERROR_SUCCESS; } else { Status = ERROR_NOT_ENOUGH_MEMORY; } } catch ( ... ) { if ( *BaseFileName ) { delete [] *BaseFileName; *BaseFileName = NULL; }
Status = ERROR_GEN_FAILURE; } } }
return Status; }
BOOLEAN WMIREG_GetApplicationName ( IN PREGISTRY_PARAMETERS a, OUT LPCWSTR *ApplicationNameU ) { if ( ApplicationNameU ) { *ApplicationNameU = a->ApplicationName; return TRUE; }
return FALSE; }
BOOLEAN WMIREG_GetVariableName ( IN PREGISTRY_PARAMETERS a, OUT LPCWSTR *VariableNameU ) { if ( VariableNameU ) { *VariableNameU = a->VariableName; return TRUE; }
return FALSE; }
// get appname mapping
PREGISTRY_MAPPING_NAME WMIREG_FindMapping ( IN PREGISTRY_MAPPING_NAME NameMapping, IN LPCWSTR MappingName ) { PREGISTRY_MAPPING_NAME Mapping = NULL; Mapping = NameMapping;
while ( Mapping != NULL ) { try { if ( wcslen( Mapping->Name ) == wcslen( MappingName ) ) { if ( _wcsnicmp ( Mapping->Name, MappingName, wcslen( MappingName ) ) == 0 ) { break; } }
Mapping = (PREGISTRY_MAPPING_NAME)Mapping->Next; } catch ( ... ) { Mapping = NULL; } }
return Mapping; }
// get appname mapping
PREGISTRY_MAPPING_APPNAME WMIREG_FindAppNameMapping ( IN PREGISTRY_MAPPING_NAME NameMapping, IN LPCWSTR ApplicationName ) { PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; AppNameMapping = (PREGISTRY_MAPPING_APPNAME)NameMapping->ApplicationNames;
while ( AppNameMapping != NULL ) { try { if ( wcslen( AppNameMapping->Name ) == wcslen( ApplicationName ) ) { if ( _wcsnicmp ( AppNameMapping->Name, ApplicationName, wcslen( ApplicationName ) ) == 0 ) { break; } }
AppNameMapping = (PREGISTRY_MAPPING_APPNAME)AppNameMapping->Next; } catch ( ... ) { AppNameMapping = NULL; } }
if ( !AppNameMapping ) { AppNameMapping = (PREGISTRY_MAPPING_APPNAME)NameMapping->DefaultAppNameMapping; }
return AppNameMapping; }
//get varname mapping
PREGISTRY_MAPPING_VARNAME WMIREG_FindVarNameMapping ( IN PREGISTRY_MAPPING_APPNAME AppNameMapping, IN LPCWSTR VariableName ) { PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL; VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames;
while ( VarNameMapping != NULL ) { try { if ( wcslen ( VarNameMapping->Name ) == wcslen( VariableName ) ) { if ( _wcsnicmp ( VarNameMapping->Name, VariableName, wcslen( VariableName ) ) == 0 ) { break; } }
VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next; } catch ( ... ) { VarNameMapping = NULL; } }
if ( !VarNameMapping ) { VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping; }
return VarNameMapping; }
// get string representing user's registry
BOOL WMIREG_UserPROFILE ( UNICODE_STRING * UserKeyPath ) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Key = NULL;
if ( NT_SUCCESS ( RtlFormatCurrentUserKeyPath( UserKeyPath ) ) ) { InitializeObjectAttributes ( &ObjectAttributes, UserKeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL );
if ( NT_SUCCESS ( NtOpenKey( &Key, GENERIC_READ, &ObjectAttributes ) ) ) { NtClose( Key ); } else { RtlFreeUnicodeString( UserKeyPath ); RtlInitUnicodeString( UserKeyPath, NULL ); } }
if ( UserKeyPath->Length == 0) { if ( !RtlCreateUnicodeString ( UserKeyPath, L"\\REGISTRY\\USER\\.DEFAULT" ) ) { return FALSE; } }
return TRUE; }
// open registry key
DWORD WMIREG_OpenMappingTarget ( IN PREGISTRY_PARAMETERS a, IN PREGISTRY_MAPPING_VARNAME VarNameMapping, IN LPCWSTR ApplicationName, OUT PHANDLE Key ) { DWORD Status = ERROR_INVALID_PARAMETER;
PREGISTRY_MAPPING_TARGET MappingTarget = NULL; ULONG MappingFlags = 0L;
BOOLEAN AppendApplicationName = FALSE;
OBJECT_ATTRIBUTES ObjectAttributes;
PUNICODE_STRING RegistryPathPrefix = NULL; UNICODE_STRING RegistryPath;
UNICODE_STRING UserKeyPath; UNICODE_STRING SoftwareKeyPath;
// initialization of strings
RtlInitUnicodeString( &UserKeyPath, NULL ); RtlInitUnicodeString( &SoftwareKeyPath, L"\\Registry\\Machine\\Software" );
// temporary unicode_string
UNICODE_STRING temp;
ULONG n = 0L; // size of reg key
// init key
*Key = INVALID_HANDLE_VALUE;
// get mapping
MappingTarget = (PREGISTRY_MAPPING_TARGET)VarNameMapping->MappingTarget; MappingFlags = VarNameMapping->MappingFlags & ( REGISTRY_MAPPING_APPEND_BASE_NAME | REGISTRY_MAPPING_APPEND_APPLICATION_NAME | REGISTRY_MAPPING_SOFTWARE_RELATIVE | REGISTRY_MAPPING_USER_RELATIVE );
if ( MappingTarget != NULL && MappingTarget->RegistryPath ) { // everything's ok
Status = ERROR_SUCCESS;
if ( ApplicationName && ( MappingFlags & REGISTRY_MAPPING_APPEND_APPLICATION_NAME ) ) { AppendApplicationName = TRUE; } else { AppendApplicationName = FALSE; }
if ( MappingFlags & REGISTRY_MAPPING_USER_RELATIVE ) { if ( WMIREG_UserPROFILE ( &UserKeyPath ) ) { if ( UserKeyPath.Length == 0 ) { Status = ERROR_ACCESS_DENIED; } } else { Status = ERROR_INVALID_PARAMETER; }
if ( Status == ERROR_SUCCESS ) { RegistryPathPrefix = &UserKeyPath; } } else if ( MappingFlags & REGISTRY_MAPPING_SOFTWARE_RELATIVE ) { RegistryPathPrefix = &SoftwareKeyPath; } else { RegistryPathPrefix = NULL; }
if ( Status == ERROR_SUCCESS ) { LPWSTR BaseFileName = NULL;
if ( MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME ) { Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName ); }
if ( Status == ERROR_SUCCESS ) { if ( RegistryPathPrefix ) { n = RegistryPathPrefix->Length + sizeof( WCHAR ); }
n += sizeof( WCHAR ) + wcslen ( MappingTarget->RegistryPath ) * sizeof ( WCHAR ); if ( MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME ) { n += sizeof( WCHAR ) + wcslen ( BaseFileName ) * sizeof ( WCHAR ); }
if (AppendApplicationName) { n += sizeof( WCHAR ) + wcslen ( ApplicationName ) * sizeof ( WCHAR ); }
n += sizeof( UNICODE_NULL );
RegistryPath.Buffer = reinterpret_cast < LPWSTR > ( RtlAllocateHeap( RtlProcessHeap(), 0, n ) ); if (RegistryPath.Buffer == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; }
if ( Status == ERROR_SUCCESS ) { RegistryPath.Length = 0; RegistryPath.MaximumLength = (USHORT)n;
if (RegistryPathPrefix != NULL) { RtlAppendUnicodeStringToString( &RegistryPath, RegistryPathPrefix ); RtlAppendUnicodeToString( &RegistryPath, L"\\" ); }
RtlInitUnicodeString( &temp, MappingTarget->RegistryPath ); RtlAppendUnicodeStringToString( &RegistryPath, &temp ); RtlInitUnicodeString( &temp, NULL );
if (MappingFlags & REGISTRY_MAPPING_APPEND_BASE_NAME) { RtlAppendUnicodeToString( &RegistryPath, L"\\" );
RtlInitUnicodeString( &temp, BaseFileName ); RtlAppendUnicodeStringToString( &RegistryPath, &temp ); RtlInitUnicodeString( &temp, NULL ); }
if (AppendApplicationName) { RtlAppendUnicodeToString( &RegistryPath, L"\\" );
RtlInitUnicodeString( &temp, ApplicationName ); RtlAppendUnicodeStringToString( &RegistryPath, &temp ); RtlInitUnicodeString( &temp, NULL ); }
// open real registry
InitializeObjectAttributes ( &ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL );
Status = NtOpenKey ( Key, GENERIC_READ, &ObjectAttributes );
// clear registry path
RtlFreeHeap( RtlProcessHeap(), 0, RegistryPath.Buffer ); } }
// clear use string
if ( UserKeyPath.Length ) { RtlFreeUnicodeString ( &UserKeyPath ); }
if ( BaseFileName ) { delete [] BaseFileName; } } }
return Status; }
// append string to result buffer
DWORD REGISTRY_AppendBufferToResultBuffer ( IN PREGISTRY_PARAMETERS a, IN PUNICODE_STRING Buffer, IN BOOLEAN IncludeNull ) { DWORD OverflowStatus = ERROR_INVALID_PARAMETER;
if ( Buffer ) { ULONG Chars = Buffer->Length / sizeof( WCHAR );
if ( a->ResultChars + Chars >= a->ResultMaxChars ) { OverflowStatus = ERROR_MORE_DATA;
Chars = a->ResultMaxChars - a->ResultChars; if ( Chars ) { Chars -= 1; } }
if ( Chars ) { memcpy( reinterpret_cast < PBYTE > ( a->ResultBuffer ) + ( a->ResultChars * sizeof( WCHAR ) ), Buffer->Buffer, Chars * sizeof( WCHAR ) ); a->ResultChars += Chars; }
if ( OverflowStatus != ERROR_MORE_DATA ) { OverflowStatus = ERROR_SUCCESS; } }
if (IncludeNull) { if ( a->ResultChars + 1 >= a->ResultMaxChars ) { OverflowStatus = ERROR_MORE_DATA; } else { a->ResultBuffer[ a->ResultChars ] = L'\0'; a->ResultChars += 1; } }
return OverflowStatus; }
DWORD REGISTRY_AppendNULLToResultBuffer ( IN PREGISTRY_PARAMETERS a ) { return REGISTRY_AppendBufferToResultBuffer( a, NULL, TRUE ); }
NTSTATUS REGISTRY_CheckSubKeyNotEmpty ( IN HANDLE Key, IN PUNICODE_STRING SubKeyName ) { NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE SubKey = INVALID_HANDLE_VALUE; KEY_VALUE_BASIC_INFORMATION KeyValueInformation; ULONG ResultLength;
InitializeObjectAttributes( &ObjectAttributes, SubKeyName, OBJ_CASE_INSENSITIVE, Key, NULL );
Status = NtOpenKey( &SubKey, GENERIC_READ, &ObjectAttributes ); if ( NT_SUCCESS ( Status ) ) { Status = NtEnumerateValueKey ( SubKey, 0, KeyValueBasicInformation, &KeyValueInformation, sizeof( KeyValueInformation ), &ResultLength );
if ( Status == STATUS_BUFFER_OVERFLOW ) { Status = STATUS_SUCCESS; }
NtClose( SubKey ); }
return Status; }
/////////////////////////////////////////////////////////////////////////////////////////
// REAL REGISTRY FUNCTIONALITY
/////////////////////////////////////////////////////////////////////////////////////////
DWORD REGISTRY_ReadVariableValue ( IN PREGISTRY_PARAMETERS a, PREGISTRY_MAPPING_APPNAME AppNameMapping, PREGISTRY_MAPPING_VARNAME VarNameMapping, LPCWSTR VariableName ) { DWORD Status = ERROR_INVALID_PARAMETER; LPCWSTR ApplicationName = NULL;
BOOLEAN OutputVariableName = FALSE;
UNICODE_STRING EqualSign;
if ( VariableName ) { RtlInitUnicodeString ( &EqualSign, L"=" ); OutputVariableName = TRUE; }
if ( !VariableName ) { if ( ! WMIREG_GetVariableName ( a, &VariableName ) ) { VariableName = NULL; } }
if ( VariableName != NULL ) { if ( ! VarNameMapping ) { VarNameMapping = WMIREG_FindVarNameMapping ( AppNameMapping, VariableName ); }
if ( VarNameMapping != NULL ) { if ( WMIREG_GetApplicationName ( a, &ApplicationName ) ) { HANDLE Key = INVALID_HANDLE_VALUE;
Status = WMIREG_OpenMappingTarget ( a, VarNameMapping, ApplicationName, &Key );
if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE ) { NTSTATUS NtStatus;
KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; PKEY_VALUE_PARTIAL_INFORMATION p = NULL;
DWORD ResultLength = 0L;
UNICODE_STRING temp; RtlInitUnicodeString ( &temp, VariableName );
NtStatus = NtQueryValueKey ( Key, &temp, KeyValuePartialInformation, &KeyValueInformation, sizeof( KeyValueInformation ), &ResultLength );
if ( ! NT_SUCCESS ( NtStatus ) ) { if ( NtStatus == STATUS_BUFFER_OVERFLOW ) { p = reinterpret_cast < PKEY_VALUE_PARTIAL_INFORMATION > ( RtlAllocateHeap ( RtlProcessHeap(), HEAP_ZERO_MEMORY, ResultLength ) ); if ( p != NULL ) { NtStatus = NtQueryValueKey ( Key, &temp, KeyValuePartialInformation, p, ResultLength, &ResultLength );
Status = NtStatus; } else { Status = ERROR_NOT_ENOUGH_MEMORY; } } else { Status = NtStatus; } } else { p = &KeyValueInformation; }
// create results
if ( Status == ERROR_SUCCESS ) { if ( OutputVariableName ) { Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, FALSE ); if ( Status == ERROR_SUCCESS ) { Status = REGISTRY_AppendBufferToResultBuffer( a, &EqualSign, FALSE ); } }
if ( Status == ERROR_SUCCESS ) { if ( p->Type == REG_SZ ) { UNICODE_STRING Value; LPWSTR s = NULL;
Value.Buffer = reinterpret_cast < LPWSTR > ( &p->Data[ 0 ] ); if ( p->DataLength >= sizeof( UNICODE_NULL ) ) { Value.Length = static_cast< USHORT > ( p->DataLength - sizeof ( UNICODE_NULL ) ); } else { Value.Length = 0; }
Value.MaximumLength = static_cast < USHORT > (p->DataLength); s = reinterpret_cast < LPWSTR > ( Value.Buffer );
if ( a->Operation == Registry_ReadKeyValue && Value.Length >= ( 2 * sizeof( WCHAR ) ) && ( s[ 0 ] == s[ ( Value.Length - sizeof( WCHAR ) ) / sizeof( WCHAR ) ] ) && ( s[ 0 ] == L'"' || s[ 0 ] == L'\'' ) ) { Value.Buffer += 1; Value.Length -= (2 * sizeof( WCHAR )); }
Status = REGISTRY_AppendBufferToResultBuffer( a, &Value, TRUE ); } else { Status = STATUS_OBJECT_TYPE_MISMATCH; } } }
// clear buffer
if ( p && p != &KeyValueInformation ) { RtlFreeHeap( RtlProcessHeap(), 0, p ); }
NtClose ( Key ); } } } }
return Status; }
DWORD REGISTRY_ReadVariableName ( IN PREGISTRY_PARAMETERS a, PREGISTRY_MAPPING_APPNAME AppNameMapping ) { DWORD Status = ERROR_SUCCESS;
PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL; LPCWSTR ApplicationName = NULL;
HANDLE Key = INVALID_HANDLE_VALUE;
WCHAR Buffer[ 256 ]; PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
// temporary unicode strings
UNICODE_STRING temp;
VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames; while ( VarNameMapping != NULL && Status == ERROR_SUCCESS ) { RtlInitUnicodeString ( &temp, VarNameMapping->Name ); Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
if ( Status == ERROR_SUCCESS ) { VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next; } }
if ( Status == ERROR_SUCCESS ) { VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping; if ( VarNameMapping != NULL ) { if ( WMIREG_GetApplicationName ( a, &ApplicationName ) ) { Status = WMIREG_OpenMappingTarget ( a, VarNameMapping, ApplicationName, &Key );
if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE ) { KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer; for ( ULONG ValueIndex = 0; Status == ERROR_SUCCESS; ValueIndex++ ) { ULONG ResultLength = 0L;
Status = NtEnumerateValueKey( Key, ValueIndex, KeyValueBasicInformation, KeyValueInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES ) { break; }
if ( NT_SUCCESS ( Status ) ) { temp.Buffer = KeyValueInformation->Name; temp.Length = (USHORT)KeyValueInformation->NameLength; temp.MaximumLength = (USHORT)KeyValueInformation->NameLength;
Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE ); } }
if ( Status == STATUS_NO_MORE_ENTRIES ) { Status = ERROR_SUCCESS; }
NtClose ( Key ); } } else { Status = ERROR_INVALID_PARAMETER; } } }
return Status; }
DWORD REGISTRY_ReadSectionValue ( IN PREGISTRY_PARAMETERS a, PREGISTRY_MAPPING_APPNAME AppNameMapping ) { DWORD Status = ERROR_SUCCESS;
PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL; LPCWSTR ApplicationName= NULL;
WCHAR Buffer[ 256 ]; PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
HANDLE Key = INVALID_HANDLE_VALUE;
VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->VariableNames; while ( VarNameMapping != NULL && Status == ERROR_SUCCESS ) { if ( VarNameMapping->Name ) { Status = REGISTRY_ReadVariableValue ( a, AppNameMapping, VarNameMapping, VarNameMapping->Name ); if ( Status != ERROR_SUCCESS ) { if ( Status == STATUS_OBJECT_TYPE_MISMATCH ) { Status = STATUS_SUCCESS; } } }
if ( Status == ERROR_SUCCESS ) { VarNameMapping = (PREGISTRY_MAPPING_VARNAME)VarNameMapping->Next; } }
if ( Status == ERROR_SUCCESS ) { VarNameMapping = (PREGISTRY_MAPPING_VARNAME)AppNameMapping->DefaultVarNameMapping; if ( VarNameMapping != NULL) { if ( WMIREG_GetApplicationName ( a, &ApplicationName ) ) { Status = WMIREG_OpenMappingTarget ( a, VarNameMapping, ApplicationName, &Key );
if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE ) { KeyValueInformation = (PKEY_VALUE_BASIC_INFORMATION)Buffer; for ( ULONG ValueIndex = 0; Status == ERROR_SUCCESS; ValueIndex++ ) { ULONG ResultLength = 0L;
Status = NtEnumerateValueKey( Key, ValueIndex, KeyValueBasicInformation, KeyValueInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES ) { break; }
if ( NT_SUCCESS ( Status ) ) { LPWSTR VariableName = NULL;
try { if ( ( VariableName = new WCHAR [ KeyValueInformation->NameLength / sizeof ( WCHAR ) + 1 ] ) != NULL ) { wcsncpy ( VariableName, (LPWSTR)&(KeyValueInformation->Name[0]), KeyValueInformation->NameLength / sizeof ( WCHAR ) ); VariableName [ KeyValueInformation->NameLength / sizeof ( WCHAR ) ] = L'\0'; } else { Status = ERROR_NOT_ENOUGH_MEMORY; } } catch ( ... ) { if ( VariableName ) { delete [] VariableName; VariableName = NULL; }
Status = ERROR_GEN_FAILURE; }
if ( Status == ERROR_SUCCESS ) { Status = REGISTRY_ReadVariableValue( a, AppNameMapping, NULL, VariableName );
delete [] VariableName; VariableName = NULL;
if ( Status != ERROR_SUCCESS ) { if ( Status == STATUS_OBJECT_TYPE_MISMATCH ) { Status = STATUS_SUCCESS; } } } } }
if ( Status == STATUS_NO_MORE_ENTRIES ) { Status = ERROR_SUCCESS; }
NtClose ( Key ); } } } }
return Status; }
DWORD REGISTRY_ReadSectionName ( IN PREGISTRY_PARAMETERS a ) { DWORD Status = ERROR_SUCCESS;
PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; HANDLE Key = INVALID_HANDLE_VALUE;
WCHAR Buffer[ 256 ]; PKEY_BASIC_INFORMATION KeyInformation = NULL;
// temporary unicode strings
UNICODE_STRING temp;
PREGISTRY_MAPPING_NAME Mapping = NULL;
LPWSTR BaseFileName = NULL; Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
if ( Status == ERROR_SUCCESS && BaseFileName ) { Mapping = WMIREG_FindMapping ( a->Mapping, BaseFileName );
delete [] BaseFileName; BaseFileName = NULL; }
if ( Mapping ) { AppNameMapping = (PREGISTRY_MAPPING_APPNAME)Mapping->ApplicationNames; while ( AppNameMapping != NULL && Status == ERROR_SUCCESS ) { RtlInitUnicodeString ( &temp, AppNameMapping->Name ); Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE );
if ( Status == ERROR_SUCCESS ) { AppNameMapping = (PREGISTRY_MAPPING_APPNAME)AppNameMapping->Next; } }
if ( Status == ERROR_SUCCESS ) { AppNameMapping = (PREGISTRY_MAPPING_APPNAME)a->Mapping->DefaultAppNameMapping; if ( AppNameMapping != NULL ) { Status = WMIREG_OpenMappingTarget ( a, reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->DefaultVarNameMapping ), NULL, &Key );
if ( Status == ERROR_SUCCESS && Key != INVALID_HANDLE_VALUE ) { KeyInformation = (PKEY_BASIC_INFORMATION)Buffer; for ( ULONG SubKeyIndex = 0; Status == ERROR_SUCCESS; SubKeyIndex++ ) { ULONG ResultLength = 0L;
Status = NtEnumerateKey( Key, SubKeyIndex, KeyBasicInformation, KeyInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES ) { break; }
if ( NT_SUCCESS ( Status ) ) { temp.Buffer = (PWSTR)&(KeyInformation->Name[0]); temp.Length = (USHORT)KeyInformation->NameLength; temp.MaximumLength = (USHORT)KeyInformation->NameLength;
Status = REGISTRY_CheckSubKeyNotEmpty( Key, &temp );
if ( NT_SUCCESS ( Status ) ) { Status = REGISTRY_AppendBufferToResultBuffer( a, &temp, TRUE ); } else if ( Status != STATUS_NO_MORE_ENTRIES ) { break; } else { Status = STATUS_SUCCESS; } } }
if ( Status == STATUS_NO_MORE_ENTRIES ) { Status = ERROR_SUCCESS; }
NtClose ( Key ); } } } }
return Status; }
/////////////////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION
/////////////////////////////////////////////////////////////////////////////////////////
DWORD WMIRegistry_Mapping ( IN PREGISTRY_PARAMETERS a ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( a ) { if ( a->Operation == Registry_ReadSectionName ) { Status = REGISTRY_ReadSectionName ( a ); } else { LPCWSTR ApplicationName = NULL; if ( WMIREG_GetApplicationName ( a, &ApplicationName ) ) { PREGISTRY_MAPPING_NAME Mapping = NULL;
LPWSTR BaseFileName = NULL; Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
if ( Status == ERROR_SUCCESS && BaseFileName ) { Mapping = WMIREG_FindMapping ( a->Mapping, BaseFileName );
delete [] BaseFileName; BaseFileName = NULL; }
if ( Mapping ) { PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; AppNameMapping = WMIREG_FindAppNameMapping ( Mapping, ApplicationName );
if ( AppNameMapping ) { if ( a->Operation == Registry_ReadKeyValue ) { Status = REGISTRY_ReadVariableValue ( a, AppNameMapping, NULL, NULL ); } else if ( a->Operation == Registry_ReadKeyName ) { Status = REGISTRY_ReadVariableName ( a, AppNameMapping ); } else if ( a->Operation == Registry_ReadSectionValue ) { Status = REGISTRY_ReadSectionValue ( a, AppNameMapping ); } else { // not supported operation
// possible write ?
Status = ERROR_INVALID_PARAMETER; } } else { // no registry for this section
// you should use file function
Status = STATUS_MORE_PROCESSING_REQUIRED; } } } } }
return Status; }
///////////////////////////////////////////////////////////////////////////////
// ALLOCATION of reg structures
///////////////////////////////////////////////////////////////////////////////
PREGISTRY_MAPPING_TARGET MappingTargetAlloc ( IN LPCWSTR RegistryPath, OUT PULONG MappingFlags ) { BOOLEAN RelativePath = FALSE; UNICODE_STRING RegistryPathString;
PREGISTRY_MAPPING_TARGET MappingTarget = NULL;
LPCWSTR SaveRegistryPath = RegistryPath; ULONG Flags = 0L;
// simulate result
*MappingFlags = Flags;
BOOLEAN Continue = TRUE;
while ( Continue ) { try { if ( *RegistryPath == L'!' ) { Flags |= REGISTRY_MAPPING_WRITE_TO_INIFILE_TOO; RegistryPath += 1; } else if ( *RegistryPath == L'#' ) { Flags |= REGISTRY_MAPPING_INIT_FROM_INIFILE; RegistryPath += 1; } else if ( *RegistryPath == L'@' ) { Flags |= REGISTRY_MAPPING_READ_FROM_REGISTRY_ONLY; RegistryPath += 1; } else if ( !_wcsnicmp ( RegistryPath, L"USR:", 4 ) ) { Flags |= REGISTRY_MAPPING_USER_RELATIVE; RegistryPath += 4; break; } else if ( !_wcsnicmp ( RegistryPath, L"SYS:", 4 ) ) { Flags |= REGISTRY_MAPPING_SOFTWARE_RELATIVE; RegistryPath += 4; break; } else { break; } } catch ( ... ) { Continue = FALSE; } }
if ( Continue ) { if ( Flags & ( REGISTRY_MAPPING_USER_RELATIVE | REGISTRY_MAPPING_SOFTWARE_RELATIVE ) ) { RelativePath = TRUE; }
if ( ( RelativePath && *RegistryPath != OBJ_NAME_PATH_SEPARATOR ) || ( !RelativePath && *RegistryPath == OBJ_NAME_PATH_SEPARATOR ) ) { RtlInitUnicodeString( &RegistryPathString, RegistryPath ); } else if ( !RelativePath && *RegistryPath == UNICODE_NULL ) { RtlInitUnicodeString( &RegistryPathString, NULL ); } else { Continue = FALSE; }
if ( Continue ) { MappingTarget = reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_TARGET ) ) ); if ( MappingTarget != NULL ) { *MappingFlags = Flags;
MappingTarget->RegistryPath = NULL; if ( RegistryPathString.Length != 0 ) { try { if ( ( MappingTarget->RegistryPath = new WCHAR [ RegistryPathString.Length / sizeof ( WCHAR ) + 1 ] ) != NULL ) { wcsncpy ( MappingTarget->RegistryPath, RegistryPathString.Buffer, RegistryPathString.Length / sizeof ( WCHAR ) ); MappingTarget->RegistryPath [RegistryPathString.Length / sizeof ( WCHAR )] = L'\0'; } } catch ( ... ) { if ( MappingTarget->RegistryPath ) { delete [] MappingTarget->RegistryPath; MappingTarget->RegistryPath = NULL; } } } } } }
return MappingTarget; }
DWORD MappingTargetFree ( IN PREGISTRY_MAPPING_TARGET MappingTarget ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( MappingTarget ) { PREGISTRY_MAPPING_TARGET MappingTargetNext = NULL; MappingTargetNext = reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( MappingTarget->Next );
if ( MappingTargetNext ) { MappingTargetFree ( MappingTargetNext ); } if ( MappingTarget->RegistryPath ) { delete [] MappingTarget->RegistryPath; MappingTarget->RegistryPath = NULL; }
RtlFreeHeap( RtlProcessHeap(), 0, MappingTarget );
// success
Status = ERROR_SUCCESS; }
return Status; }
DWORD MappingVarNameFree ( IN PREGISTRY_MAPPING_VARNAME VarNameMapping ); BOOLEAN MappingVarNameAlloc ( PREGISTRY_MAPPING_NAME FileNameMapping, PREGISTRY_MAPPING_APPNAME AppNameMapping, PUNICODE_STRING VariableName, LPCWSTR RegistryPath, PREGISTRY_MAPPING_VARNAME *ReturnedVarNameMapping ) { PREGISTRY_MAPPING_TARGET MappingTarget = NULL;; PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL; PREGISTRY_MAPPING_VARNAME *pp;
ULONG MappingFlags = 0L;
BOOLEAN Result = FALSE; BOOLEAN Continue = TRUE;
if ( VariableName->Length != 0 ) { pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &AppNameMapping->VariableNames ); while ( VarNameMapping = *pp ) { try { if ( VarNameMapping->Name ) { if ( ! _wcsnicmp ( VariableName->Buffer, VarNameMapping->Name, VariableName->Length ) ) { break; } } } catch ( ... ) { Continue = FALSE; break; }
pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &VarNameMapping->Next ); } } else { pp = reinterpret_cast < PREGISTRY_MAPPING_VARNAME* > ( &AppNameMapping->DefaultVarNameMapping ); VarNameMapping = *pp; }
if ( Continue && VarNameMapping == NULL ) { MappingTarget = MappingTargetAlloc ( RegistryPath, &MappingFlags ); if (MappingTarget != NULL) { VarNameMapping = reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_VARNAME ) ) ); if (VarNameMapping != NULL) { VarNameMapping->MappingFlags = MappingFlags; VarNameMapping->MappingTarget = reinterpret_cast < ULONG_PTR > ( MappingTarget );
if ( VariableName->Length != 0 ) { try { if ( ( VarNameMapping->Name = new WCHAR [ VariableName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL ) { wcsncpy ( VarNameMapping->Name, VariableName->Buffer, VariableName->Length / sizeof ( WCHAR ) ); VarNameMapping->Name [VariableName->Length / sizeof ( WCHAR )] = L'\0';
Result = TRUE; } } catch ( ... ) { if ( VarNameMapping->Name ) { delete [] VarNameMapping->Name; VarNameMapping->Name = NULL; }
MappingVarNameFree ( VarNameMapping ); throw; } } else { Result = TRUE; }
*pp = VarNameMapping;
// return value
*ReturnedVarNameMapping = VarNameMapping; } } }
return Result; }
DWORD MappingVarNameFree ( IN PREGISTRY_MAPPING_VARNAME VarNameMapping ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( VarNameMapping ) { PREGISTRY_MAPPING_VARNAME VarNameMappingNext = NULL; VarNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( VarNameMapping->Next );
if ( VarNameMappingNext ) { MappingVarNameFree ( VarNameMappingNext ); }
// return status from helper ?
Status = MappingTargetFree ( reinterpret_cast < PREGISTRY_MAPPING_TARGET > ( VarNameMapping->MappingTarget ) );
if ( VarNameMapping->Name ) { delete [] VarNameMapping->Name; VarNameMapping->Name = NULL; }
RtlFreeHeap( RtlProcessHeap(), 0, VarNameMapping ); VarNameMapping = NULL;
// success
Status = ERROR_SUCCESS; }
return Status; }
DWORD MappingAppNameFree ( IN PREGISTRY_MAPPING_APPNAME AppNameMapping ); BOOLEAN MappingAppNameAlloc ( PREGISTRY_MAPPING_NAME FileNameMapping, PUNICODE_STRING ApplicationName, PREGISTRY_MAPPING_APPNAME *ReturnedAppNameMapping ) { PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; PREGISTRY_MAPPING_APPNAME *pp;
BOOLEAN Result = FALSE; BOOLEAN Continue = TRUE;
if ( ApplicationName->Length != 0 ) { pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &FileNameMapping->ApplicationNames ); while ( AppNameMapping = *pp ) { try { if ( AppNameMapping->Name ) { if ( ! _wcsnicmp ( ApplicationName->Buffer, AppNameMapping->Name, ApplicationName->Length ) ) { break; } } } catch ( ... ) { Continue = FALSE; break; }
pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &AppNameMapping->Next ); } } else { pp = reinterpret_cast < PREGISTRY_MAPPING_APPNAME* > ( &FileNameMapping->DefaultAppNameMapping ); AppNameMapping = *pp; }
if ( Continue && AppNameMapping == NULL) { AppNameMapping = reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_APPNAME ) ) ); if (AppNameMapping != NULL) { if (ApplicationName->Length != 0) { try { if ( ( AppNameMapping->Name = new WCHAR [ ApplicationName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL ) { wcsncpy ( AppNameMapping->Name, ApplicationName->Buffer, ApplicationName->Length / sizeof ( WCHAR ) ); AppNameMapping->Name [ApplicationName->Length / sizeof ( WCHAR )] = L'\0';
Result = TRUE; } } catch ( ... ) { if ( AppNameMapping->Name ) { delete [] AppNameMapping->Name; AppNameMapping->Name = NULL; }
MappingAppNameFree ( AppNameMapping ); throw; } } else { Result = TRUE; }
*pp = AppNameMapping;
// return value
*ReturnedAppNameMapping = AppNameMapping; } }
return Result; }
DWORD MappingAppNameFree ( IN PREGISTRY_MAPPING_APPNAME AppNameMapping ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( AppNameMapping ) { PREGISTRY_MAPPING_APPNAME AppNameMappingNext = NULL; AppNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( AppNameMapping->Next );
if ( AppNameMappingNext ) { MappingAppNameFree ( AppNameMappingNext ); }
MappingVarNameFree( reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->VariableNames ) ); MappingVarNameFree( reinterpret_cast < PREGISTRY_MAPPING_VARNAME > ( AppNameMapping->DefaultVarNameMapping ) );
if ( AppNameMapping->Name ) { delete [] AppNameMapping->Name; AppNameMapping->Name = NULL; }
RtlFreeHeap( RtlProcessHeap(), 0, AppNameMapping ); AppNameMapping = NULL;
// success
Status = ERROR_SUCCESS; }
return Status; }
BOOLEAN MappingNameAlloc ( IN PUNICODE_STRING FileName, OUT PREGISTRY_MAPPING_NAME *ReturnedFileNameMapping ) { PREGISTRY_MAPPING_NAME FileNameMapping = NULL;
BOOLEAN Result = FALSE;
FileNameMapping = reinterpret_cast < PREGISTRY_MAPPING_NAME > ( RtlAllocateHeap( RtlProcessHeap (), HEAP_ZERO_MEMORY, sizeof( REGISTRY_MAPPING_NAME ) ) ); if ( FileNameMapping != NULL) { if (FileName->Length != 0) { try { if ( ( FileNameMapping->Name = new WCHAR [ FileName->Length / sizeof ( WCHAR ) + 1 ] ) != NULL ) { wcsncpy ( FileNameMapping->Name, FileName->Buffer, FileName->Length / sizeof ( WCHAR ) ); FileNameMapping->Name [FileName->Length / sizeof ( WCHAR )] = L'\0';
Result = TRUE; } } catch ( ... ) { if ( FileNameMapping->Name ) { delete [] FileNameMapping->Name; FileNameMapping->Name = NULL; } } } else { Result = TRUE; }
// return value
*ReturnedFileNameMapping = FileNameMapping; }
return Result; }
DWORD MappingNameFree ( IN PREGISTRY_MAPPING_NAME FileNameMapping ) { DWORD Status = ERROR_INVALID_PARAMETER;
if ( FileNameMapping ) { PREGISTRY_MAPPING_NAME FileNameMappingNext = NULL; FileNameMappingNext = reinterpret_cast < PREGISTRY_MAPPING_NAME > ( FileNameMapping->Next );
if ( FileNameMappingNext ) { MappingNameFree ( FileNameMappingNext ); }
MappingAppNameFree( reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( FileNameMapping->ApplicationNames ) ); MappingAppNameFree( reinterpret_cast < PREGISTRY_MAPPING_APPNAME > ( FileNameMapping->DefaultAppNameMapping ) );
if ( FileNameMapping->Name ) { delete [] FileNameMapping->Name; FileNameMapping->Name = NULL; }
RtlFreeHeap( RtlProcessHeap(), 0, FileNameMapping ); FileNameMapping = NULL;
// success
Status = ERROR_SUCCESS; }
return Status; }
NTSTATUS IniFileMapping ( IN PREGISTRY_MAPPING_NAME FileNameMapping, IN HANDLE Key,
IN LPCWSTR MyApplicationName, IN LPCWSTR MyVariableName ) { NTSTATUS Status = STATUS_SUCCESS; WCHAR Buffer[ 512 ]; PKEY_BASIC_INFORMATION KeyInformation = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
HANDLE SubKeyHandle = INVALID_HANDLE_VALUE; ULONG SubKeyIndex; UNICODE_STRING ValueName; UNICODE_STRING SubKeyName;
UNICODE_STRING NullString; RtlInitUnicodeString( &NullString, NULL );
//
// Enumerate node
//
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer; for ( ULONG ValueIndex = 0; TRUE; ValueIndex++ ) { ULONG ResultLength = 0L; Status = NtEnumerateValueKey ( Key, ValueIndex, KeyValueFullInformation, KeyValueInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES ) { Status = STATUS_SUCCESS; break; } else if ( !NT_SUCCESS( Status ) ) { break; }
ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]); ValueName.Length = (USHORT)KeyValueInformation->NameLength; ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
if ( KeyValueInformation->Type == REG_SZ ) { BOOL Continue = TRUE; if ( MyApplicationName && MyVariableName ) { if ( _wcsnicmp ( ValueName.Buffer, MyVariableName, ValueName.Length / sizeof ( WCHAR ) ) ) { Continue = FALSE; } }
if ( Continue ) { if ( MappingAppNameAlloc ( FileNameMapping, &ValueName, &AppNameMapping ) ) { if ( MappingVarNameAlloc ( FileNameMapping, AppNameMapping, &NullString, (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset), &VarNameMapping ) ) { if (ValueName.Length == 0) { VarNameMapping->MappingFlags |= REGISTRY_MAPPING_APPEND_APPLICATION_NAME; } } } } } }
//
// Enumerate node's children and apply ourselves to each one
//
KeyInformation = (PKEY_BASIC_INFORMATION)Buffer; for ( ULONG SubKeyIndex = 0; TRUE; SubKeyIndex++ ) { ULONG ResultLength = 0L; Status = NtEnumerateKey ( Key, SubKeyIndex, KeyBasicInformation, KeyInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; break; } else if ( !NT_SUCCESS ( Status ) ) { break; }
SubKeyName.Buffer = (PWSTR)&(KeyInformation->Name[0]); SubKeyName.Length = (USHORT)KeyInformation->NameLength; SubKeyName.MaximumLength = (USHORT)KeyInformation->NameLength;
InitializeObjectAttributes ( &ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE, Key, NULL );
BOOL Continue = TRUE; if ( MyApplicationName ) { if ( _wcsnicmp ( SubKeyName.Buffer, MyApplicationName, SubKeyName.Length / sizeof ( WCHAR ) ) ) { Continue = FALSE; } }
if ( Continue ) { Status = NtOpenKey( &SubKeyHandle, GENERIC_READ, &ObjectAttributes );
try { if ( NT_SUCCESS( Status ) && SubKeyHandle != INVALID_HANDLE_VALUE && MappingAppNameAlloc( FileNameMapping, &SubKeyName, &AppNameMapping ) ) { KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer; for ( ULONG ValueIndex = 0; AppNameMapping != NULL; ValueIndex++ ) { Status = NtEnumerateValueKey ( SubKeyHandle, ValueIndex, KeyValueFullInformation, KeyValueInformation, sizeof( Buffer ), &ResultLength );
if ( Status == STATUS_NO_MORE_ENTRIES ) { Status = STATUS_SUCCESS; break; } else if ( !NT_SUCCESS ( Status ) ) { break; }
ValueName.Buffer = (PWSTR)&(KeyValueInformation->Name[0]); ValueName.Length = (USHORT)KeyValueInformation->NameLength; ValueName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
BOOL ContinueValue = TRUE; if ( MyApplicationName && MyVariableName ) { if ( _wcsnicmp ( ValueName.Buffer, MyVariableName, ValueName.Length / sizeof ( WCHAR ) ) ) { ContinueValue = FALSE; } }
if ( ContinueValue ) { if ( KeyValueInformation->Type == REG_SZ ) { MappingVarNameAlloc ( FileNameMapping, AppNameMapping, &ValueName, (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset), &VarNameMapping ); } } }
NtClose( SubKeyHandle ); SubKeyHandle = INVALID_HANDLE_VALUE; } } catch ( ... ) { if ( SubKeyHandle && SubKeyHandle != INVALID_HANDLE_VALUE ) { NtClose( SubKeyHandle ); SubKeyHandle = INVALID_HANDLE_VALUE; }
throw; } } }
return Status; }
DWORD WMIRegistry_InitMapping ( PREGISTRY_PARAMETERS a ) { DWORD Status = ERROR_INVALID_PARAMETER; PREGISTRY_MAPPING_NAME RegistryMapping = NULL;
if ( a ) { // prepare mapping
a->Mapping = NULL;
NTSTATUS NtStatus = STATUS_SUCCESS;
PREGISTRY_MAPPING_NAME DefaultFileNameMapping = NULL; PREGISTRY_MAPPING_NAME FileNames = NULL;
PREGISTRY_MAPPING_APPNAME AppNameMapping = NULL; PREGISTRY_MAPPING_VARNAME VarNameMapping = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE IniFileMappingRoot = INVALID_HANDLE_VALUE;
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = NULL; PKEY_BASIC_INFORMATION KeyInformation = NULL;
WCHAR Buffer[ 512 ];
LPWSTR BaseFileName = NULL; Status = WMIREG_GetBaseFileName ( a->FileName, &BaseFileName );
if ( Status == ERROR_SUCCESS && BaseFileName ) { UNICODE_STRING FullKeyName;
FullKeyName.Length = 0; FullKeyName.MaximumLength = ( wcslen ( L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\" ) + wcslen ( BaseFileName ) + 1 ) * sizeof ( WCHAR ); FullKeyName.Buffer = reinterpret_cast < PWSTR > ( RtlAllocateHeap( RtlProcessHeap(), 0, FullKeyName.MaximumLength ) );
if ( FullKeyName.Buffer != NULL ) { RtlAppendUnicodeToString ( &FullKeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\" ); RtlAppendUnicodeToString ( &FullKeyName, BaseFileName );
InitializeObjectAttributes ( &ObjectAttributes, &FullKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
NtStatus = NtOpenKey ( &IniFileMappingRoot, GENERIC_READ, &ObjectAttributes );
if ( NT_SUCCESS ( NtStatus ) && IniFileMappingRoot != INVALID_HANDLE_VALUE ) { UNICODE_STRING BaseFile; RtlInitUnicodeString ( &BaseFile, BaseFileName );
if ( ! MappingNameAlloc( &BaseFile, &FileNames ) ) { NtStatus = STATUS_NO_MEMORY; } else { try { NtStatus = IniFileMapping( FileNames, IniFileMappingRoot, a->ApplicationName, a->VariableName ); } catch ( ... ) { MappingNameFree ( FileNames ); FileNames = NULL;
NtStatus = STATUS_NO_MEMORY; }
if ( ! NT_SUCCESS ( NtStatus ) ) { if ( FileNames ) { RtlFreeHeap( RtlProcessHeap(), 0, FileNames ); FileNames = NULL; } } }
if ( NT_SUCCESS ( NtStatus ) ) { a->Mapping = FileNames; }
// close main root
if ( IniFileMappingRoot && IniFileMappingRoot != INVALID_HANDLE_VALUE ) { NtClose ( IniFileMappingRoot ); IniFileMappingRoot = NULL; } }
// clear buffer
RtlFreeHeap ( RtlProcessHeap (), 0, FullKeyName.Buffer ); } else { NtStatus = STATUS_NO_MEMORY; }
// we are done with looking for
delete [] BaseFileName; BaseFileName = NULL; }
// name has not found ( get ready for default )
if ( NT_SUCCESS ( NtStatus ) && a->Mapping == NULL ) { UNICODE_STRING KeyName; RtlInitUnicodeString ( &KeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping" );
InitializeObjectAttributes ( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
NtStatus = NtOpenKey ( &IniFileMappingRoot, GENERIC_READ, &ObjectAttributes );
if ( NT_SUCCESS ( NtStatus ) && IniFileMappingRoot != INVALID_HANDLE_VALUE ) { ULONG ResultLength = 0L;
UNICODE_STRING NullString; RtlInitUnicodeString( &NullString, NULL );
UNICODE_STRING ValueName; RtlInitUnicodeString( &ValueName, NULL );
NtStatus = NtQueryValueKey ( IniFileMappingRoot, &ValueName, KeyValuePartialInformation, KeyValueInformation, sizeof( Buffer ), &ResultLength );
try { if ( NT_SUCCESS ( NtStatus ) ) { if ( MappingNameAlloc( &NullString, &DefaultFileNameMapping ) ) { if ( MappingAppNameAlloc ( DefaultFileNameMapping, &NullString, &AppNameMapping ) ) { if ( MappingVarNameAlloc ( DefaultFileNameMapping, AppNameMapping, &NullString, (PWSTR)(KeyValueInformation->Data), &VarNameMapping ) ) { VarNameMapping->MappingFlags |= REGISTRY_MAPPING_APPEND_BASE_NAME | REGISTRY_MAPPING_APPEND_APPLICATION_NAME;
// assign proper mapping
a->Mapping = DefaultFileNameMapping; } } } } } catch ( ... ) { MappingNameFree ( DefaultFileNameMapping ); DefaultFileNameMapping = NULL;
a->Mapping = NULL;
NtStatus = STATUS_NO_MEMORY; }
// close main root
if ( IniFileMappingRoot && IniFileMappingRoot != INVALID_HANDLE_VALUE ) { NtClose ( IniFileMappingRoot ); IniFileMappingRoot = NULL; } } }
if ( a->Mapping ) { // return success
Status = ERROR_SUCCESS; } else { if ( NT_SUCCESS ( NtStatus ) ) { // we do not have mapping
Status = STATUS_MORE_PROCESSING_REQUIRED; } else { Status = NtStatus; } } }
return Status; }
DWORD WMIRegistry_ParametersInit ( #ifdef WRITE_OPERATION
BOOLEAN WriteOperation, #endif WRITE_OPERATION
REGISTRY_OPERATION Operation, BOOLEAN MultiValueStrings,
LPCWSTR FileName, LPCWSTR ApplicationName, LPCWSTR VariableName, LPWSTR VariableValue, PULONG ResultMaxChars,
PREGISTRY_PARAMETERS *ReturnedParameterBlock ) { DWORD Status = ERROR_SUCCESS; PREGISTRY_PARAMETERS a = NULL;
if ( ! ReturnedParameterBlock ) { Status = ERROR_INVALID_PARAMETER; }
if ( Status == ERROR_SUCCESS ) { try { a = new REGISTRY_PARAMETERS(); if ( a== NULL ) { Status = ERROR_NOT_ENOUGH_MEMORY; } } catch ( ... ) { if ( a ) { delete a; a = NULL; }
Status = ERROR_NOT_ENOUGH_MEMORY; } }
if ( Status == ERROR_SUCCESS ) { #ifdef WRITE_OPERATION
a->WriteOperation = WriteOperation; #endif WRITE_OPERATION
a->ValueBufferAllocated = FALSE;
a->Operation = Operation; a->MultiValueStrings = MultiValueStrings;
if ( FileName ) { a->FileName = FileName; } else { a->FileName = L"win.ini"; }
// section name
if ( ApplicationName ) { a->ApplicationName = ApplicationName; } else { a->ApplicationName = NULL; }
// key name
if ( VariableName ) { a->VariableName= VariableName; } else { a->VariableName= NULL; }
Status = WMIRegistry_InitMapping ( a ); if ( Status != ERROR_SUCCESS ) { delete a; a = NULL; } else { // key value
if ( VariableValue ) { #ifdef WRITE_OPERATION
if (a->WriteOperation) { a->ValueBuffer = VariableValue; a->ValueLength = wcslen ( VariableValue ); } else #endif WRITE_OPERATION
{ if ( ResultMaxChars ) { a->ResultMaxChars = *ResultMaxChars; } else { a->ResultMaxChars = 0; }
a->ResultChars = 0; a->ResultBuffer = VariableValue; } } else { #ifdef WRITE_OPERATION
if ( a->WriteOperation ) { a->ValueBuffer = NULL; a->ValueLength = 0; } else #endif WRITE_OPERATION
{ a->ResultMaxChars = 0; a->ResultChars = 0; a->ResultBuffer = NULL; } } } }
if ( ReturnedParameterBlock ) { *ReturnedParameterBlock = a; }
return Status; }
DWORD WMIRegistry_ParametersClear ( PREGISTRY_PARAMETERS ParameterBlock ) { DWORD Status = ERROR_SUCCESS;
if ( ! ParameterBlock ) { Status = ERROR_INVALID_PARAMETER; }
if ( Status == ERROR_SUCCESS ) { if ( ParameterBlock->Mapping ) { MappingNameFree ( ParameterBlock->Mapping ); ParameterBlock->Mapping = NULL; }
delete ParameterBlock; ParameterBlock = NULL; }
return Status; }
///////////////////////////////////////////////////////////////////////////////
// read function
///////////////////////////////////////////////////////////////////////////////
DWORD WMIRegistry ( #ifdef WRITE_OPERATION
IN BOOLEAN WriteOperation, #endif WRITE_OPERATION
IN BOOLEAN SectionOperation, IN LPCWSTR FileName, IN LPCWSTR ApplicationName, IN LPCWSTR VariableName, IN OUT LPWSTR VariableValue, IN OUT PULONG VariableValueLength ) { // variables
DWORD Status = ERROR_INVALID_PARAMETER; REGISTRY_OPERATION Operation = Registry_None; BOOLEAN MultiValueStrings = FALSE;
if ( SectionOperation ) { VariableName = NULL; }
if ( ApplicationName ) { if ( VariableValue ) { if ( VariableName ) { Operation = Registry_ReadKeyValue; } else { if ( SectionOperation ) { Operation = Registry_ReadSectionValue; MultiValueStrings = TRUE; } else { Operation = Registry_ReadKeyName; MultiValueStrings = TRUE; } } } } else { if ( ! ( SectionOperation || ! VariableValue ) ) { Operation = Registry_ReadSectionName; MultiValueStrings = TRUE; } }
// real operation
if ( Operation != Registry_None ) { PREGISTRY_PARAMETERS a = NULL;
Status = WMIRegistry_ParametersInit ( #ifdef WRITE_OPERATION
WriteOperation, #endif WRITE_OPERATION
Operation, MultiValueStrings, FileName, ApplicationName, VariableName, VariableValue, VariableValueLength, &a );
if ( Status == ERROR_SUCCESS ) { if ( a->Mapping != NULL ) { Status = WMIRegistry_Mapping( a );
if ( Status == ERROR_SUCCESS || Status == ERROR_MORE_DATA ) { if ( a->Operation == Registry_ReadKeyName || a->Operation == Registry_ReadSectionName || a->Operation == Registry_ReadSectionValue ) { REGISTRY_AppendNULLToResultBuffer ( a ); }
if ( VariableValueLength ) { *VariableValueLength = a->ResultChars; } } } else { Status = ERROR_INVALID_PARAMETER;
if ( VariableValueLength ) { *VariableValueLength = 0; } } }
WMIRegistry_ParametersClear ( a ); }
::SetLastError ( Status ); return Status; }
///////////////////////////////////////////////////////////////////////////////
// get profile string
///////////////////////////////////////////////////////////////////////////////
DWORD APIENTRY WMIRegistry_PrivateProfileString ( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName ) { DWORD Status = ERROR_SUCCESS; ULONG n = nSize;
if ( lpDefault == NULL ) { lpDefault = L""; }
Status = WMIRegistry ( #ifdef WRITE_OPERATION
FALSE, // Write operation
#endif WRITE_OPERATION
FALSE, // SectionOperation
lpFileName, lpAppName, lpKeyName, lpReturnedString, &n );
if ( n && ( Status == ERROR_SUCCESS || Status == STATUS_BUFFER_OVERFLOW ) ) { if ( Status == ERROR_SUCCESS ) { n--; } else { if ( !lpAppName || !lpKeyName ) { if ( nSize >= 2 ) { n = nSize - 2; lpReturnedString[ n+1 ] = L'\0'; } else { n = 0; } } else { if ( nSize >= 1 ) { n = nSize - 1; } else { n = 0; } } } } else { n = wcslen( lpDefault ); while ( n > 0 && lpDefault[n-1] == L' ') { n -= 1; }
if (n >= nSize) { n = nSize; }
wcsncpy ( lpReturnedString, lpDefault, n ); }
if ( n < nSize ) { lpReturnedString[ n ] = L'\0'; } else { if ( nSize > 0 ) { lpReturnedString[ nSize-1 ] = L'\0'; } }
return n; }
///////////////////////////////////////////////////////////////////////////////
// get profile section
///////////////////////////////////////////////////////////////////////////////
DWORD APIENTRY WMIRegistry_PrivateProfileSection ( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName ) { NTSTATUS Status; ULONG n;
n = nSize; Status = WMIRegistry ( #ifdef WRITE_OPERATION
FALSE, // Write operation
#endif WRITE_OPERATION
TRUE, // SectionOperation
lpFileName, lpAppName, NULL, lpReturnedString, &n );
if ( Status == ERROR_SUCCESS || Status == STATUS_BUFFER_OVERFLOW ) { if ( Status == ERROR_SUCCESS ) { n--; } else { if ( nSize >= 2 ) { n = nSize - 2; lpReturnedString[ n+1 ] = L'\0'; } else { n = 0; } } } else { n = 0; }
if ( n < nSize ) { lpReturnedString[ n ] = L'\0'; } else { if ( nSize > 0 ) { lpReturnedString[ nSize-1 ] = L'\0'; } }
return n; }
///////////////////////////////////////////////////////////////////////////////
// get profile integer
///////////////////////////////////////////////////////////////////////////////
UINT APIENTRY WMIRegistry_PrivateProfileInt ( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault ) { WCHAR ValueBuffer[ 256 ];
ULONG ReturnValue = nDefault; ULONG cb = 0;
cb = WMIRegistry_PrivateProfileString ( lpAppName, lpKeyName, NULL, ValueBuffer, sizeof( ValueBuffer ) / sizeof( WCHAR ), NULL ); if ( cb ) { // convert value to integer
_wtoi ( ValueBuffer ); }
return ReturnValue; }
///////////////////////////////////////////////////////////////////////////////
// get profile integer caller
///////////////////////////////////////////////////////////////////////////////
UINT APIENTRY WMIRegistry_ProfileInt ( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault ) { return( WMIRegistry_PrivateProfileInt ( lpAppName, lpKeyName, nDefault ) ); }
///////////////////////////////////////////////////////////////////////////////
// get profile section caller
///////////////////////////////////////////////////////////////////////////////
DWORD APIENTRY WMIRegistry_ProfileSection ( LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize ) { return( WMIRegistry_PrivateProfileSection ( lpAppName, lpReturnedString, nSize, NULL ) ); }
///////////////////////////////////////////////////////////////////////////////
// get profile string caller
///////////////////////////////////////////////////////////////////////////////
DWORD APIENTRY WMIRegistry_ProfileString ( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize ) { return( WMIRegistry_PrivateProfileString ( lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, NULL ) ); }
|