【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)

简介: 【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)

1、创建注册表项和子项

VOID RegCreateText()
{
  HANDLE hKey;
  HANDLE hSubkey;
  NTSTATUS status;
  OBJECT_ATTRIBUTES oa;
  ULONG ulRet;
  UNICODE_STRING RegPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\MyKey");
  UNICODE_STRING SubPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\MyKey\\SubKey");
  InitializeObjectAttributes(&oa, &RegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
  status = ZwCreateKey(&hKey, KEY_ALL_ACCESS, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &ulRet);
  if (NT_SUCCESS(status))
  {
    if (ulRet == REG_CREATED_NEW_KEY)
    {
      KdPrint(("项不存在创建成功\n"));
    }
    else
    {
      KdPrint(("项存在,打开它\n"));
    }
  }
  else
  {
    KdPrint(("创建注册表项失败\n"));
  }

  InitializeObjectAttributes(&oa, &SubPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
  status = ZwCreateKey(&hSubkey, KEY_ALL_ACCESS, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &ulRet);
  if (NT_SUCCESS(status))
  {
    if (ulRet == REG_CREATED_NEW_KEY)
    {
      KdPrint(("子项不存在创建成功\n"));
    }
    else if(ulRet == REG_OPENED_EXISTING_KEY)
    {
      KdPrint(("子项存在,打开它\n"));
    }
  }
  else
  {
    KdPrint(("创建注册表子项是失败\n"));
  }
  ZwClose(hKey);
  ZwClose(hSubkey);
}


2、打开注册表、修改注册表并读取注册表的信息

VOID RegTest()
{
  HANDLE hKey;
  NTSTATUS status;
  OBJECT_ATTRIBUTES oa;
  UNICODE_STRING RegPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\MyKey");
  UNICODE_STRING ValueName;
  DWORD Value = -1;
  CHAR buffer[] = "hello world" ;
  PKEY_VALUE_PARTIAL_INFORMATION pvpi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, 1024);
  ULONG Length;
  InitializeObjectAttributes(&oa, &RegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
  status = ZwOpenKey(&hKey, KEY_ALL_ACCESS, &oa);
  if (NT_SUCCESS(status))
  {
    KdPrint(("打开成功\n"));
  }
  else
  {
    KdPrint(("打开失败\n"));
  }
  //修改注册表
  RtlInitUnicodeString(&ValueName, L"字符串");
  ZwSetValueKey(hKey, &ValueName, 0, REG_SZ, L"你好", wcslen(L"你好") * sizeof(WCHAR));
  
  RtlInitUnicodeString(&ValueName, L"整数");
  ZwSetValueKey(hKey, &ValueName, 0, REG_DWORD, &Value, sizeof(DWORD));

  RtlInitUnicodeString(&ValueName, L"二进制");
  ZwSetValueKey(hKey, &ValueName, 0, REG_BINARY, buffer, strlen(buffer));

  //读取字符串
  RtlZeroMemory(pvpi, 1024);
  RtlInitUnicodeString(&ValueName, L"字符串");
  ZwQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, pvpi, 1024, &Length);
  if (pvpi->Type == REG_SZ)
  {
    KdPrint(("%ls\n", pvpi->Data));
  }

  //读取整数
  RtlZeroMemory(pvpi, 1024);
  RtlInitUnicodeString(&ValueName, L"整数");
  ZwQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, pvpi, 1024, &Length);
  if (pvpi->Type == REG_DWORD)
  {
    KdPrint(("%d\n", *(PULONG)pvpi->Data));
  }

  //读取二进制
  RtlZeroMemory(pvpi, 1024);
  RtlInitUnicodeString(&ValueName, L"二进制");
  ZwQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, pvpi, 1024, &Length);
  if (pvpi->Type == REG_BINARY)
  {
    KdPrint(("%s\n", pvpi->Data));
  }
}


3、枚举注册表子项

