从C中的Windows内核驱动程序读取注册表

时间:2014-05-15 10:43:02

标签: c windows winapi kernel registry

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

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

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

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

我无法弄清楚我做错了什么,而且由于我是内核驱动程序的新手并且调试过程非常繁琐,我不确定是否或者不是我只是错误地引用了注册表值,或者在系统引导的这个阶段注册表是否完全可用。

mydriver.c

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);
}

2 个答案:

答案 0 :(得分:4)

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

另请参阅:Registry Trees and Keys for Devices and Drivers

答案 1 :(得分:0)

您可以像这样使用传递给RegistryPath的{​​{1}}:

DriverEntry

在我的示例中,我正在读取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