DriverObject->MajorFunction[IRP_MJ_CLOSE] = Wdm1Close;
DriverObject->MajorFunction[IRP_MJ_PNP] = Wdm1Pnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = Wdm1Power;
DriverObject->MajorFunction[IRP_MJ_READ] = Wdm1Read;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Wdm1Write;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Wdm1DeviceControl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Wdm1SystemControl;
// …
return status;
}
Wdm1.rc simply defines a version resource block with version and copyright information.
The
Eventually
The first section of
Listing 4.6 ReadReg
void ReadReg(IN PUNICODE_STRING DriverRegistryPath) {
// Make zero terminated copy of driver registry path
USHORT FromLen = DriverRegistryPath->Length;
PUCHAR wstrDriverRegistryPath = (PUCHAR)ExAnocatePool(PagedPool, FromLen+sizeof(WCHAR));
if( wstrDriverRegistryPath==NULL) return;
RtlCopyMemory(wstrDriverRegistryPath, DriverRegistryPath->Buffer, FromLen);
RtlZeroMemory(wstrDriverRegistryPath+FromLen, sizeof(WCHAR));
// Initialise our ULONG and UNICODE_STRING values
ULONG UlongValue = –1;
UNICODE_STRING UnicodeString;
UnicodeString.Buffer = NULL;
UnicodeString.MaximumLength = 0;
UnicodeString.Length = 0;
// Build up our registry query table
RTL_QUERY_REGISTRY_TABLE QueryTable[4];
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Name = L'Parameters';
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
QueryTable[0].EntryContext = NULL;
QueryTable[1].Name = L'UlongValue';
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
OueryTable[1].EntryContext = &UlongValue;
QueryTable[2].Name = L''; // Default value
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[2].EntryContext = &UnicodeString;
// Issue query
NTSTATUS status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, (PWSTR)wstrDriverRegistryPath, QueryTable, NULL, NULL);
// Print results
DebugPrint('ReadReg %x: UlongValue %x UnicodeString %T', status.UlongValue, &UnicodeString);
// Do not forget to free buffers
if (UnicodeString.Buffer!=NULL) ExFreePool(UnicodeString.Buffer);
ExFreePool(wstrDriverRegistryPath);
}
The UNICODE_STRING Structure
This is how the UNICODE_STRING type is defined.
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
The
Just in case you were interested, you do not have to use these kernel routines to access Unicode strings. You can fiddle with a string structure however you like, as long as it is in a valid format when passed to the kernel.
Table 4.6 UNICODE_STRING functions
RtlAnsiStringToUnicodeString | Converts an ANSI string to a Unicode string, optionally allocating a buffer. |
RtlAppendUnicodeStringToString | Append one Unicode string to another, up to the length ofthe destination buffer. |
RtlAppendUnicodeToString | Append a wide string to a Unicode string, up to the length of the destination buffer. |
RtlCompareUnicodeString | Compares two Unicode strings, optionally case-insensitive. |
RtlCopyUnicodeString | Copies one Unicode string to another, up to the length of the destination buffer. |