22、Windows内核函数(3)Windows驱动开发详解笔记,注册表操作

注册表项相当于文件夹,注册表子项子文件夹(类似目录)。 

1、创建关闭 

ZwCreateKey  

示例代码

代码
1 VOID CreateRegTest()
2 {
3 //创建或打开某注册表项目
4 UNICODE_STRING RegUnicodeString;
5 HANDLE hRegister;
6
7 //初始化UNICODE_STRING字符串
8 RtlInitUnicodeString( &RegUnicodeString,
9 MY_REG_SOFTWARE_KEY_NAME);
10
11 OBJECT_ATTRIBUTES objectAttributes;
12 //初始化objectAttributes
13 InitializeObjectAttributes(&objectAttributes,
14 &RegUnicodeString,
15 OBJ_CASE_INSENSITIVE,//对大小写敏感
16 NULL,
17 NULL );
18 ULONG ulResult;
19 //创建或带开注册表项目
20 NTSTATUS ntStatus = ZwCreateKey( &hRegister,
21 KEY_ALL_ACCESS,
22 &objectAttributes,
23 0,
24 NULL,
25 REG_OPTION_NON_VOLATILE,
26 &ulResult);
27
28 if (NT_SUCCESS(ntStatus))
29 {
30 //判断是被新创建,还是已经被创建
31 if(ulResult==REG_CREATED_NEW_KEY)
32 {
33 KdPrint(("The register item is created\n"));
34 }else if(ulResult==REG_OPENED_EXISTING_KEY)
35 {
36 KdPrint(("The register item has been created,and now is opened\n"));
37 }
38 }
39
40 //(2)创建或打开某注册表项目的子项
41 UNICODE_STRING subRegUnicodeString;
42 HANDLE hSubRegister;
43
44 //初始化UNICODE_STRING字符串
45 RtlInitUnicodeString( &subRegUnicodeString,
46 L"SubItem");
47
48 OBJECT_ATTRIBUTES subObjectAttributes;
49 //初始化subObjectAttributes
50 InitializeObjectAttributes(&subObjectAttributes,
51 &subRegUnicodeString,
52 OBJ_CASE_INSENSITIVE,//对大小写敏感
53 hRegister,
54 NULL );
55 //创建或带开注册表项目
56 ntStatus = ZwCreateKey( &hSubRegister,
57 KEY_ALL_ACCESS,
58 &subObjectAttributes,
59 0,
60 NULL,
61 REG_OPTION_NON_VOLATILE,
62 &ulResult);
63
64 if (NT_SUCCESS(ntStatus))
65 {
66 //判断是被新创建,还是已经被创建
67 if(ulResult==REG_CREATED_NEW_KEY)
68 {
69 KdPrint(("The sub register item is created\n"));
70 }else if(ulResult==REG_OPENED_EXISTING_KEY)
71 {
72 KdPrint(("The sub register item has been created,and now is opened\n"));
73 }
74 }
75
76 //关闭注册表句柄
77 ZwClose(hRegister);
78 ZwClose(hSubRegister);
79 }
80
2、打开 

ZwOpenKey  

3、添加、修改、注册表键值 

ZwSetValueKey  

示例代码

代码
1 VOID SetRegTest()
2 {
3 UNICODE_STRING RegUnicodeString;
4 HANDLE hRegister;
5
6 //初始化UNICODE_STRING字符串
7 RtlInitUnicodeString( &RegUnicodeString,
8 MY_REG_SOFTWARE_KEY_NAME);
9
10 OBJECT_ATTRIBUTES objectAttributes;
11 //初始化objectAttributes
12 InitializeObjectAttributes(&objectAttributes,
13 &RegUnicodeString,
14 OBJ_CASE_INSENSITIVE,//对大小写敏感
15 NULL,
16 NULL );
17 //打开注册表
18 NTSTATUS ntStatus = ZwOpenKey( &hRegister,
19 KEY_ALL_ACCESS,
20 &objectAttributes);
21
22 if (NT_SUCCESS(ntStatus))
23 {
24 KdPrint(("Open register successfully\n"));
25 }
26
27 UNICODE_STRING ValueName;
28 //初始化ValueName
29 RtlInitUnicodeString( &ValueName, L"REG_DWORD value");
30
31 //设置REG_DWORD子键
32 ULONG ulValue = 1000;
33 ZwSetValueKey(hRegister,
34 &ValueName,
35 0,
36 REG_DWORD,
37 &ulValue,
38 sizeof(ulValue));
39
40 //初始化ValueName
41 RtlInitUnicodeString( &ValueName, L"REG_SZ value");
42 WCHAR* strValue = L"hello world";
43
44 //设置REG_SZ子键
45 ZwSetValueKey(hRegister,
46 &ValueName,
47 0,
48 REG_SZ,
49 strValue,
50 wcslen(strValue)*2+2);
51
52
53 //初始化ValueName
54 RtlInitUnicodeString( &ValueName, L"REG_BINARY value");
55
56 UCHAR buffer[10];
57 RtlFillMemory(buffer,sizeof(buffer),0xFF);
58
59 //设置REG_MULTI_SZ子键
60 ZwSetValueKey(hRegister,
61 &ValueName,
62 0,
63 REG_BINARY,
64 buffer,
65 sizeof(buffer));
66
67 //关闭注册表句柄
68 ZwClose(hRegister);
69 }
70
4、查询 

