设为首页 收藏本站
查看: 1249|回复: 0

8、Windows驱动开发技术详解笔记(4) 基本语法回顾

[复制链接]

尚未签到

发表于 2015-5-23 14:21:20 | 显示全部楼层 |阅读模式
4、注册表操作

和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数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系列函数的封装,可以有效地简化对注册表的操作过程。
DSC0000.png
DSC0001.png
表 Zw系统注册相关函数
http://msdn.microsoft.com/en-us/library/ff566425%28VS.85%29.aspx
DSC0002.png
表 Rtl系统注册相关函数
http://msdn.microsoft.com/en-us/library/ff561822%28VS.85%29.aspx
1)读写注册表
注册表是以二元形式存储的,即“键名”和“键值”,通过键名来设置键值,其中键值分为多种情况。
DSC0003.png
表 注册键类型
通过ZwSetValueKe y 函数添加或修改注册表键值,通过ZwQueryValueKe y 函
数查询相关键值。
2)枚举
枚举注册表通常分两种情况:枚举一个注册表项的所有子项和枚举一个注册表项的所有子键。
枚举子项使用ZwQueryKey(注意不是ZwQueryValueKey)和ZwEnumerateKe y配合完成,枚举子键使用ZwQueryKey和ZwEnumerateValueKey配合完成。
我们以枚举子项来说明思路,首先利用ZwQueryKey获得某项究竟有多少个子项,然后利用ZwEnumerateKe y来获取指定子项的详细信息,这个过程是通过一个子项索引(index)来完成的。在使用ZwQueryKey时,可以将参数KeyInformationClass指定为KeyFullInformation,它对应KEY_FULL_INFORMATION结构中的SubKeys指明了该项中有多少子项。
3)一个例子如下


DSC0004.gif DSC0005.gif 代码



  1 /************************************************************************
  2
  3 * 函数名称:RegEnumTest
  4
  5 * 功能描述:测试读取注册表
  6
  7 * 参数列表:
  8
  9 * 返回 值:返回状态
10
11 *************************************************************************/
12
13 NTSTATUS
14
15 RegEnumTest()
16
17 {
18
19 UNICODE_STRING ustrRegString;
20
21 UNICODE_STRING ustrKeyName;
22
23 HANDLE hRegister;
24
25 ULONG ulSize, i = 0;
26
27 OBJECT_ATTRIBUTES obj_attrib;
28
29 NTSTATUS status;
30
31 PKEY_FULL_INFORMATION pfi;
32
33 PKEY_BASIC_INFORMATION pbi;
34
35  // 初始化
36  
37 RtlInitUnicodeString(&ustrRegString,L"\\Registry\\Machine\\SOFTWARE\\ODBC\\ODBC.INI");
38
39 InitializeObjectAttributes(&obj_attrib,
40
41  &ustrRegString,
42
43 OBJ_CASE_INSENSITIVE,
44
45 NULL,
46
47 NULL);
48
49  // 打开注册表
50
51 status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &obj_attrib);
52
53 if (NT_SUCCESS(status))
54
55 {
56
57 KdPrint(("[Test] ZwOpenKey %wZ Success!", ustrRegString));
58
59 }
60
61 // 第一次调用是为了获取需要的长度
62
63 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize);
64
65 pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);
66
67 // 第二次调用是为了获取数据
68
69 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize);
70
71 for (i = 0; i < pfi->SubKeys; i++)
72
73 {
74
75 // 获取第i 个子项的长度
76
77 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize);
78
79 pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);
80
81 // 获取第i 个子项的数据
82
83 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize);
84
85 ustrKeyName.Length = (USHORT)pbi->NameLength;
86
87 ustrKeyName.Buffer = pbi->Name;
88
89 KdPrint(("[Test] The %d SubItem Name : %wZ.\n", i, &ustrKeyName));
90
91 // 释放内存
92
93 ExFreePool(pbi);
94
95 }
96
97 ExFreePool(pfi);
98
99 ZwClose(hRegister);
100
101 return STATUS_SUCCESS;
102
103 }
  4)读与写



