首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用C语言从windows内核驱动程序读取注册表

用C语言从windows内核驱动程序读取注册表
EN

Stack Overflow用户
提问于 2014-05-15 10:43:02
回答 3查看 5.2K关注 0票数 2

我需要从注册表(最好)或文件读取设置。驱动程序是一个内核驱动程序,它设置为启动类型为SYSTEM,因此所有服务和WinAPI都不一定可用。

我试图使用RtlQueryRegistryValues函数从注册表中读取单个字符串值,但是无论我做什么,我似乎都会得到相同的0xC0000034错误代码,这些代码被转换成STATUS_OBJECT_NAME_NOT_FOUND

根据MSDN上可用的文档,当路径参数不匹配有效键或设置了特定标志且不满足该标志的特定条件时,STATUS_OBJECT_NAME_NOT_FOUND将从RtlQueryRegistryValues返回。据我所知,注册表项实际上存在于我的测试机器中,而且我没有使用RTL_QUERY_REGISTRY_REQUIRED标志。

我试图读取的注册表值位于HKEY_LOCAL_MACHINE/SOFTWARE/company/ProjectName下面,我试图同时读取默认值和名为parameter的REG_SZ值。对RtlQueryRegistryValues的调用是在DriverEntry(.)期间执行的加载驱动程序的阶段。

我不知道我做错了什么,而且由于我对内核驱动程序并不熟悉,而且调试过程非常繁琐,所以我不确定我是否只是错误地引用了注册表值,或者在系统启动的这一阶段是否可以使用注册表。

mydriver.c

代码语言:javascript
运行
复制
NTSTATUS DriverEntry(...) {
    NTSTATUS regStatus = 0;
    UNICODE_STRING data;
    RTL_QUERY_REGISTRY_TABLE query[2];
    WCHAR* regPath = L"\\Registry\\Machine\\SOFTWARE\\Company\\ProjectName";

    RtlZeroMemory(query, sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);

    data.Buffer = NULL;
    data.MaximumLength = 0;
    data.Length = 0;

    // query[0].Name = L"Parameter";
    query[0].Name = L""; // L"" refers to the default value
    query[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
    query[0].EntryContext = &data;

    regStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, regPath, query, NULL, NULL);

    DebugPrint("regStatus: %lx\n", regStatus);
    DebugPrint("data: %wZ\n", &data);
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-15 13:58:48

我不是100%确定,但我怀疑软件子树的注册表单元没有加载。你为什么要访问它?驱动程序配置参数的适当位置是它自己的注册表项(\Registry\Machine\System\CurrentControlSet\Services\<DriverName>\),它的路径甚至被传递给您的DriverEntry函数,因此您不需要硬编码它。

另见:设备和驱动程序的注册表树和键

票数 4
EN

Stack Overflow用户

发布于 2020-08-28 20:26:13

您可以使用传入DriverEntryDriverEntry,如下所示:

代码语言:javascript
运行
复制
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    // ...

    NTSTATUS ntStatus = STATUS_SUCCESS;

    UNICODE_STRING valueName = RTL_CONSTANT_STRING(L"<YOUR_VALUE_NAME>");
    HANDLE hRegistryKey;
    PKEY_VALUE_FULL_INFORMATION pKeyInfo = nullptr;

    // Create object attributes for registry key querying
    OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
    InitializeObjectAttributes(&ObjectAttributes, RegistryPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    do {
        ntStatus = ZwOpenKey(&hRegistryKey, KEY_QUERY_VALUE, &ObjectAttributes);
        if (!NT_SUCCESS(ntStatus)) {
            KdPrint((DRIVER_PREFIX "Registry key open failed (0x%08X)\n", ntStatus));
            break;
        }

        ULONG ulKeyInfoSize;
        ULONG ulKeyInfoSizeNeeded = GetKeyInfoSize(hRegistryKey, &valueName);
        if (ulKeyInfoSizeNeeded == 0) {
            KdPrint((DRIVER_PREFIX "Value not found\n"));
            break;
        }
        ulKeyInfoSize = ulKeyInfoSizeNeeded;

        pKeyInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, ulKeyInfoSize, DRIVER_TAG);
        if (pKeyInfo == nullptr) {
            KdPrint((DRIVER_PREFIX "Could not allocate memory for KeyValueInfo\n"));
            break;
        }
        RtlZeroMemory(pKeyInfo, ulKeyInfoSize);

        ntStatus = ZwQueryValueKey(hRegistryKey, &valueName, KeyValueFullInformation, pKeyInfo, ulKeyInfoSize, &ulKeyInfoSizeNeeded);
        if (!NT_SUCCESS(ntStatus) || ulKeyInfoSize != ulKeyInfoSizeNeeded) {
            KdPrint((DRIVER_PREFIX "Registry value querying failed (0x%08X)\n", ntStatus));
            break;
        }
        
        // your data
        ULONG someLong = *(ULONG*)((ULONG_PTR)pKeyInfo + pKeyInfo->DataOffset);
    } while (false);
    
    // cleanup
    if (hRegistryKey) {
        ZwClose(hRegistryKey);
    }

    if (pKeyInfo) {
        ExFreePoolWithTag(pKeyInfo, DRIVER_TAG);
    }

    if (!NT_SUCCESS(ntStatus)) {
        // Here you can set a default data if something failed it the way
    }

    // ...
}

ULONG GetKeyInfoSize(HANDLE hRegistryKey, PUNICODE_STRING pValueName) {
    NTSTATUS ntStatus = STATUS_SUCCESS;

    ULONG ulKeyInfoSizeNeeded;
    ntStatus = ZwQueryValueKey(hRegistryKey, pValueName, KeyValueFullInformation, 0, 0, &ulKeyInfoSizeNeeded);
    if (ntStatus == STATUS_BUFFER_TOO_SMALL || ntStatus == STATUS_BUFFER_OVERFLOW) {
        // Expected don't worry - when ZwQueryValueKey fails with one of the above statuses, it returns the size needed
        return ulKeyInfoSizeNeeded;
    }
    else {
        KdPrint((DRIVER_PREFIX "Could not get key info size (0x%08X)\n", ntStatus));
    }

    return 0;
}

在我的例子中,我正在阅读一个ULONG,但它可能是任何东西,它的想法是,您想要读取的地址位于address pKeyInfo + pKeyInfo->DataOffset

票数 2
EN

Stack Overflow用户

发布于 2022-08-15 12:39:51

看起来问题就在RTL_QUERY_REGISTRY_DIRECT上。

根据文献资料,它还需要设置RTL_QUERY_REGISTRY_TYPECHECK标志。

反过来,RTL_QUERY_REGISTRY_TYPECHECK标志需要设置DefaultTypeDefaultSize (of PKEY_VALUE_FULL_INFORMATION)。至少这是我所发现的,这不是根据文档。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23675956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档