VOID RegEnumTest()
{
  HANDLE hkey;
  NTSTATUS status;
  ULONG Length;
  ULONG Index;

  OBJECT_ATTRIBUTES oa; //对象属性
  //HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  UNICODE_STRING RegPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
  InitializeObjectAttributes(&oa, &RegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);  //初始化对象属性信息
  
  PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, 1024);   //分配内存
  PKEY_BASIC_INFORMATION pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, 1024); //分配内存
  PKEY_VALUE_FULL_INFORMATION pvpi = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool(PagedPool, 1024);

  status = ZwOpenKey(&hkey, KEY_ALL_ACCESS, &oa);   //打开注册表
  if (!NT_SUCCESS(status))
  {
    KdPrint(("打开注册表失败\n"));
    return;
  }
  status = ZwQueryKey(hkey, KeyFullInformation, pfi, 1024, &Length);  //查询注册表
  if (NT_SUCCESS(status))
  {
    KdPrint(("***********************************\n"));
    for (Index = 0; Index < pfi->SubKeys; Index++)  //遍历所有子项
    {
      RtlZeroMemory(pbi, 1024);
      ZwEnumerateKey(hkey, Index, KeyBasicInformation, pbi, 1024, &Length); //枚举出注册表子项的基本信息
      if (NT_SUCCESS(status))
      {
        KdPrint(("%ls\n", pbi->Name));  //输出子项的名称
      }
    }
    KdPrint(("***********************************\n"));
    for (Index = 0; Index < pfi->Values; Index++) //遍历所有子项的值
    {
      RtlZeroMemory(pvpi, 1024);
      status = ZwEnumerateValueKey(hkey, Index, KeyValueFullInformation, pvpi, 1024, &Length);  //枚举出注册表子项的值
      if (NT_SUCCESS(status))
      {
        switch (pvpi->Type)
        {
        case REG_DWORD:
          KdPrint(("%ls:%d\n", pvpi->Name, *(PULONG)((PCHAR)pvpi + pvpi->DataOffset)));
          break;
        case REG_SZ:
        case REG_MULTI_SZ:
        case REG_EXPAND_SZ:
          KdPrint(("%ls:%ls\n", pvpi->Name, (PCHAR)pvpi + pvpi->DataOffset));
          break;
        default:
          break;
        }
      }
    }
  }
  ZwClose(hkey);
  if (pfi != NULL)
  {
    ExFreePool(pfi);
  }
  if (pbi != NULL)
  {
    ExFreePool(pbi);
  }
  if (pvpi != NULL)
  {
    ExFreePool(pvpi);
  }
}

、代码实现效果图


(1)注册表的创建、打开、修改、读取


(2)注册表子项的枚举


补充:

也可使用微软封装的RTL函数来进行注册表的相关操作。

//微软封装的RTL函数
VOID RtlTest()
{ 
  NTSTATUS status;
  status = RtlCreateRegistryKey(RTL_REGISTRY_SERVICES, L"MyService");
  if (NT_SUCCESS(status))
  {
    KdPrint(("Rtl创建子项成功\n"));
  }
  status = RtlCheckRegistryKey(RTL_REGISTRY_SERVICES, L"MyService");
  if (NT_SUCCESS(status))
  {
    KdPrint(("注册表子项存在\n"));
  }
  status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, L"MyService", L"字符串", REG_SZ, L"你好世界", 8);
  if (NT_SUCCESS(status))
  {
    KdPrint(("写入成功\n"));
  }

  status = RtlDeleteRegistryValue(RTL_REGISTRY_SERVICES, L"MyService", L"字符串");
  if (NT_SUCCESS(status))
  {
    KdPrint(("删除成功\n"));
  }
}
相关文章
|
1月前
|
存储 数据可视化 Python
【python】python tkinter 计算器GUI版本(模仿windows计算器 源码)【独一无二】
【python】python tkinter 计算器GUI版本(模仿windows计算器 源码)【独一无二】
|
27天前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
78 0
|
28天前
|
开发者 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 或官网下载工具包。
36 0
|
2月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
81 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
1月前
|
Windows
Windows 映射网络驱动器及删除-此网格连接不存在
Windows 映射网络驱动器及删除-此网格连接不存在
81 0
|
2月前
|
安全 测试技术 Windows
LabVIEW版本、硬件驱动和Windows版本之间兼容性
LabVIEW版本、硬件驱动和Windows版本之间兼容性
64 2
|
3月前
|
Java Nacos 微服务
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
|
24天前
|
网络安全 虚拟化 Windows
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
|
1月前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
1月前
|
开发框架 .NET API
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
76 0