PFILE_OBJECT HidFileObject = NULL;
PDEVICE_OBJECT HidDevice;
NTSTATUS status = IoGetDeviceObjectPointer(HidSymLinkName, FILE_ALL_ACCESS, &HidFileObject, &HidDevice);
if (!NT_SUCCESS(status)) {
DebugPrintMsg('IoGetDeviceObjectPointer failed');
return;
}
// Close file object
ObDereferenceObject(HidFileObject);
// Inspect HID capabilities here
PHIDP_PREPARSED_DATA HidPreparsedData = NULL;
USHORT HidInputReportLen, HidOutputReportLen;
if (!GetCapabilities(HidDevice, HidPreparsedData, HidInputReportLen, HidOutputReportLen)) {
DebugPrintMsg('GetCapabilities failed');
FreeIfAllocated(HidPreparsedData);
return;
}
// Reference device object
status = ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, Kernel Mode);
if (!NT_SUCCESS(status)) {
DebugPrintMsg('ObReferenceObjectByPointer failed');
FreeIfAllocated(HidPreparsedData);
return;
}
// Allocate a buffer for the device ext HidSymLinkName
PWSTR HidSymLinkNameBuffer = (PWSTR)ExAllocatePool(NonPagedPool, HidSymLinkName->MaximumLength);
if (HidSymLinkNameBuffer==NULL) {
FreelfAllocated(HidPreparsedData);
ObDereferenceObject(HidDevice);
return;
}
#define NT_DEVICE_NAME L'\Device\HidKbd'
#define SYM_LINK_NAME L'\DosDevices\HidKbd'
// Initialise NT and Symbolic link names
UNICODE_STRING deviceName, linkName;
RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME);
RtlInitUnicodeString(&linkName, SYM_LINK_NAME);
// Create our device object
status = IoCreateDevice(DriverObject, sizeof(HIDKBD_DEVICE_EXTENSION), &deviceName, FILE_DEVICE_KEYBOARD, 0, FALSE, &HidKbdDo);
if (!NT_SUCCESS(status)) {
HidKbdDo = NULL;
FreeIfAllocated(HidSymLinkNameBuffer);
FreeIfAllocated(HidPreparsedData);
ObDereferenceObject(HidDevice);
return;
}
// Set up our device extension
PHIDKBD_DEVICE_EXTENSION dx = (PHIDKBD_DEVICE_EXTENSION)HidKbdDo->DeviceExtension;
dx->HidKbdDo = HidKbdDo;
dx->HidDevice = HidDevice;
dx->HidPreparsedData = HidPreparsedData;
dx->HidSymLinkName.Length = 0;
dx->HidSymLinkName.MaximumLength = HidSymLinkName->MaximumLength;
dx->HidSymLinkName.Buffer = HidSymLinkNameBuffer;
RtlCopyUnicodeString(&dx->HidSymLinkName, HidSymLinkName);
// Create a symbolic link so our device is visible to Win32…
DebugPrint('Creating symbolic link XT', &linkName);
status = IoCreateSymbolicLink(&linkName, &deviceName);
if (!NT_SUCCESS(status)) {
DebugPrintMsg('Could not create symbolic link');
FreeIfAllocated(dx->HidSymLinkName.Buffer);
IoDeleteDevice(HidKbdDo);
ObDereferenceObject(HidDevice);
HidKbdDo = NULL;
return;
}
HidKbdDo->Flags |= DO_BUFFERED_IO;
HidKbdDo->Flags &= ~DO_DEVICE_INITIALIZING;
HidKbdDo->StackSize = HidDevice->StackSize+1;
DebugPrintMsg('Device created OK');
}
Deleting the HidKbd Device
The HidKbd device must be deleted in two circumstances. First, if HidKbd is notified that the HID device has been removed. Second, if the HidKbd driver is unloaded. The
Before the device is deleted,
Listing 23.9 HidKbd DeleteDevice routine
void DeleteDevice(IN PUNICODE_STRING HidSymLinkName) {
if (HidKbdDo==NULL) return;
PHIDKBD_DEVICE_EXTENSION dx = (PHIDKBD_DEVICE_EXTENSION)HidKbdDo->DeviceExtension;
if (HidSymLinkName!=NULL && RtlCompareUnicodeString(HidSymLinkName, &dx->HidSymLinkName, FALSE)!=0) {
DebugPrintMsg('DeleteDevice: symbolic link does not match our device');
return;
}
DebugPrintMsg('Deleting our device');