|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
geninst.c
Abstract:
This modules contains routines to implement GenInstall of an inf section. This is based on the code from the setupapi. Currently, it only supports a subset of GenInstall functionality i.e AddReg and DelReg and BitReg.
Author:
Santosh Jodh (santoshj) 08-Aug-1998
Environment:
Kernel mode.
Revision History:
--*/
#include "cmp.h"
#include "stdlib.h"
#include "parseini.h"
#include "geninst.h"
typedef BOOLEAN (* PFN_INFRULE)( IN PVOID InfHandle, IN PCHAR Section, IN PVOID RefData );
typedef BOOLEAN (* PFN_REGLINE)( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex );
BOOLEAN CmpProcessReg( IN PVOID InfHandle, IN PCHAR Section, IN PVOID RefData );
NTSTATUS CmpProcessAddRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex );
NTSTATUS CmpProcessDelRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex );
NTSTATUS CmpProcessBitRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex );
NTSTATUS CmpGetAddRegInfData( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex, IN ULONG ValueIndex, IN ULONG ValueType, OUT PVOID *Data, OUT PULONG DataSize );
NTSTATUS CmpOpenRegKey( IN OUT PHANDLE Key, IN OUT PULONG Disposition, IN PCHAR Root, IN PCHAR SubKey, IN ULONG DesiredAccess, IN BOOLEAN Create );
NTSTATUS CmpAppendStringToMultiSz( IN HANDLE Key, IN PCHAR ValueName, IN OUT PVOID *Data, IN OUT PULONG DataSize );
//
// Copied from setupapi.h
//
// Flags for AddReg section lines in INF. The corresponding value
// is <ValueType> in the AddReg line format given below:
//
// <RegRootString>,<SubKey>,<ValueName>,<ValueType>,<Value>...
//
// The low word contains basic flags concerning the general data type
// and AddReg action. The high word contains values that more specifically
// identify the data type of the registry value. The high word is ignored
// by the 16-bit Windows 95 SETUPX APIs.
//
#define FLG_ADDREG_BINVALUETYPE ( 0x00000001 )
#define FLG_ADDREG_NOCLOBBER ( 0x00000002 )
#define FLG_ADDREG_DELVAL ( 0x00000004 )
#define FLG_ADDREG_APPEND ( 0x00000008 ) // Currently supported only
// for REG_MULTI_SZ values.
#define FLG_ADDREG_KEYONLY ( 0x00000010 ) // Just create the key, ignore value
#define FLG_ADDREG_OVERWRITEONLY ( 0x00000020 ) // Set only if value already exists
#define FLG_ADDREG_TYPE_MASK ( 0xFFFF0000 | FLG_ADDREG_BINVALUETYPE )
#define FLG_ADDREG_TYPE_SZ ( 0x00000000 )
#define FLG_ADDREG_TYPE_MULTI_SZ ( 0x00010000 )
#define FLG_ADDREG_TYPE_EXPAND_SZ ( 0x00020000 )
#define FLG_ADDREG_TYPE_BINARY ( 0x00000000 | FLG_ADDREG_BINVALUETYPE )
#define FLG_ADDREG_TYPE_DWORD ( 0x00010000 | FLG_ADDREG_BINVALUETYPE )
#define FLG_ADDREG_TYPE_NONE ( 0x00020000 | FLG_ADDREG_BINVALUETYPE )
#define FLG_BITREG_CLEAR ( 0x00000000 )
#define FLG_BITREG_SET ( 0x00000001 )
#define FLG_BITREG_TYPE_BINARY ( 0x00000000 )
#define FLG_BITREG_TYPE_DWORD ( 0x00000002 )
//
// We currently only support AddReg and DelReg sections.
//
#define NUM_OF_INF_RULES 3
//
// GenInstall methods we support.
//
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("INITCONST")
#endif
struct { PCHAR Name; PFN_INFRULE Action; PVOID RefData; } const gInfRuleTable[NUM_OF_INF_RULES] = { {"AddReg", CmpProcessReg, (PVOID)(ULONG_PTR) CmpProcessAddRegLine}, {"DelReg", CmpProcessReg, (PVOID)(ULONG_PTR) CmpProcessDelRegLine}, {"BitReg", CmpProcessReg, (PVOID)(ULONG_PTR) CmpProcessBitRegLine} }; static const UNICODE_STRING NullString = {0, 1, L""};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,CmpAppendStringToMultiSz)
#pragma alloc_text(INIT,CmpOpenRegKey)
#pragma alloc_text(INIT,CmpGetAddRegInfData)
#pragma alloc_text(INIT,CmpProcessReg)
#pragma alloc_text(INIT,CmpProcessAddRegLine)
#pragma alloc_text(INIT,CmpProcessDelRegLine)
#pragma alloc_text(INIT,CmpProcessBitRegLine)
#pragma alloc_text(INIT,CmpGenInstall)
#endif
BOOLEAN CmpGenInstall( IN PVOID InfHandle, IN PCHAR Section )
/*++
Routine Description:
This routine does a GenInstall of the section in the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
Return Value:
TRUE iff the entire section was processed successfully.
--*/
{ ULONG ruleNumber; ULONG i; PCHAR ruleName; PCHAR regSection; BOOLEAN result = FALSE;
if (CmpSearchInfSection(InfHandle, Section)) { //
// Go through all the rules in the section and try to process
// each of them.
//
for ( ruleNumber = 0; ruleName = CmpGetKeyName(InfHandle, Section, ruleNumber); ruleNumber++) {
//
// Search for the proceesing function in our table.
//
for ( i = 0; i < NUM_OF_INF_RULES && _stricmp(ruleName, gInfRuleTable[i].Name); i++);
if ( i >= NUM_OF_INF_RULES || (regSection = CmpGetSectionLineIndex( InfHandle, Section, ruleNumber, 0)) == NULL || !CmpSearchInfSection(InfHandle, Section)) { result = FALSE; break; }
if (!(*gInfRuleTable[i].Action)(InfHandle, regSection, gInfRuleTable[i].RefData)) { result = FALSE; } }
//
// All inf rules processed.
//
if (ruleNumber) { result = TRUE; } }
return (result); }
BOOLEAN CmpProcessReg( IN PVOID InfHandle, IN PCHAR Section, IN PVOID RefData )
/*++
Routine Description:
This routine processes a AddReg section in the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
Return Value:
TRUE iff the entire section was processed successfully.
--*/
{ ULONG lineIndex; NTSTATUS status = STATUS_SUCCESS; NTSTATUS temp;
//
// Process all the lines in the xxxReg Section.
//
for ( lineIndex = 0; CmpSearchInfLine(InfHandle, Section, lineIndex); lineIndex++) { temp = (*(PFN_REGLINE)(ULONG_PTR)RefData)(InfHandle, Section, lineIndex); if (!NT_SUCCESS(temp)) { status = temp; } }
if (NT_SUCCESS(status)) { return (TRUE); }
return (FALSE); }
NTSTATUS CmpProcessAddRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex )
/*++
Routine Description:
This routine processes a AddReg line in the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
LineIndex - Index of the line to be read.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status = STATUS_UNSUCCESSFUL; PCHAR rootKeyName; PCHAR subKeyName; PCHAR valueName; ULONG flags; ULONG valueType; HANDLE key; ULONG disposition; BOOLEAN dontSet; PVOID data = 0; ULONG dataSize = 0; ANSI_STRING ansiString; UNICODE_STRING unicodeString;
//
// Get the root-key name.
//
rootKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 0); if (rootKeyName) { //
// Get the optional sub-key name.
//
subKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 1);
//
// Value name is optional. Can be NULL or "".
//
valueName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 2); //
// If we don't have a value name, the type is REG_SZ to force
// the right behavior in RegSetValueEx. Otherwise get the data type.
//
valueType = REG_SZ;
//
// Read in the flags.
//
if (!CmpGetIntField( InfHandle, Section, LineIndex, 3, &flags)) { flags = 0; }
//
// Convert the flags to the registry type.
//
switch(flags & FLG_ADDREG_TYPE_MASK) {
case FLG_ADDREG_TYPE_SZ:
valueType = REG_SZ; break;
case FLG_ADDREG_TYPE_MULTI_SZ:
valueType = REG_MULTI_SZ; break;
case FLG_ADDREG_TYPE_EXPAND_SZ:
valueType = REG_EXPAND_SZ; break;
case FLG_ADDREG_TYPE_BINARY:
valueType = REG_BINARY; break;
case FLG_ADDREG_TYPE_DWORD:
valueType = REG_DWORD; break;
case FLG_ADDREG_TYPE_NONE:
valueType = REG_NONE; break;
default :
//
// If the FLG_ADDREG_BINVALUETYPE is set, then the highword
// can contain just about any random reg data type ordinal value.
//
if(flags & FLG_ADDREG_BINVALUETYPE) { //
// Disallow the following reg data types:
//
// REG_NONE, REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ
//
valueType = HIGHWORD(flags);
if(valueType < REG_BINARY || valueType == REG_MULTI_SZ) { return (STATUS_INVALID_PARAMETER); }
} else { return (STATUS_INVALID_PARAMETER); } break; }
//
// Presently, the append behavior flag is only supported for
// REG_MULTI_SZ values.
//
if((flags & FLG_ADDREG_APPEND) && valueType != REG_MULTI_SZ) { return (STATUS_INVALID_PARAMETER); }
//
// W9x compatibility.
//
if( (!valueName || *valueName == '\0') && valueType == REG_EXPAND_SZ) { valueType = REG_SZ; }
//
// Open the specified key if possible.
//
status = CmpOpenRegKey( &key, &disposition, rootKeyName, subKeyName, KEY_ALL_ACCESS, (BOOLEAN)!(flags & FLG_ADDREG_OVERWRITEONLY));
if (NT_SUCCESS(status)) { //
// Respect the key only flag.
//
if (!(flags & FLG_ADDREG_KEYONLY)) { status = CmpGetAddRegInfData( InfHandle, Section, LineIndex, 4, valueType, &data, &dataSize); if (NT_SUCCESS(status)) { //
// This variable gets set to TRUE if we dont actually want to set
// the value.
//
dontSet = FALSE; if (flags & FLG_ADDREG_APPEND) { status = CmpAppendStringToMultiSz( key, valueName, &data, &dataSize); } if (NT_SUCCESS(status)) { //
// W9x compatibility.
//
if (disposition == REG_OPENED_EXISTING_KEY) { if ( (flags & FLG_ADDREG_NOCLOBBER) && (valueName == NULL || *valueName == '\0')) { status = NtQueryValueKey( key, (PUNICODE_STRING)&NullString, KeyValueBasicInformation, NULL, 0, &disposition); if (NT_SUCCESS(status) || status == STATUS_BUFFER_TOO_SMALL) { flags &= ~FLG_ADDREG_NOCLOBBER; } status = STATUS_SUCCESS; }
if (flags & FLG_ADDREG_DELVAL) { //
// setupx compatibility.
//
dontSet = TRUE; if (valueName) { //
// Delete the specified value.
//
RtlInitAnsiString(&ansiString, valueName); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { status = NtDeleteValueKey(key, &unicodeString); RtlFreeUnicodeString(&unicodeString); } } } } else { flags &= ~FLG_ADDREG_NOCLOBBER; }
if (!dontSet) { //
// If no clobber flag is set, make sure that the value does not
// already exist.
//
RtlInitAnsiString(&ansiString, valueName); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { NTSTATUS existStatus;
if (flags & FLG_ADDREG_NOCLOBBER) { existStatus = NtQueryValueKey( key, &unicodeString, KeyValueBasicInformation, NULL, 0, &disposition); if (NT_SUCCESS(existStatus) || existStatus == STATUS_BUFFER_TOO_SMALL) { dontSet = TRUE; } } else { if (flags & FLG_ADDREG_OVERWRITEONLY) { existStatus = NtQueryValueKey( key, &unicodeString, KeyValueBasicInformation, NULL, 0, &disposition); if (!NT_SUCCESS(existStatus) && existStatus != STATUS_BUFFER_TOO_SMALL) { dontSet = TRUE; } } }
if (!dontSet) { status = NtSetValueKey( key, &unicodeString, 0, valueType, data, dataSize); }
RtlFreeUnicodeString(&unicodeString); } } } } } NtClose(key); } else if (flags & FLG_ADDREG_OVERWRITEONLY) { status = STATUS_SUCCESS; } }
return (status); }
NTSTATUS CmpProcessDelRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex )
/*++
Routine Description:
This routine processes a DelReg line in the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
LineIndex - Index of the line to be read.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status = STATUS_UNSUCCESSFUL; PCHAR rootKeyName; PCHAR subKeyName; PCHAR valueName; HANDLE key; ULONG disposition; ANSI_STRING ansiString; UNICODE_STRING unicodeString;
//
// Read the required fields.
//
rootKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 0);
subKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 1);
if (rootKeyName && subKeyName) { //
// Read the optional field.
//
valueName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 2);
//
// Open the specified registry key.
//
status = CmpOpenRegKey( &key, &disposition, rootKeyName, subKeyName, KEY_ALL_ACCESS, FALSE);
//
// Proceed if we successfully opened the registry key.
//
if (NT_SUCCESS(status)) {
//
// If the key was successfully opened, do the DelReg.
//
if (valueName) { //
// Delete the specified value.
//
RtlInitAnsiString(&ansiString, valueName); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { status = NtDeleteValueKey(key, &unicodeString); RtlFreeUnicodeString(&unicodeString); } } else { //
// No value specified. The subkey needs to be deleted.
//
status = NtDeleteKey(key); }
//
// Close the key handle.
//
NtClose(key); } }
return (status); }
NTSTATUS CmpProcessBitRegLine( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex )
/*++
Routine Description:
This routine processes a BitReg line in the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
LineIndex - Index of the line to be read.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status = STATUS_UNSUCCESSFUL; PCHAR rootKeyName; PCHAR subKeyName; PCHAR valueName; ULONG flags; ULONG mask; ULONG field = 0; HANDLE key; ULONG disposition; ANSI_STRING ansiString; UNICODE_STRING unicodeString; PCHAR buffer; ULONG size; PKEY_VALUE_FULL_INFORMATION valueInfo;
//
// Get the root-key name.
//
rootKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 0); if (rootKeyName) { //
// Get the optional sub-key name.
//
subKeyName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 1);
//
// Value name is optional. Can be NULL or "".
//
valueName = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, 2); if (valueName && *valueName) { //
// Read in the flags.
//
if (!CmpGetIntField( InfHandle, Section, LineIndex, 3, &flags)) { flags = 0; }
if (!CmpGetIntField( InfHandle, Section, LineIndex, 4, &mask)) { mask = 0; }
if (!(flags & FLG_BITREG_TYPE_DWORD)) { if (!CmpGetIntField( InfHandle, Section, LineIndex, 5, &field)) { return (status); } }
//
// Open the specified registry key.
//
status = CmpOpenRegKey( &key, &disposition, rootKeyName, subKeyName, KEY_QUERY_VALUE | KEY_SET_VALUE, FALSE); if (NT_SUCCESS(status)) { //
// Read the existing data.
//
RtlInitAnsiString(&ansiString, valueName); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { size = 0; status = NtQueryValueKey( key, &unicodeString, KeyValueFullInformation, NULL, 0, &size); if (size) { status = STATUS_NO_MEMORY; buffer = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG); if (buffer) { status = NtQueryValueKey( key, &unicodeString, KeyValueFullInformation, buffer, size, &size); if (NT_SUCCESS(status)) { valueInfo = (PKEY_VALUE_FULL_INFORMATION)buffer; if (flags & FLG_BITREG_TYPE_DWORD) { if (valueInfo->Type == REG_DWORD && valueInfo->DataLength == sizeof(ULONG)) { if (flags & FLG_BITREG_SET) { *(PULONG)(buffer + valueInfo->DataOffset) |= mask; } else { *(PULONG)(buffer + valueInfo->DataOffset) &= ~mask; } } } else { if (valueInfo->Type == REG_BINARY && field < valueInfo->DataLength) { if (flags & FLG_BITREG_SET) { *(PUCHAR)(buffer + valueInfo->DataOffset + field) |= mask; } else { *(PUCHAR)(buffer + valueInfo->DataOffset + field) &= ~mask; } } } status = NtSetValueKey( key, &unicodeString, 0, valueInfo->Type, buffer + valueInfo->DataOffset, valueInfo->DataLength); } else { #ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"Value cannot be read for BitReg in %s line %d\n", Section, LineIndex); #endif //_CM_LDR_
ASSERT(NT_SUCCESS(status)); } ExFreePool(buffer); } else { ASSERT(buffer); status = STATUS_NO_MEMORY; } }
RtlFreeUnicodeString(&unicodeString); } //
// Close the key handle.
//
NtClose(key); } } }
return (status); }
NTSTATUS CmpGetAddRegInfData( IN PVOID InfHandle, IN PCHAR Section, IN ULONG LineIndex, IN ULONG ValueIndex, IN ULONG ValueType, OUT PVOID *Data, OUT PULONG DataSize )
/*++
Routine Description:
This routine reads AddReg data from the inf.
Input Parameters:
InfHandle - Handle to the inf to be read.
Section - Name of the section to be read.
LineIndex - Index of the line to be read.
ValueIndex - Index of the value to be read.
ValueType - Data type to be read.
Data - Receives pointer to the buffer in which data has been read.
DataSize - Receives the size of the data buffer.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status = STATUS_UNSUCCESSFUL; PCHAR str; ULONG count; ULONG i; ANSI_STRING ansiString; UNICODE_STRING unicodeString;
//
// Validate the required fields.
//
ASSERT(Data); ASSERT(DataSize);
switch (ValueType) { case REG_DWORD:
*DataSize = sizeof(ULONG); *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG); if (*Data) { //
// DWORD data is specified as four bytes in W9x.
//
if (CmpGetSectionLineIndexValueCount( InfHandle, Section, LineIndex) == 8) { if (!CmpGetBinaryField( InfHandle, Section, LineIndex, ValueIndex, *Data, *DataSize, NULL)) { *((PULONG)*Data) = 0; }
status = STATUS_SUCCESS; } else { //
// Get the DWORD value.
//
if (!CmpGetIntField( InfHandle, Section, LineIndex, 4, *Data)) { *((PULONG)*Data) = 0; }
status = STATUS_SUCCESS; } } else { ASSERT(*Data); status = STATUS_NO_MEMORY; }
break;
case REG_SZ: case REG_EXPAND_SZ:
//
// Null terminated string. Gets converted to unicode before being
// added into the registry.
//
str = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, ValueIndex); if (str) { RtlInitAnsiString(&ansiString, str); *DataSize = (ansiString.Length << 1) + sizeof(UNICODE_NULL); unicodeString.MaximumLength = (USHORT)*DataSize; unicodeString.Buffer = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG); *Data = NULL; if (unicodeString.Buffer) { status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE); if (NT_SUCCESS(status)) { *Data = unicodeString.Buffer; status = STATUS_SUCCESS; } } else { ASSERT(unicodeString.Buffer); status = STATUS_NO_MEMORY; } } else { ASSERT(str); status = STATUS_NO_MEMORY; }
break;
case REG_MULTI_SZ:
*DataSize = 0; *Data = NULL;
//
// Loop to determine the total memory that needs to be allocated.
//
count = CmpGetSectionLineIndexValueCount( InfHandle, Section, LineIndex); if (count > ValueIndex) { count -= ValueIndex; for (i = 0; i < count; i++) { str = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, ValueIndex + i); if (str == NULL) { break; }
*DataSize += (ULONG)((strlen(str) * sizeof(WCHAR)) + sizeof(UNICODE_NULL)); }
if (i == count) { //
// Account for the terminating NULL.
//
*DataSize += sizeof(UNICODE_NULL); *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG); if (*Data) { for ( i = 0, unicodeString.Buffer = *Data; i < count; i++, unicodeString.Buffer = (PWCHAR)((PCHAR)unicodeString.Buffer + unicodeString.MaximumLength)) { str = CmpGetSectionLineIndex( InfHandle, Section, LineIndex, ValueIndex + i); if (str == NULL) { break; } RtlInitAnsiString(&ansiString, str); unicodeString.MaximumLength = (ansiString.Length * sizeof(WCHAR)) + sizeof(UNICODE_NULL); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE); if (!NT_SUCCESS(status)) { break; } }
//
// Terminate the multi-sz string.
//
if (i == count) { unicodeString.Buffer[0] = UNICODE_NULL; status = STATUS_SUCCESS; } } else { ASSERT(*Data); status = STATUS_NO_MEMORY; } } }
break;
case REG_BINARY: default:
//
// Free form binary data.
//
if (CmpGetBinaryField( InfHandle, Section, LineIndex, ValueIndex, NULL, 0, DataSize) && *DataSize) { *Data = ExAllocatePoolWithTag(PagedPool, *DataSize, CM_GENINST_TAG); if (*Data) { if (CmpGetBinaryField( InfHandle, Section, LineIndex, 4, *Data, *DataSize, NULL)) { status = STATUS_SUCCESS; } } else { ASSERT(*Data); status = STATUS_NO_MEMORY; } } else { status = STATUS_UNSUCCESSFUL; }
break; }
return (status); }
NTSTATUS CmpOpenRegKey( IN OUT PHANDLE Key, IN OUT PULONG Disposition, IN PCHAR Root, IN PCHAR SubKey, IN ULONG DesiredAccess, IN BOOLEAN Create )
/*++
Routine Description:
This routine opens\creates a handle to the registry key.
Input Parameters:
Key - Receives the handle to the key.
Disposition - Receives the disposition of the key.
Root - Abbreviated name of the root key.
SubKey - Name of the subkey under the root.
DesiredAccess - Desired access flags for the key.
Create - TRUE if the key needs to be created instead of opened.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status = STATUS_OBJECT_NAME_INVALID; SIZE_T size; PCHAR str; ANSI_STRING ansiString; UNICODE_STRING unicodeString; OBJECT_ATTRIBUTES objectAttributes;
str = NULL; size = strlen(SubKey) + 1;
//
// Check if we understand the specified root name.
//
if (_stricmp(Root, "HKLM") == 0) { size += (sizeof("\\Registry\\Machine\\") - 1); // Already added one above for NULL
str = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG); if (str) { _snprintf(str, size, "\\Registry\\Machine\\%s", SubKey); str[size - 1] = 0; } else { ASSERT(str); status = STATUS_NO_MEMORY; } } else { ASSERT(_stricmp(Root, "HKLM") == 0); }
//
// Proceed if we have a valid key name.
//
if (str) { RtlInitAnsiString(&ansiString, str); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { InitializeObjectAttributes( &objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); if (Create) { //
// Create a new key or open an existing one.
//
status = NtCreateKey( Key, DesiredAccess, &objectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, Disposition ? Disposition : (PULONG)&size); } else { //
// Open existing key.
//
if (Disposition) { *Disposition = REG_OPENED_EXISTING_KEY; } status = NtOpenKey( Key, DesiredAccess, &objectAttributes); }
RtlFreeUnicodeString(&unicodeString); } else { ASSERT(NT_SUCCESS(status)); }
ExFreePool(str); }
return (status); }
NTSTATUS CmpAppendStringToMultiSz( IN HANDLE Key, IN PCHAR ValueName, IN OUT PVOID *Data, IN OUT PULONG DataSize )
/*++
Routine Description:
This routine opens\creates a handle to the registry key.
Input Parameters:
Key - Receives the handle to the key.
ValueName - Name of the value to be appended to.
Data - Buffer containing the multi-sz to be appended.
DataSize - Size of the data.
Return Value:
Standard NT status value.
--*/
{ NTSTATUS status; ULONG size; ANSI_STRING ansiString; UNICODE_STRING unicodeString; PKEY_VALUE_FULL_INFORMATION valueInfo; PVOID buffer; PVOID str;
ASSERT(DataSize && *DataSize); ASSERT(*Data);
RtlInitAnsiString(&ansiString, ValueName); status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); if (NT_SUCCESS(status)) { size = 0; status = NtQueryValueKey( Key, &unicodeString, KeyValueFullInformation, NULL, 0, &size); if (size) { buffer = ExAllocatePoolWithTag(PagedPool, size, CM_GENINST_TAG); if (buffer) { status = NtQueryValueKey( Key, &unicodeString, KeyValueFullInformation, buffer, size, &size); if (NT_SUCCESS(status)) { valueInfo = (PKEY_VALUE_FULL_INFORMATION)buffer; str = ExAllocatePoolWithTag( PagedPool, valueInfo->DataLength + *DataSize - sizeof(UNICODE_NULL), CM_GENINST_TAG); if (str) { memcpy( str, (PCHAR)buffer + valueInfo->DataOffset, valueInfo->DataLength); memcpy( (PCHAR)str + valueInfo->DataLength - sizeof(UNICODE_NULL), *Data, *DataSize); ExFreePool(*Data); *Data = str; *DataSize += valueInfo->DataLength - sizeof(UNICODE_NULL); } else { #ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpAppendStringToMultiSz: Failed to allocate memory!\n"); #endif //_CM_LDR_
ASSERT(str); status = STATUS_NO_MEMORY; } } ExFreePool(buffer); } else { #ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpAppendStringToMultiSz: Failed to allocate memory!\n"); #endif //_CM_LDR_
ASSERT(buffer); status = STATUS_NO_MEMORY; } } RtlFreeUnicodeString(&unicodeString); }
return (status); }
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif
|