ZwQueryValueKey  

来查询注册表项。 

1)用ZwQueryValueKey 获取数据结构的长度。

2)分配如此长度的内存。

3)再次调用ZwQueryValueKey 查询。

4)回收内存。

示例代码

代码
1 VOID QueryRegTest()
2 {
3 UNICODE_STRING RegUnicodeString;
4 HANDLE hRegister;
5
6 //初始化UNICODE_STRING字符串
7 RtlInitUnicodeString( &RegUnicodeString,
8 MY_REG_SOFTWARE_KEY_NAME);
9
10 OBJECT_ATTRIBUTES objectAttributes;
11 //初始化objectAttributes
12 InitializeObjectAttributes(&objectAttributes,
13 &RegUnicodeString,
14 OBJ_CASE_INSENSITIVE,//对大小写敏感
15 NULL,
16 NULL );
17 //打开注册表
18 NTSTATUS ntStatus = ZwOpenKey( &hRegister,
19 KEY_ALL_ACCESS,
20 &objectAttributes);
21
22 if (NT_SUCCESS(ntStatus))
23 {
24 KdPrint(("Open register successfully\n"));
25 }
26
27 UNICODE_STRING ValueName;
28 //初始化ValueName
29 RtlInitUnicodeString( &ValueName, L"REG_DWORD value");
30
31 //读取REG_DWORD子键
32 ULONG ulSize;
33 ntStatus = ZwQueryValueKey(hRegister,
34 &ValueName,
35 KeyValuePartialInformation ,
36 NULL,
37 0,
38 &ulSize);
39
40 if (ntStatus==STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0)
41 {
42 ZwClose(hRegister);
43 KdPrint(("The item is not exist\n"));
44 return;
45 }
46 PKEY_VALUE_PARTIAL_INFORMATION pvpi =
47 (PKEY_VALUE_PARTIAL_INFORMATION)
48 ExAllocatePool(PagedPool,ulSize);
49
50 ntStatus = ZwQueryValueKey(hRegister,
51 &ValueName,
52 KeyValuePartialInformation ,
53 pvpi,
54 ulSize,
55 &ulSize);
56 if (!NT_SUCCESS(ntStatus))
57 {
58 ZwClose(hRegister);
59 KdPrint(("Read regsiter error\n"));
60 return;
61 }
62 //判断是否为REG_DWORD类型
63 if (pvpi->Type==REG_DWORD && pvpi->DataLength==sizeof(ULONG))
64 {
65 PULONG pulValue = (PULONG) pvpi->Data;
66 KdPrint(("The value:%d\n",*pulValue));
67 }
68
69 ExFreePool(pvpi);
70
71 //初始化ValueName
72 RtlInitUnicodeString( &ValueName, L"REG_SZ value");
73 //读取REG_SZ子键
74 ntStatus = ZwQueryValueKey(hRegister,
75 &ValueName,
76 KeyValuePartialInformation ,
77 NULL,
78 0,
79 &ulSize);
80
81 if (ntStatus==STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0)
82 {
83 ZwClose(hRegister);
84 KdPrint(("The item is not exist\n"));
85 return;
86 }
87 pvpi =
88 (PKEY_VALUE_PARTIAL_INFORMATION)
89 ExAllocatePool(PagedPool,ulSize);
90
91 ntStatus = ZwQueryValueKey(hRegister,
92 &ValueName,
93 KeyValuePartialInformation ,
94 pvpi,
95 ulSize,
96 &ulSize);
97 if (!NT_SUCCESS(ntStatus))
98 {
99 ZwClose(hRegister);
100 KdPrint(("Read regsiter error\n"));
101 return;
102 }
103 //判断是否为REG_SZ类型
104 if (pvpi->Type==REG_SZ)
105 {
106 KdPrint(("The value:%S\n",pvpi->Data));
107 }
108
109 ZwClose(hRegister);
110 }
5、枚举子项

ZwQueryKeyZwEnumerateKey 来枚举子项。

 ZwQueryKey获取某注册表项究竟有多少个子项,而ZwEnumerateKey 针对第几个子项获取该子项的具体信息。

我们发现,凡是调用有长度的函数,一般都是两次调用,第一次调用来获得具体查询(使用该函数)需要的内存需要多大长度,第二次调用时来查询具体信息。

示例代码

 

