注册表
+ -

驱动配置信息读取RtlQueryRegistryValues 重启电脑驱动读注册表失败

2023-02-01 80 0

为什么这里要说是“驱动配置信息读取RtlQueryRegistryValues”,那是因为自己踩了坑的。
在写Windows驱动的时候,有时需要根据配置信息上来让驱动实现不同的功能。但这个配置信息放在那里合适呢?
第一当然是在文件中了,但是感觉放在那里都感觉好像不合适,而且容易被删除。另外如果参数信息比较多,自己还得写解析格式代码,感觉开发起来有点2。在驱动中重复造轮子,好像不是什么好的选择。
第二种就是放在注册表了,这种想法感觉很正统。但是放在那里了?又是一个问题。这又由每个人定义而不同,但放在不同的位置有时会有一些莫名的问题。比如如下:
我们知道驱动是随系统开机时加载的,所以这时候有一种情况就是驱动加载的比较早,注册表加载的比较晚。这时会导致我们需要读取信息的注册表目录树尚未建立,而读不到信息。这样让驱动会使用默认的信息来配置,但实际上是有的。这在我们系统开机后安装驱动是没有问题的,但对于重启后,很可能造成配置的参数信息不成功。
本人曾在AddDevice中读取计算机\HKEY_LOCAL_MACHINE\SOFTWARE,是一定读取不到的。在测试模式或者禁用驱动模式下,在IRP_MN_START_DEVICE中读,是可以的。但在签完名后,有的机器还是读不到的。

上面说了这么多,就是要表达一个意思,使用注册表读驱动的参数信息,是要讲究的。这个讲究很可能就出现在RtlQueryRegistryValues上。另外我们在看一些驱动的源代码时,有大量这种获取配置信息,所以这应该就是正确了。

NTSTATUS 
  RtlQueryRegistryValues(
    IN ULONG  RelativeTo,
    IN PCWSTR  Path,
    IN PRTL_QUERY_REGISTRY_TABLE  QueryTable,
    IN PVOID  Context,
    IN PVOID  Environment  OPTIONAL
    );
  • RelativeTo是要读的注册表的路径,可以为
含义
RTL_REGISTRY_ABSOLUTE Path 是绝对注册表路径。
RTL_REGISTRY_CONTROL Registry\Machine\System\CurrentControlSet\Control。
RTL_REGISTRY_DEVICEMAP Registry\Machine\Hardware\DeviceMap。
RTL_REGISTRY_SERVICES Registry\Machine\System\CurrentControlSet\Services。
RTL_REGISTRY_USER Registry\User\CurrentUser
RTL_REGISTRY_WINDOWS_NT Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion。
  • Path:是二级路径
  • QueryTable:是一次可以获取多个参数的数组。
    NTSTATUS
    QueryRoutine (
      IN PWSTR ValueName,
      IN ULONG ValueType,
      IN PVOID ValueData,
      IN ULONG ValueLength,
      IN PVOID Context,
      IN PVOID EntryContext
      );
    
    这个数组的最后一项必须为NULL,表示最后一个。

这里搞一个示例,需要的自行修改:


NTSTATUS RegQueryGenericCompositeUSBDeviceString(IN OUT PWCHAR *GenericCompositeUSBDeviceString)
{
    NTSTATUS ntStatus;
    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
    PWCHAR usbstr = L"pnpflag";
    PWCHAR valuename = L"pnpstring";

    PAGED_CODE();

    //
    // Set up QueryTable to do the following:
    //

    // Upgrade install flag
    QueryTable[0].QueryRoutine = GetConfigValue;
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
    QueryTable[0].Name = valuename;
    QueryTable[0].EntryContext = GenericCompositeUSBDeviceString;
    QueryTable[0].DefaultType = 0;
    QueryTable[0].DefaultData = NULL;
    QueryTable[0].DefaultLength = 0;

    //
    // Stop
    //
    QueryTable[1].QueryRoutine = NULL;
    QueryTable[1].Flags = 0;
    QueryTable[1].Name = NULL;

    ntStatus = RtlQueryRegistryValues(
                RTL_REGISTRY_CONTROL,
                usbstr,
                QueryTable,                    // QueryTable
                NULL,                        // Context
                NULL);                        // Environment

    return ntStatus;
}

