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

简介:  4、注册表操作 和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey 完成。与ZwCreateFile函数类似,它通过一个OBJECT_ATTRIBUTES 获得需要创建或打开的路径信息,但在内核中这个路径与用户模式下不相同,实际上,因为用户模式下的应用程序总是由某个“当前用户”打开的,因此在用户模式下可以直接访问HKEY_CLASSES_ROOT 和HKEY_CURRENT_USER,但工作在内核模式下的驱动程序不属于任何一个用户,因此不能直接访问这两个根键。

 4、注册表操作

和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey 完成。与ZwCreateFile函数类似,它通过一个OBJECT_ATTRIBUTES 获得需要创建或打开的路径信息,但在内核中这个路径与用户模式下不相同,实际上,因为用户模式下的应用程序总是由某个当前用户打开的,因此在用户模式下可以直接访问HKEY_CLASSES_ROOT HKEY_CURRENT_USER,但工作在内核模式下的驱动程序不属于任何一个用户,因此不能直接访问这两个根键。

如果ZwCreateKey 指定的项不存在,则会直接创建该项,同时由函数的Disposition参数返回REG_CREATED_NEW_KEY;如果指定项已经存在了,则 Disposition返回值REG_OPENED_EXISTING_KEYDDK同样提供了一个ZwOpenKey函数用以简化打开注册表的操作。同时DDK还提供一系列以Rtl 开头的运行时函数,它们可以是对Zw系列函数的封装,可以有效地简化对注册表的操作过程。

wps_clip_image-6573

wps_clip_image-25020

Zw系统注册相关函数

http://msdn.microsoft.com/en-us/library/ff566425%28VS.85%29.aspx

wps_clip_image-10646

Rtl系统注册相关函数

http://msdn.microsoft.com/en-us/library/ff561822%28VS.85%29.aspx

1)读写注册表

注册表是以二元形式存储的,即键名键值,通过键名来设置键值,其中键值分为多种情况。

wps_clip_image-11238

表 注册键类型

通过ZwSetValueKe y 函数添加或修改注册表键值,通过ZwQueryValueKe y

数查询相关键值。

2)枚举

枚举注册表通常分两种情况:枚举一个注册表项的所有子项和枚举一个注册表项的所有子键。

枚举子项使用ZwQueryKey(注意不是ZwQueryValueKey)和ZwEnumerateKe y配合完成,枚举子键使用ZwQueryKeyZwEnumerateValueKey配合完成。

我们以枚举子项来说明思路,首先利用ZwQueryKey获得某项究竟有多少个子项,然后利用ZwEnumerateKe y来获取指定子项的详细信息,这个过程是通过一个子项索引(index)来完成的。在使用ZwQueryKey时,可以将参数KeyInformationClass指定为KeyFullInformation,它对应KEY_FULL_INFORMATION结构中的SubKeys指明了该项中有多少子项。

3)一个例子如下

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.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结构将被返回到这个指针所指内存中。

示例代码:

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
 
    
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(LTest);

PWCHAR value = { LMy Test Value};

// 数据长度要将字符串长度加上1,把最后一个空结束符

status = ZwSetValueKey(my_key,

&name,0,REG_SZ,value,(wcslen(value)+1)*sizeof(WCHAR));

if(!NT_SUCCESS(status))

{

// 错误处理

……

}

目录
相关文章
|
3月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
90 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
3月前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
104 0
|
3月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
239 0
|
4月前
|
存储 安全 程序员
Windows任务管理器开发原理与实现
Windows任务管理器开发原理与实现
|
5月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
95 0
|
5月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
250 0
|
5月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
376 0
|
5月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
471 0
|
5月前
|
iOS开发 Android开发 MacOS
从零到全能开发者:解锁Uno Platform,一键跨越多平台应用开发的神奇之旅,让你的代码飞遍Windows、iOS、Android、macOS及Web,技术小白也能秒变跨平台大神!
【8月更文挑战第31天】从零开始,踏上使用Uno Platform开发跨平台应用的旅程。只需编写一次代码,即可轻松部署到Windows、iOS、macOS、Android及Web(通过WASM)等多个平台。Uno Platform为.NET生态带来前所未有的灵活性和效率,简化跨平台开发。首先确保安装了Visual Studio或VS Code及.NET SDK,然后选择合适的项目模板创建新项目。项目结构类似传统.NET MAUI或WPF项目,包含核心NuGet包。通过简单的按钮示例,你可以快速上手并构建应用。Uno Platform让你的技术探索之旅充满无限可能。
106 0
|
5月前
|
Kubernetes Cloud Native 开发者
探索云原生技术:Kubernetes入门与实践探索Windows操作系统的隐藏功能
【8月更文挑战第31天】在数字化转型的浪潮中,云原生技术成为企业提升敏捷性、效率和可靠性的关键。本文将带你了解云原生的核心组件之一——Kubernetes(K8s),通过浅显易懂的语言和实际代码示例,引导你步入这一强大工具的世界。无论你是初学者还是有经验的开发者,本篇都将为你打开一扇通向高效资源管理与自动化部署的大门。