8、Windows驱动开发技术详解笔记(4) 基本语法回顾
时间:2010-10-18 来源:edwardlewiswe
和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey 完成。与ZwCreateFile函数类似,它通过一个OBJECT_ATTRIBUTES 获得需要创建或打开的路径信息,但在内核中这个路径与用户模式下不相同,实际上,因为用户模式下的应用程序总是由某个“当前用户”打开的,因此在用户模式下可以直接访问HKEY_CLASSES_ROOT 和HKEY_CURRENT_USER,但工作在内核模式下的驱动程序不属于任何一个用户,因此不能直接访问这两个根键。
如果ZwCreateKey 指定的项不存在,则会直接创建该项,同时由函数的Disposition参数返回REG_CREATED_NEW_KEY;如果指定项已经存在了,则 Disposition返回值REG_OPENED_EXISTING_KEY。DDK同样提供了一个ZwOpenKey函数用以简化打开注册表的操作。同时DDK还提供一系列以Rtl 开头的运行时函数,它们可以是对Zw系列函数的封装,可以有效地简化对注册表的操作过程。
表 Zw系统注册相关函数
http://msdn.microsoft.com/en-us/library/ff566425%28VS.85%29.aspx
表 Rtl系统注册相关函数
http://msdn.microsoft.com/en-us/library/ff561822%28VS.85%29.aspx
1)读写注册表
注册表是以二元形式存储的,即“键名”和“键值”,通过键名来设置键值,其中键值分为多种情况。
表 注册键类型
通过ZwSetValueKe y 函数添加或修改注册表键值,通过ZwQueryValueKe y 函
数查询相关键值。
2)枚举
枚举注册表通常分两种情况:枚举一个注册表项的所有子项和枚举一个注册表项的所有子键。
枚举子项使用ZwQueryKey(注意不是ZwQueryValueKey)和ZwEnumerateKe y配合完成,枚举子键使用ZwQueryKey和ZwEnumerateValueKey配合完成。
我们以枚举子项来说明思路,首先利用ZwQueryKey获得某项究竟有多少个子项,然后利用ZwEnumerateKe y来获取指定子项的详细信息,这个过程是通过一个子项索引(index)来完成的。在使用ZwQueryKey时,可以将参数KeyInformationClass指定为KeyFullInformation,它对应KEY_FULL_INFORMATION结构中的SubKeys指明了该项中有多少子项。
3)一个例子如下
/************************************************************************
* 函数名称:RegEnumTest
* 功能描述:测试读取注册表
* 参数列表:
* 返回 值:返回状态
*************************************************************************/
NTSTATUS
RegEnumTest()
{
UNICODE_STRING ustrRegString;
UNICODE_STRING ustrKeyName;
HANDLE hRegister;
ULONG ulSize, i = 0;
OBJECT_ATTRIBUTES obj_attrib;
NTSTATUS status;
PKEY_FULL_INFORMATION pfi;
PKEY_BASIC_INFORMATION pbi;
// 初始化
RtlInitUnicodeString(&ustrRegString,L"\\Registry\\Machine\\SOFTWARE\\ODBC\\ODBC.INI");
InitializeObjectAttributes(&obj_attrib,
&ustrRegString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
// 打开注册表
status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &obj_attrib);
if (NT_SUCCESS(status))
{
KdPrint(("[Test] ZwOpenKey %wZ Success!", ustrRegString));
}
// 第一次调用是为了获取需要的长度
ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize);
pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);
// 第二次调用是为了获取数据
ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize);
for (i = 0; i < pfi->SubKeys; i++)
{
// 获取第i 个子项的长度
ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize);
pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);
// 获取第i 个子项的数据
ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize);
ustrKeyName.Length = (USHORT)pbi->NameLength;
ustrKeyName.Buffer = pbi->Name;
KdPrint(("[Test] The %d SubItem Name : %wZ.\n", i, &ustrKeyName));
// 释放内存
ExFreePool(pbi);
}
ExFreePool(pfi);
ZwClose(hRegister);
return STATUS_SUCCESS;
}