NTSTATUS GetConfigValue(
    IN PWSTR ValueName,
    IN ULONG ValueType,
    IN PVOID ValueData,
    IN ULONG ValueLength,
    IN PVOID Context,
    IN PVOID EntryContext
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PWCHAR tmpStr;

    switch (ValueType) {
//    case REG_DWORD:
//        *(PVOID*)EntryContext = *(PVOID*)ValueData;
//        break;
//    case REG_BINARY:
//        RtlCopyMemory(EntryContext, ValueData, ValueLength);
//        break;
    case REG_SZ:
        if (ValueLength) {
            tmpStr = ExAllocatePool(PagedPool, ValueLength);
            if (tmpStr) {
                RtlZeroMemory(tmpStr, ValueLength);
                RtlCopyMemory(tmpStr, ValueData, ValueLength);
                *(PWCHAR *)EntryContext = tmpStr;
            } else {
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        } else {
            ntStatus = STATUS_INVALID_PARAMETER;
        }
        break;
    default:
//        TEST_TRAP();
        ntStatus = STATUS_INVALID_PARAMETER;
    }
    return ntStatus;
}

0 篇笔记 写笔记

Windows驱动注册表写数据
实际上注册表的写入比读取要简单。因为这省略了一个尝试数据的大小的过程。直接将数据写入即可。写入值一般使用函数ZwSetValueKey 。这个函数的原型如下:NTSTATUS ZwSetValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRI......
Windows驱动读注册表数据
一般使用ZwQueryValueKey来读取注册表中键的值。要注意的是注册表中的值可能有多种数据类型。而且长度也是没有定数的。为此,在读取过程中,就可能要面对很多种可能的情况。ZwQueryValueKey这个函数的原型如下:NTSTATUS ZwQueryValueKey( IN HAN......
Windows修改注册表使应用程序开机自动运行
先向大家介绍能让WINDOWS自动启动的2个文件和8个注册键1: 当前用户专用的启动文件夹 将快捷方式放入WINDOWS的用户启动文件夹中.在开始菜单的启动文件夹上,右键选中“打开”菜单如在本机win7 x64下为:C:/Users/Administrator/AppData/Roaming/M......
Windows内核打开注册表
和在应用程序中编程的方式类似,注册表是一个巨大的树形结构。操作一般都是打开某个子键。子键下有若干个值可以获得。每一个值有一个名字。值有不同的类型。一般需要查询才能获得其类型。子键一般用一个路径来表示。和应用程序编程的一点重大不同是这个路径的写法不一样。一般应用编程中需要提供一个根子键的句柄。而驱动......
读写注册表SetRegisterValue和GetRegisterValue
注册表DWORD CUtils::SetRegisterValue(HKEY key, LPCSTR path, LPCSTR name, LPBYTE pData, ULONG nLen, DWORD type){ HKEY hKey = NULL; DWORD err = ......
Windows下注册ASIO
在带有WOW6432 ASIO的Windows 64位系统上,32位和64位主机应用程序都可以使用ASIO。要求ASIO驱动程序的COM部分以32位和64位二进制形式提供32位主机应用程序将查询32位Windows注册表部分(Wow6432)。64位主机应用程序将查询普通Windows注册表。A......
ASIO asiosample.dll注册及注册表信息变化
在Windows下注册ASIO一节中,是需要对COM进入注册的。故我们使用Regsvr32命令注册。如:K:usbzhasioasiosdk_2.3.3_2019-06-14driverasiosampleasiosampleDebug>REGSVR32 asiosample.......
SetupAPI根据硬件ID获取驱动INF文件和驱动日期版本信息
SetupAPI根据硬件ID获取驱动INF文件和驱动日期版本信息。注释掉的代码是获取该硬件的所有可用驱动信息。代码是逐渐完善的,没想到可以直接从注册表信息中获取到。SetupDiOpenDevRegKey打开的注册表路径示例为:计算机HKEY_LOCAL_MACHINESYSTEM......
SetupDiGetDeviceRegistryProperty函数使用示例
通过SetupDiOpenDeviceInterface函数打开设备路径,在通过SetupDiGetDeviceInterfaceDetail函数获取SP_DEVINFO_DATA结构的值,有了这个结构的值就可以调用SetupDiGetDeviceRegistryProperty函数获取设备的一系列......
Windows驱动中读取注册表中的DWORD32值
ULONG GetRegisterMicChannelDWORD32(){ HANDLE hHandle = NULL; OBJECT_ATTRIBUTES oa; NTSTATUS statues; UNICODE_STRING path; UNICOD......
Windows驱动注册表(硬件、服务、类)项详解
Windows驱动有三种注册表键负责配置。它们是硬件(或实例), 类和 服务。硬件(或实例)键包含单个设备的信息。类键涉及所有相同类型设备的共同信息。服务键包含驱动程序信息。注册表路径 硬件(hardware)键[HKEY_LOCAL_MACHINESYSTEMCurr......
INF文件中HKR
在Windows驱动的注册表中,AddReg用于添加注册表项,其中有一些通用的缩写:HKCR代表HKEY_CLASSES_ROOT;HKCU代表HKEY_CURRENT_USER;HKLM代表HKEY_LOCAL_MACHINEHKU代表HKEY_USERS不过,我们有时会经常见到的是HKR,......
SWAP APO inf文件信息
SWAP APO编译后的主体为swapapo.dll这里参考ComponentizedApoSample.inf文件的部分节选说明。inf文件的方体结构和普通的驱动INF文件一致,其结构如下:这里关于APO的注册关键是注册表Apo_AddReg相关的。这里先将各个UUID之间的关系说明一下:[A......
清除音频设备的音效处理模块APO(FxProperties注册表项)
Windows 音效处理大致分为SFX,MFX,EFX, 按照顺序,依次处理。下面是如何移除这些模块的方法:打开设备管理器-音频输入输出设备,找到要修改的设备,右键属性-详情,在属性列表框里选择 设备实例路径,有如下值,记录红色部分SWDMMDEVAPI{0.0.0.00000000}.{0......
Windows音频设备及状态
Windows音频设备都在注册表:计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionMMDevicesAudio下,不过这里存储的是系统中当前存在的和以前存在的音频设备。当然,在设备管理器中,也可以通过显示隐藏设......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!