一般使用ZwQueryValueKey来读取注册表中键的值。要注意的是注册表中的值可能有多种数据类型。而且长度也是没有定数的。为此,在读取过程中,就可能要面对很多种可能的情况。
http://msdn.microsoft.com/en-us/library/ff567069%28VS.85%29.aspx
其参数中:
KeyValueInformationClass:本次查询所需要查询的信息类型。这有如下的三种可能。
KeyValueBasicInformation:获得基础信息,包含值名和类型。
KeyValueFullInformation:获得完整信息。包含值名、类型和值的数据。
KeyValuePartialInformation:获得局部信息。包含类型和值数据。
使用KeyValuePartialInformation最常见。
KeyValueInformation:当KeyValueInformationClass被设置为KeyValuePartialInformation时,KEY_VALUE_PARTIAL_INFORMATION结构将被返回到这个指针所指内存中。
示例代码:




代码



1 // 要读取的值的名字
2
3 UNICODE_STRING my_key_name =
4
5 RTL_CONSTANT_STRING(L”SystemRoot”);
6
7 // 用来试探大小的key_infor
8
9 KEY_VALUE_PARTIAL_INFORMATION key_infor;
10
11 // 最后实际用到的key_infor指针。内存分配在堆中
12
13 PKEY_VALUE_PARTIAL_INFORMATION ac_key_infor;
14
15 ULONG ac_length;
16
17 ……
18
19 // 前面已经打开了句柄my_key,下面如此来读取值:
20
21 status = ZwQueryValueKey(
22
23 my_key,
24
25 &my_key_name,
26
27 KeyValuePartialInformation,
28
29 &key_infor,
30
31 sizeof(KEY_VALUE_PARTIAL_INFORMATION),
32
33 &ac_length);
34
35 if(!NT_SUCCESS(status) &&
36
37 status != STATUS_BUFFER_OVERFLOW &&
38
39 status != STATUS_BUFFER_TOO_SMALL)
40
41 {
42
43 // 错误处理
44
45 …
46
47 }
48
49 // 如果没失败,那么分配足够的空间,再次读取
50
51 ac_key_infor = (PKEY_VALUE_PARTIAL_INFORMATION)
52
53 ExAllocatePoolWithTag(NonpagedPool,ac_length ,MEM_TAG);
54
55 if(ac_key_infor == NULL)
56
57 {
58
59 stauts = STATUS_INSUFFICIENT_RESOURCES;
60
61 // 错误处理
62
63 …
64
65 }
66
67 status = ZwQueryValueKey(
68
69 my_key,
70
71 &my_key_name,
72
73 KeyValuePartialInformation,
74
75 ac_key_infor,
76
77 ac_length,
78
79 &ac_length);
80
81 // 到此为止,如果status为STATUS_SUCCESS,则要读取的数据已经
82
83 // 在ac_key_infor->Data中。请转换为UNICODE_STRING
84
85 ……
  写:


一般使用函数ZwSetValueKey
http://msdn.microsoft.com/en-us/library/ff567109%28VS.85%29.aspx
其中的TileIndex参数请始终填入0。
Data是要写入的数据的开始地址,而DataSize是要写入的数据的长度。由于Data是一个空指针,因此,Data可以指向任何数据。 ZwSetValueKey执行时:如果Value已经存在,则写入覆盖,否则新建一个。下面的例子写入一个名字为“Test”,而且值为“My Test Value”的字符串值。假设my_key是一个已经打开的子键的句柄。
UNICODE_STRING name = RTL_CONSTANT_STRING(L”Test”);
PWCHAR value = { L”My Test Value” };

// 数据长度要将字符串长度加上1,把最后一个空结束符
status = ZwSetValueKey(my_key,
&name,0,REG_SZ,value,(wcslen(value)+1)*sizeof(WCHAR));
if(!NT_SUCCESS(status))
{
// 错误处理
……
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-69895-1-1.html 上篇帖子: Windows 2000 (SP4) +Visual Studio 2005中,运行Designer Model 出错(GUID = {30AE7E2B-6C0 下篇帖子: Windows 8 有戏 or 没戏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表