代码
1 VOID EnumerateSubItemRegTest()
2 {
3 UNICODE_STRING RegUnicodeString;
4 HANDLE hRegister;
5
6 //初始化UNICODE_STRING字符串
7 RtlInitUnicodeString( &RegUnicodeString,
8 MY_REG_SOFTWARE_KEY_NAME);
9
10 OBJECT_ATTRIBUTES objectAttributes;
11 //初始化objectAttributes
12 InitializeObjectAttributes(&objectAttributes,
13 &RegUnicodeString,
14 OBJ_CASE_INSENSITIVE,//对大小写敏感
15 NULL,
16 NULL );
17 //打开注册表
18 NTSTATUS ntStatus = ZwOpenKey( &hRegister,
19 KEY_ALL_ACCESS,
20 &objectAttributes);
21
22 if (NT_SUCCESS(ntStatus))
23 {
24 KdPrint(("Open register successfully\n"));
25 }
26
27 ULONG ulSize;
28 //第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度
29 ZwQueryKey(hRegister,
30 KeyFullInformation,
31 NULL,
32 0,
33 &ulSize);
34
35 PKEY_FULL_INFORMATION pfi =
36 (PKEY_FULL_INFORMATION)
37 ExAllocatePool(PagedPool,ulSize);
38
39 //第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
40 ZwQueryKey(hRegister,
41 KeyFullInformation,
42 pfi,
43 ulSize,
44 &ulSize);
45
46 for (ULONG i=0;i<pfi->SubKeys;i++)
47 {
48 //第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度
49 ZwEnumerateKey(hRegister,
50 i,
51 KeyBasicInformation,
52 NULL,
53 0,
54 &ulSize);
55
56 PKEY_BASIC_INFORMATION pbi =
57 (PKEY_BASIC_INFORMATION)
58 ExAllocatePool(PagedPool,ulSize);
59
60 //第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
61 ZwEnumerateKey(hRegister,
62 i,
63 KeyBasicInformation,
64 pbi,
65 ulSize,
66 &ulSize);
67
68 UNICODE_STRING uniKeyName;
69 uniKeyName.Length =
70 uniKeyName.MaximumLength =
71 (USHORT)pbi->NameLength;
72
73 uniKeyName.Buffer = pbi->Name;
74
75 KdPrint(("The %d sub item name:%wZ\n",i,&uniKeyName));
76
77 ExFreePool(pbi);
78 }
79
80 ExFreePool(pfi);
81 ZwClose(hRegister);
82 }
83
6、枚举子键

通过ZwQueryKeyZwEnumerateValueKey来枚举子键。

7、删除子项

ZwDeleteKey 

只能删除没有子项的项目。

8、其它

DDK中定义了一些运行时函数来简化上面的操作。

RtlCreateRegistryKey  创建注册表

RtlCheckRegistryKey  checks for the existence of a given named key in the registry

RtlWriteRegistryValue  写注册表

RtlDeleteRegistryValue  删除注册表

示例代码

代码
1 void RtlRegTest()
2 {
3 //创建子项目
4 NTSTATUS ntStatus =
5 RtlCreateRegistryKey(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan");
6 if (NT_SUCCESS(ntStatus))
7 {
8 KdPrint(("Create the item successfully\n"));
9 }
10
11 //检查某项是否存在
12 ntStatus =
13 RtlCheckRegistryKey(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan");
14 if (NT_SUCCESS(ntStatus))
15 {
16 KdPrint(("The item is exist\n"));
17 }
18
19 //写入REG_DWORD的数据
20 ULONG value1 = 100;
21 ntStatus =
22 RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
23 L"HelloDDK\\Zhangfan",
24 L"DWORD_Value",
25 REG_DWORD,
26 &value1,
27 sizeof(value1));
28 if (NT_SUCCESS(ntStatus))
29 {
30 KdPrint(("Write the DWORD value succuessfully\n"));
31 }
32
33 PWCHAR szString = L"Hello DDK";
34 ntStatus =
35 RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
36 L"HelloDDK\\Zhangfan",
37 L"SZ_Value",
38 REG_SZ,
39 szString,
40 wcslen(szString)*2+2);
41
42 if (NT_SUCCESS(ntStatus))
43 {
44 KdPrint(("Write the REG_SZ value succuessfully\n"));
45 }
46
47 RTL_QUERY_REGISTRY_TABLE paramTable[2];
48 RtlZeroMemory(paramTable, sizeof(paramTable));
49
50 ULONG defaultData=0;
51 ULONG uQueryValue;
52 paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
53 paramTable[0].Name = L"DWORD_Value";
54 paramTable[0].EntryContext = &uQueryValue;
55 paramTable[0].DefaultType = REG_DWORD;
56 paramTable[0].DefaultData = &defaultData;
57 paramTable[0].DefaultLength = sizeof(ULONG);
58
59 //查询REG_DWORD的数据
60 ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
61 L"HelloDDK\\Zhangfan",
62 paramTable,
63 NULL,
64 NULL);
65 if (NT_SUCCESS(ntStatus))
66 {
67 KdPrint(("Query the item successfully\n"));
68 KdPrint(("The item is :%d\n",uQueryValue));
69 }
70
71 //删除子键
72 ntStatus = RtlDeleteRegistryValue(RTL_REGISTRY_SERVICES,
73 L"HelloDDK\\Zhangfan",
74 L"DWORD_Value");
75 if (NT_SUCCESS(ntStatus))
76 {
77 KdPrint(("delete the value successfully\n"));
78 }
79 }
参考:

1Windows驱动开发详解

2MSDN

原文地址:https://www.cnblogs.com/mydomain/p/1864013.html