Reading registry from windows kernel driver in C

c, kernel, registry, winapi, windows

Solution

I'm not 100% sure but I suspect the registry hive for the Software subtree is just not loaded. Why are you trying to access it anyway? The proper place for driver config parameters is its own registry key (`\Registry\Machine\System\CurrentControlSet\Services\<DriverName>\`) and the path to it is even passed to your `DriverEntry` function so you don't need to hardcode it.

See also: Registry Trees and Keys for Devices and Drivers.

Problem

I need to read settings from the registry (preferably) or from a file. The driver is a kernel driver that is set to start with type of start set to `SYSTEM`, so all services and WinAPIs are not necessarily available. I'm attempting to use the `RtlQueryRegistryValues` function in order to read a single String value from the registry, but whatever I do I seem to get the same `0xC0000034` error code back which translate to `STATUS_OBJECT_NAME_NOT_FOUND`. According to the documentation available at MSDN `STATUS_OBJECT_NAME_NOT_FOUND` is returned from `RtlQueryRegistryValues` when the path parameter does not match a valid key, or a specific flag is set and conditions specific to that flag is not met. As far as I can tell the registry keys are actually present in my test machine and I'm not using the `RTL_QUERY_REGISTRY_REQUIRED` flag. The registry values I'm attempting to read is located under `HKEY_LOCAL_MACHINE/SOFTWARE/company/ProjectName`, I'm attempting to read both the default value and a REG_SZ value named `parameter`. The call to `RtlQueryRegistryValues` is performed during the DriverEntry(...) stage of loading the driver. I can't figure out what it is that I'm doing wrong, and since I'm new to kernel drivers and the debugging process is quite tedious I'm not sure whether or not I just refer to the registry values incorrectly or if the registry is available at all during this stage of the system boot. 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); } ```

Original source