Операции с реестром с помощью Native API

Как получить доступ к реестру через функции ntdll




Для операций с реестром используются документированные в MSDN функции, названия которых оканчиваются на -Key, например для чтения из реестра используется NtQueryValueKey.

На уровне Native API реестр выглядит немного не так, как в Win32. Вместо нескольких корневых псевдоключей HKEY_XXX используется единственный ключ «\REGISTRY» с двумя подключами «\USER» и «\MACHINE». Эти два ключа соответствуют HKEY_USERS и HKEY_LOCAL_MACHINE. Эквивалента ключу HKEY_CURRENT_USER нет, ветки разных пользователей следует искать в “\USER”. Ключу HKEY_CLASSES_ROOT соответствуют разные ветви реестра, располагающиеся как в ветке “\USER”, так и в “\MACHINE”. Еще одно отличие от WinAPI в том, что работая с реестром, мы оперируем обычным типом HANDLE, а не специальным типом HKEY.

Дэниэл Мэдден еще в 2006 году написал программу с открытым исходным кодом под названием NtRegEdit — аналог стандартного редактора реестра (regedit.exe). NtRegEdit использует для доступа к реестру только функции Native API, поэтому код из программы можно перенести в своё собственное native-приложение.

В библиотеке ZenWinX также присутствует код, использующий функции реестра. Например, функция winx_register_boot_exec_command умеет, как видно из названия, прописывать команду, выполняющуюся при запуске, то есть выполнять запись в ключ реестра BootExecute.

Библиотека ntreg корейского программиста rodream содержит набор функций для работы с реестром, достаточно просто подключить к своему проекту файлы ntreg.c и ntreg.h и программа может читать и писать в реестр. В этой библиотеке отсутствует функция вывода списка ключей и значений из заданной ветки реестра, но к счастью, её несложно написать самостоятельно.

Чтобы узнать, какие подключи есть у какого-либо ключа, используется функция NtEnumerateKey.

NTSYSCALLAPI NTSTATUS NTAPI NtEnumerateKey(
    IN HANDLE KeyHandle,
    IN ULONG Index,
    IN KEY_INFORMATION_CLASS KeyInformationClass,
    OUT PVOID KeyInformation,
    IN ULONG Length,
    OUT PULONG ResultLength
);
Имена подключей будут браться из указателя на структуру KEY_NODE_INFORMATION. В параметр KeyInformationClass записываем константу KeyNodeInformation, в параметр KeyInformation помещаем указатель на структуру. Код для получения всех подключей в итоге будет выглядеть следующим образом:
ULONG ResultLength, i = 0;
char buf[BUFFER_SIZE];
PKEY_NODE_INFORMATION pki = (PKEY_NODE_INFORMATION)buf;

while (STATUS_SUCCESS == NtEnumerateKey(hKey, i++,
  KeyNodeInformation, pki, BUFFER_SIZE, &ResultLength))
{
  ;
}
Внутри этого цикла очередное имя подключа доступно как строка WCHAR pki->Name, её можно выводить на экран или сохранять в какой-нибудь внутренний список. Похожим образом можно получить список всех значений, содержащихся в ключе реестра, только используется другая функция NtEnumerateValueKey с константой KeyValueBasicInformation, а результат оказывается в структуре KEY_VALUE_BASIC_INFORMATION.
pbi = (PKEY_VALUE_BASIC_INFORMATION)buf;

while (STATUS_SUCCESS == NtEnumerateValueKey(hKey, i++,
  KeyValueBasicInformation, pbi, BUFFER_SIZE, &ResultLength))
{
  ;
}
Имя находится в строке pbi->Name, а тип значения (REG_SZ, REG_DWORD или другой) определяется в pbi->Type.

Автор: амдф
Дата: 15.04.2011


При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт.