Программирование драйверов Windows

         

Работа с Системным Реестром через вызовы ZwXxx


Все-таки наиболее богатым и основательным является набор функций для работы с Системным Реестром ZwXxx.

ZwCreateKey открывает доступ к существующему подразделу Системного Реестра или создает новый. Возвращает дескриптор открытого объекта.

ZwOpenKey открывает доступ к существующему разделу Системного Реестра и возвращает дескриптор открытого объекта (см.пример ниже).

ZwQueryKey возвращает информацию о подразделе &#8212 его класс, число и размер вложенных подразделов. Инициатор вызова должен предоставить достаточного размера буфер для принимаемой информации, иначе вызов будет завершен с кодом ошибки STATUS_BUFFER_TOO_SMALL или STATUS_BUFFER_OVERFLOW.

ZwEnumerateKey возвращает информацию о вложенных подразделах предварительно открытого подраздела Системного Реестра.

ZwEnumerateValueKey возвращает информацию о параметрах и их значениях для предварительно открытого подраздела Системного Реестра.

ZwQueryValueKey возвращает информацию о значении параметра, присутствующего в данном предварительно открытом разделе Системного Реестра. Характер возвращаемой информации определяет третий аргумент вызова, который принимает одно из значений KeyValueBasicInformation, KeyValueFullInformation или KeyValuePartialInformation. Пример применения данной функции приводится ниже.

ZwSetValueKey создает или изменяет значение параметра в открытом подразделе Системного Реестра. Для возможности применения этой функции, дескриптор подраздела при открытии должен быть получен с применением маски DesiredAccess, содержащей флаг KEY_SET_VALUE

ZwFlushKey форсирует фиксацию изменений, сделанных в открытом подразделе вызовами ZwCreateKey или ZwSetValueKey, на диске.

ZwDeleteKey удаляет открытый подраздел из Системного Реестра.

ZwClose закрывает дескриптор открытого ранее подраздела Системного Реестра, фиксирует произведенные изменения на жестком диске.

Ниже приводится пример программного кода, выполняющий операции по получении значения параметра ErrorControl из раздела Системного Реестра, который был создан для описания драйвера и поступил в процедуру DriverEntry в аргументе RegistryPath.


Для случая драйвера Example.sys этот подраздел называется HKLM\SYSTEM\ControlSet001\Services\Example, а собственно строка RegistryPath хранит значение:

L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Example"

Вся работа с Системным Реестром вынесена в отдельную функцию GetRegValueDword.

// Сначала объявляем прототип GetRegValueDword: int GetRegValueDword(PCWSTR RegPath,PCWSTR ValueName,PULONG pValue); extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { . . .

if(!GetRegValueDword( RegistryPath-&#62Buffer, L"ErrorControl", &ulValue)) { #if DBG DbgPrint("Error in GetRegValueDword."); #endif } else { #if DBG DbgPrint("RegistryPath\\ErrorControl = %x.", ulValue); #endif }

int GetRegValueDword(PCWSTR RegPath, PCWSTR ValueName, PULONG pValue) { int ReturnValue = 0; NTSTATUS status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE KeyHandle; KEY_VALUE_PARTIAL_INFORMATION *pInformation; ULONG uInformationSize; UNICODE_STRING UnicodeRegPath; UNICODE_STRING UnicodeValueName; // Инициализация UNICODE_STRING полученными // не-счетными строками двухбайтных символов RtlInitUnicodeString(&UnicodeRegPath, RegPath); RtlInitUnicodeString(&UnicodeValueName, ValueName);

// Описание атрибутов, в частности, полного имени подраздела InitializeObjectAttributes(&ObjectAttributes, &UnicodeRegPath, 0, // Flags NULL, // Root directory NULL); // Security descriptor

status = ZwOpenKey( &KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes );

if( !NT_SUCCESS(status) ) // Если не получен доступ к подразделу: { #if DBG DbgPrint("=Example= Can not open reg path %ws .", UnicodeRegPath.Buffer); DbgPrint("=Example= Status = %x.",status); if (Status==STATUS_INVALID_HANDLE) DbgPrint("=Example= STATUS_INVALID_HANDLE."); if(Status==STATUS_ACCESS_DENIED) DbgPrint ("=Example= STATUS_ACCESS_DENIED."); #endif return 0; }

// Вычисляем размер буфера для получения информации о параметре: uInformationSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG);



// Выделение области в страничной памяти. // Область будет помечена тегом 'EXaM' pInformation = (KEY_VALUE_PARTIAL_INFORMATION*) ExAllocatePoolWithTag(PagedPool, uInformationSize,'EXaM');

if( pInformation == NULL ) // Не выделена память { ZwClose(KeyHandle); return 0; }

// Получить описание типа KeyValuePartialInformation: // status = ZwQueryValueKey(KeyHandle, &UnicodeValueName, KeyValuePartialInformation, pInformation, uInformationSize, &uInformationSize );

if( !NT_SUCCESS(status) ) { #if DBG DbgPrint("=Example= ZwQueryValueKey not successful."); #endif } else { if( pInformation-&#62Type == REG_DWORD && pInformation-&#62DataLength == sizeof(ULONG) ) { RtlCopyMemory(pValue, pInformation-&#62Data, sizeof(ULONG)); ReturnValue = 1; } }

// Завершение работы ExFreePool(Information); ZwClose(KeyHandle);

return ReturnValue; }

Практически все функции для работы с Системным Реестром должны вызываться из кода, работающего на уровне IRQL равном PASSIVE_LEVEL

Содержание раздела