From: yang on
Hi,
I had developed a usb hid device. In user mode, it works well by the hid
api.
But I can't communication with it in kernel, when I iocall it by the device
io control irp, the return value is SUCCESS, but no data return.The source
code use some driver sample, I don't know why? Somebody help me? Or some
sample codes?

Thanks!!!!

yang

--
Help
From: Doron Holan [MS] on
how about posting the source code thatis not working

d

--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.


"yang" <yy_bj(a)hotmail.com> wrote in message
news:A159B2F0-D094-492E-AF6B-519684A697C8(a)microsoft.com...
> Hi,
> I had developed a usb hid device. In user mode, it works well by the hid
> api.
> But I can't communication with it in kernel, when I iocall it by the
> device
> io control irp, the return value is SUCCESS, but no data return.The
> source
> code use some driver sample, I don't know why? Somebody help me? Or some
> sample codes?
>
> Thanks!!!!
>
> yang
>
> --
> Help


From: yang on
Thank you very much.
the part of suorce code is this:
///////////////////////////////////////////////////////////////////////////////////
// CallHidIoctl: Make an IOCTL call to the HID class driver

static NTSTATUS CallHidIoctl( IN PDEVICE_OBJECT HidDevice, IN ULONG
IoControlCode,
OUT PVOID Output, IN ULONG OutputLen)
{
IO_STATUS_BLOCK IoStatus;
KEVENT event;

// Initialise IRP completion event
KeInitializeEvent(&event, NotificationEvent, FALSE);

// Build Internal IOCTL IRP
PIRP Irp = IoBuildDeviceIoControlRequest(
IoControlCode, HidDevice,
NULL, 0, // Input buffer
Output, OutputLen, // Output buffer
TRUE, &event, &IoStatus);
// Call the driver and wait for completion if necessary
NTSTATUS status = IoCallDriver( HidDevice, Irp);
if (status == STATUS_PENDING)
{
DebugPrintMsg("CallHidIoctl: waiting for completion");
status = KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL);
}
else
IoStatus.Status = status;

// return IRP completion status
status = IoStatus.Status;
DebugPrint("CallHidIoctl: status %x", status);
return status;
}

///////////////////////////////////////////////////////////////////////////////////
// GetPreparsedData: Get the HID device preparsed data

static bool GetPreparsedData( IN PDEVICE_OBJECT HidDevice, OUT
PHIDP_PREPARSED_DATA &HidPreparsedData)
{
HID_COLLECTION_INFORMATION HidCi;
NTSTATUS status = CallHidIoctl( HidDevice,
IOCTL_HID_GET_COLLECTION_INFORMATION,
&HidCi, sizeof(HidCi));
if( !NT_SUCCESS(status))
{
DebugPrint("IOCTL_HID_GET_COLLECTION_INFORMATION failed %x", status);
return false;
}

//RETURN VALUE IS ZERO
DebugPrint("HID attributes: VendorID=%4x, ProductID=%4x, VersionNumber=%4x",
HidCi.VendorID, HidCi.ProductID, HidCi.VersionNumber);

ULONG PreparsedDatalen = HidCi.DescriptorSize;
DebugPrint("PreparsedDatalen %d",PreparsedDatalen);
HidPreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool( NonPagedPool,
PreparsedDatalen);
if( HidPreparsedData==NULL)
{
DebugPrintMsg("No memory");
return false;
}

status = CallHidIoctl( HidDevice, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
HidPreparsedData, PreparsedDatalen);
if( !NT_SUCCESS(status))
{
DebugPrint("IOCTL_HID_GET_COLLECTION_DESCRIPTOR failed %x", status);
return false;
}

return true;
}
///////////////////////////////////////////////////////////////////////////////////
// GetCapabilities: Get capabilities to see if a HID keyboard
// Return true if HID keyboard found

static bool GetCapabilities( IN PDEVICE_OBJECT HidDevice,
PHIDP_PREPARSED_DATA &HidPreparsedData,
USHORT& InputReportLen, USHORT& OutputReportLen)
{
ULONG status;
PDEVICE_OBJECT ChdPDO = NULL;

HidPreparsedData = NULL;
InputReportLen = 0;
OutputReportLen = 0;
if( !GetPreparsedData( HidDevice, HidPreparsedData))
{
DebugPrintMsg("GetPreparsedData failed");
return false;
}

return true;
}

void CreateDevice( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING
HidSymLinkName)
{
PFILE_OBJECT HidFileObject = NULL;
PDEVICE_OBJECT HidDevice;
NTSTATUS status = IoGetDeviceObjectPointer( HidSymLinkName, FILE_ALL_ACCESS,
&HidFileObject, &HidDevice);
if( !NT_SUCCESS(status))
{
DebugPrint("IoGetDeviceObjectPointer failed %x", status);
return;
}

// Close file object
ObDereferenceObject(HidFileObject);

ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, KernelMode);

// Inspect HID capabilities here
PHIDP_PREPARSED_DATA HidPreparsedData = NULL;
USHORT HidInputReportLen, HidOutputReportLen;

if( !GetCapabilities( HidDevice, HidPreparsedData, HidInputReportLen,
HidOutputReportLen))
{
DebugPrintMsg("GetCapabilities failed");
ObDereferenceObject(HidDevice);
FreeIfAllocated(HidPreparsedData);
return;
}

FreeIfAllocated(HidPreparsedData);
ObDereferenceObject(HidDevice);

DebugPrintMsg("Device created OK");
}
/////////////////////////////////////////////////////////////////////////////
// HidKbdDicCallback: PnP Notify callback for device interface changes
// Process device arrival and removal messages

NTSTATUS HidKbdDicCallback(
IN PVOID NotificationStructure,
IN PVOID Context)
{
PDEVICE_INTERFACE_CHANGE_NOTIFICATION dicn =
(PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure;
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;

if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_ARRIVAL))
{
DebugPrint("Device arrival: %T", dicn->SymbolicLinkName);
CreateDevice( DriverObject, dicn->SymbolicLinkName);
}
else if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_REMOVAL))
{
DebugPrint("Device removal: %T", dicn->SymbolicLinkName);
//DeleteDevice( dicn->SymbolicLinkName);
}
else
DebugPrint("Some other device event: %T", dicn->SymbolicLinkName);

return STATUS_SUCCESS;
}

#pragma code_seg("INIT") // start INIT section

/////////////////////////////////////////////////////////////////////////////
// RegisterForPnpNotification: Ask for device interface change events

NTSTATUS RegisterForPnpNotification( IN PDRIVER_OBJECT DriverObject)
{
DebugPrintMsg("RegisterForPnpNotification");

NTSTATUS status = IoRegisterPlugPlayNotification(
EventCategoryDeviceInterfaceChange,
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)&GUID_CLASS_INPUT, DriverObject,
HidKbdDicCallback, DriverObject,
&diNotificationEntry);
return status;
}

/////////////////////////////////////////////////////////////////////////////
// DriverEntry:
//
// Description:
// This function initializes the driver, and creates
// any objects needed to process I/O requests.
//
// Arguments:
// Pointer to the Driver object
// Registry path string for driver service key
//
// Return Value:
// This function returns STATUS_XXX

extern "C"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;

DebugPrintInit("vHidSk1 Entry");
DebugPrint("Registry_Path is %T",RegistryPath);

// Export other driver entry points...
DriverObject->DriverExtension->AddDevice = HidRdrAddDevice;
DriverObject->DriverUnload = HidRdrUnload;

DriverObject->MajorFunction[IRP_MJ_CREATE] = HidRdrCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidRdrClose;

DriverObject->MajorFunction[IRP_MJ_CLEANUP] = HidRdrCleanup;

DriverObject->MajorFunction[IRP_MJ_PNP] = HidRdrPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = HidRdrPower;

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidRdrDeviceControl;

DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
HidRdrInternalDeviceControl;

DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidRdrSystemControl;

// Initialise spin lock which protects access to shared memory buffer
ExInitializeFastMutex(&g_StateLock);
RtlZeroBytes(g_ReaderName, 10 * sizeof(ULONG *));

RegisterForPnpNotification(DriverObject);

DebugPrint("DriverEntry completed %x", status);

return status;
}
#pragma code_seg() // end INIT section

//////////////////////////////////////////////////////////////////////////////
// HidRdrUnload
//
// Description:
// Unload the driver by removing any remaining objects, etc.
//
// Arguments:
// Pointer to the Driver object
//
// Return Value:
// None

#pragma code_seg("PAGE") // start PAGE section

//////////////////////////////////////////////////////////////////////////////
// UnregisterForPnpNotification: Stop device interface change events

void UnregisterForPnpNotification()
{
//DeleteDevice(NULL);
DebugPrintMsg("UnregisterForPnpNotification");
if( diNotificationEntry!=NULL)
{
IoUnregisterPlugPlayNotification(diNotificationEntry);
diNotificationEntry = NULL;
}
}

VOID HidRdrUnload(IN PDRIVER_OBJECT DriverObject)
{
DebugPrintMsg("HidRdrUnload");
DebugPrintClose();

UnregisterForPnpNotification();

return;
}

From: Doron Holan [MS] on
you need to keep the fileobject after IoGetDeviceObjectPointer. furthermore
you need to set the next stack location FileObject value to it on every I/O
you send. deref the fileobject when you close down the device.

finally, you need to register for file handle notifications on the
fileobject itself so that you can be notified when the HID device is being
removed and close down the device. see the toastmon example for how to do
this.

d



--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.


"yang" <yy_bj(a)hotmail.com> wrote in message
news:7199414A-F69B-4E52-85E7-1F312B1852C6(a)microsoft.com...
> Thank you very much.
> the part of suorce code is this:
> ///////////////////////////////////////////////////////////////////////////////////
> // CallHidIoctl: Make an IOCTL call to the HID class driver
>
> static NTSTATUS CallHidIoctl( IN PDEVICE_OBJECT HidDevice, IN ULONG
> IoControlCode,
> OUT PVOID Output, IN ULONG OutputLen)
> {
> IO_STATUS_BLOCK IoStatus;
> KEVENT event;
>
> // Initialise IRP completion event
> KeInitializeEvent(&event, NotificationEvent, FALSE);
>
> // Build Internal IOCTL IRP
> PIRP Irp = IoBuildDeviceIoControlRequest(
> IoControlCode, HidDevice,
> NULL, 0, // Input buffer
> Output, OutputLen, // Output buffer
> TRUE, &event, &IoStatus);
> // Call the driver and wait for completion if necessary
> NTSTATUS status = IoCallDriver( HidDevice, Irp);
> if (status == STATUS_PENDING)
> {
> DebugPrintMsg("CallHidIoctl: waiting for completion");
> status = KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE,
> NULL);
> }
> else
> IoStatus.Status = status;
>
> // return IRP completion status
> status = IoStatus.Status;
> DebugPrint("CallHidIoctl: status %x", status);
> return status;
> }
>
> ///////////////////////////////////////////////////////////////////////////////////
> // GetPreparsedData: Get the HID device preparsed data
>
> static bool GetPreparsedData( IN PDEVICE_OBJECT HidDevice, OUT
> PHIDP_PREPARSED_DATA &HidPreparsedData)
> {
> HID_COLLECTION_INFORMATION HidCi;
> NTSTATUS status = CallHidIoctl( HidDevice,
> IOCTL_HID_GET_COLLECTION_INFORMATION,
> &HidCi, sizeof(HidCi));
> if( !NT_SUCCESS(status))
> {
> DebugPrint("IOCTL_HID_GET_COLLECTION_INFORMATION failed %x", status);
> return false;
> }
>
> //RETURN VALUE IS ZERO
> DebugPrint("HID attributes: VendorID=%4x, ProductID=%4x,
> VersionNumber=%4x",
> HidCi.VendorID, HidCi.ProductID, HidCi.VersionNumber);
>
> ULONG PreparsedDatalen = HidCi.DescriptorSize;
> DebugPrint("PreparsedDatalen %d",PreparsedDatalen);
> HidPreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool( NonPagedPool,
> PreparsedDatalen);
> if( HidPreparsedData==NULL)
> {
> DebugPrintMsg("No memory");
> return false;
> }
>
> status = CallHidIoctl( HidDevice, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
> HidPreparsedData, PreparsedDatalen);
> if( !NT_SUCCESS(status))
> {
> DebugPrint("IOCTL_HID_GET_COLLECTION_DESCRIPTOR failed %x", status);
> return false;
> }
>
> return true;
> }
> ///////////////////////////////////////////////////////////////////////////////////
> // GetCapabilities: Get capabilities to see if a HID keyboard
> // Return true if HID keyboard found
>
> static bool GetCapabilities( IN PDEVICE_OBJECT HidDevice,
> PHIDP_PREPARSED_DATA &HidPreparsedData,
> USHORT& InputReportLen, USHORT& OutputReportLen)
> {
> ULONG status;
> PDEVICE_OBJECT ChdPDO = NULL;
>
> HidPreparsedData = NULL;
> InputReportLen = 0;
> OutputReportLen = 0;
> if( !GetPreparsedData( HidDevice, HidPreparsedData))
> {
> DebugPrintMsg("GetPreparsedData failed");
> return false;
> }
>
> return true;
> }
>
> void CreateDevice( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING
> HidSymLinkName)
> {
> PFILE_OBJECT HidFileObject = NULL;
> PDEVICE_OBJECT HidDevice;
> NTSTATUS status = IoGetDeviceObjectPointer( HidSymLinkName,
> FILE_ALL_ACCESS,
> &HidFileObject, &HidDevice);
> if( !NT_SUCCESS(status))
> {
> DebugPrint("IoGetDeviceObjectPointer failed %x", status);
> return;
> }
>
> // Close file object
> ObDereferenceObject(HidFileObject);
>
> ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, KernelMode);
>
> // Inspect HID capabilities here
> PHIDP_PREPARSED_DATA HidPreparsedData = NULL;
> USHORT HidInputReportLen, HidOutputReportLen;
>
> if( !GetCapabilities( HidDevice, HidPreparsedData, HidInputReportLen,
> HidOutputReportLen))
> {
> DebugPrintMsg("GetCapabilities failed");
> ObDereferenceObject(HidDevice);
> FreeIfAllocated(HidPreparsedData);
> return;
> }
>
> FreeIfAllocated(HidPreparsedData);
> ObDereferenceObject(HidDevice);
>
> DebugPrintMsg("Device created OK");
> }
> /////////////////////////////////////////////////////////////////////////////
> // HidKbdDicCallback: PnP Notify callback for device interface changes
> // Process device arrival and removal messages
>
> NTSTATUS HidKbdDicCallback(
> IN PVOID NotificationStructure,
> IN PVOID Context)
> {
> PDEVICE_INTERFACE_CHANGE_NOTIFICATION dicn =
> (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure;
> PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;
>
> if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_ARRIVAL))
> {
> DebugPrint("Device arrival: %T", dicn->SymbolicLinkName);
> CreateDevice( DriverObject, dicn->SymbolicLinkName);
> }
> else if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_REMOVAL))
> {
> DebugPrint("Device removal: %T", dicn->SymbolicLinkName);
> //DeleteDevice( dicn->SymbolicLinkName);
> }
> else
> DebugPrint("Some other device event: %T", dicn->SymbolicLinkName);
>
> return STATUS_SUCCESS;
> }
>
> #pragma code_seg("INIT") // start INIT section
>
> /////////////////////////////////////////////////////////////////////////////
> // RegisterForPnpNotification: Ask for device interface change events
>
> NTSTATUS RegisterForPnpNotification( IN PDRIVER_OBJECT DriverObject)
> {
> DebugPrintMsg("RegisterForPnpNotification");
>
> NTSTATUS status = IoRegisterPlugPlayNotification(
> EventCategoryDeviceInterfaceChange,
> PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
> (PVOID)&GUID_CLASS_INPUT, DriverObject,
> HidKbdDicCallback, DriverObject,
> &diNotificationEntry);
> return status;
> }
>
> /////////////////////////////////////////////////////////////////////////////
> // DriverEntry:
> //
> // Description:
> // This function initializes the driver, and creates
> // any objects needed to process I/O requests.
> //
> // Arguments:
> // Pointer to the Driver object
> // Registry path string for driver service key
> //
> // Return Value:
> // This function returns STATUS_XXX
>
> extern "C"
> NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath)
> {
> NTSTATUS status = STATUS_SUCCESS;
>
> DebugPrintInit("vHidSk1 Entry");
> DebugPrint("Registry_Path is %T",RegistryPath);
>
> // Export other driver entry points...
> DriverObject->DriverExtension->AddDevice = HidRdrAddDevice;
> DriverObject->DriverUnload = HidRdrUnload;
>
> DriverObject->MajorFunction[IRP_MJ_CREATE] = HidRdrCreate;
> DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidRdrClose;
>
> DriverObject->MajorFunction[IRP_MJ_CLEANUP] = HidRdrCleanup;
>
> DriverObject->MajorFunction[IRP_MJ_PNP] = HidRdrPnp;
> DriverObject->MajorFunction[IRP_MJ_POWER] = HidRdrPower;
>
> DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidRdrDeviceControl;
>
> DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
> HidRdrInternalDeviceControl;
>
> DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidRdrSystemControl;
>
> // Initialise spin lock which protects access to shared memory buffer
> ExInitializeFastMutex(&g_StateLock);
> RtlZeroBytes(g_ReaderName, 10 * sizeof(ULONG *));
>
> RegisterForPnpNotification(DriverObject);
>
> DebugPrint("DriverEntry completed %x", status);
>
> return status;
> }
> #pragma code_seg() // end INIT section
>
> //////////////////////////////////////////////////////////////////////////////
> // HidRdrUnload
> //
> // Description:
> // Unload the driver by removing any remaining objects, etc.
> //
> // Arguments:
> // Pointer to the Driver object
> //
> // Return Value:
> // None
>
> #pragma code_seg("PAGE") // start PAGE section
>
> //////////////////////////////////////////////////////////////////////////////
> // UnregisterForPnpNotification: Stop device interface change events
>
> void UnregisterForPnpNotification()
> {
> //DeleteDevice(NULL);
> DebugPrintMsg("UnregisterForPnpNotification");
> if( diNotificationEntry!=NULL)
> {
> IoUnregisterPlugPlayNotification(diNotificationEntry);
> diNotificationEntry = NULL;
> }
> }
>
> VOID HidRdrUnload(IN PDRIVER_OBJECT DriverObject)
> {
> DebugPrintMsg("HidRdrUnload");
> DebugPrintClose();
>
> UnregisterForPnpNotification();
>
> return;
> }
>


From: yang on
Thank you!

I have modified my source code as you said.But no effect.

I revised it as blow:
///////////////////////////////////////////////////////////////////////////////////
// CallHidIoctl: Make an IOCTL call to the HID class driver

static NTSTATUS CallHidIoctl( IN PDEVICE_OBJECT HidDevice, PFILE_OBJECT
HidFileObject, IN ULONG IoControlCode,
OUT PVOID Output, IN ULONG OutputLen)
{
IO_STATUS_BLOCK IoStatus;
KEVENT event;

// Initialise IRP completion event
KeInitializeEvent(&event, NotificationEvent, FALSE);

// Build Internal IOCTL IRP
PIRP Irp = IoBuildDeviceIoControlRequest(
IoControlCode, HidDevice,
NULL, 0, // Input buffer
Output, OutputLen, // Output buffer
TRUE, &event, &IoStatus);

// Store file object pointer
PIO_STACK_LOCATION IrpStack = IoGetNextIrpStackLocation(Irp);
IrpStack->FileObject = HidFileObject;



// Call the driver and wait for completion if necessary
NTSTATUS status = IoCallDriver( HidDevice, Irp);
if (status == STATUS_PENDING)
{
DebugPrintMsg("CallHidIoctl: waiting for completion");
status = KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL);
}
else
IoStatus.Status = status;

// return IRP completion status
status = IoStatus.Status;
DebugPrint("CallHidIoctl: status %x", status);
return status;
}

///////////////////////////////////////////////////////////////////////////////////
// GetPreparsedData: Get the HID device preparsed data

static bool GetPreparsedData( IN PDEVICE_OBJECT HidDevice, PFILE_OBJECT
HidFileObject, OUT PHIDP_PREPARSED_DATA &HidPreparsedData)
{
HID_COLLECTION_INFORMATION HidCi;
NTSTATUS status = CallHidIoctl( HidDevice, HidFileObject,
IOCTL_HID_GET_COLLECTION_INFORMATION,
&HidCi, sizeof(HidCi));
if( !NT_SUCCESS(status))
{
DebugPrint("IOCTL_HID_GET_COLLECTION_INFORMATION failed %x", status);
return false;
}
DebugPrint("HID attributes: VendorID=%4x, ProductID=%4x, VersionNumber=%4x",
HidCi.VendorID, HidCi.ProductID, HidCi.VersionNumber);

ULONG PreparsedDatalen = HidCi.DescriptorSize;
DebugPrint("PreparsedDatalen %d",PreparsedDatalen);
HidPreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool( NonPagedPool,
PreparsedDatalen);
if( HidPreparsedData==NULL)
{
DebugPrintMsg("No memory");
return false;
}

status = CallHidIoctl( HidDevice, HidFileObject,
IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
HidPreparsedData, PreparsedDatalen);
if( !NT_SUCCESS(status))
{
DebugPrint("IOCTL_HID_GET_COLLECTION_DESCRIPTOR failed %x", status);
return false;
}

return true;
}
///////////////////////////////////////////////////////////////////////////////////
// GetCapabilities: Get capabilities to see if a HID keyboard
// Return true if HID keyboard found

static bool GetCapabilities( IN PDEVICE_OBJECT HidDevice, PFILE_OBJECT
HidFileObject, PHIDP_PREPARSED_DATA &HidPreparsedData,
USHORT& InputReportLen, USHORT& OutputReportLen)
{
ULONG status;
PDEVICE_OBJECT ChdPDO = NULL;

/*
// Call the port driver with the request and wait for it to complete.
status = CallUsbPnP(HidDevice, &ChdPDO, IRP_MN_QUERY_DEVICE_RELATIONS);
if ( status != STATUS_SUCCESS )
return(false);

DebugPrint("ChdPDO = %x", ChdPDO);
if (ChdPDO)
ObDereferenceObject( ChdPDO );
*/

HidPreparsedData = NULL;
InputReportLen = 0;
OutputReportLen = 0;
if( !GetPreparsedData( HidDevice, HidFileObject, HidPreparsedData))
{
DebugPrintMsg("GetPreparsedData failed");
return false;
}

return true;
}

void CreateDevice( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING
HidSymLinkName)
{
PFILE_OBJECT HidFileObject = NULL;
PDEVICE_OBJECT HidDevice;
NTSTATUS status = IoGetDeviceObjectPointer( HidSymLinkName, FILE_ALL_ACCESS,
&HidFileObject, &HidDevice);
if( !NT_SUCCESS(status))
{
DebugPrint("IoGetDeviceObjectPointer failed %x", status);
return;
}

// Close file object
//ObDereferenceObject(HidFileObject);

//ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, KernelMode);

// Inspect HID capabilities here
PHIDP_PREPARSED_DATA HidPreparsedData = NULL;
USHORT HidInputReportLen, HidOutputReportLen;
if( !GetCapabilities( HidDevice, HidFileObject, HidPreparsedData,
HidInputReportLen, HidOutputReportLen))
{
DebugPrintMsg("GetCapabilities failed");
// Close file object
ObDereferenceObject(HidFileObject);
FreeIfAllocated(HidPreparsedData);
return;
}

FreeIfAllocated(HidPreparsedData);
ObDereferenceObject(HidFileObject);

DebugPrintMsg("Device created OK");
}
/////////////////////////////////////////////////////////////////////////////
// HidKbdDicCallback: PnP Notify callback for device interface changes
// Process device arrival and removal messages

NTSTATUS HidKbdDicCallback(
IN PVOID NotificationStructure,
IN PVOID Context)
{
PDEVICE_INTERFACE_CHANGE_NOTIFICATION dicn =
(PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure;
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;

if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_ARRIVAL))
{
DebugPrint("Device arrival: %T", dicn->SymbolicLinkName);
CreateDevice( DriverObject, dicn->SymbolicLinkName);
}
else if( IsEqualGUID( dicn->Event, GUID_DEVICE_INTERFACE_REMOVAL))
{
DebugPrint("Device removal: %T", dicn->SymbolicLinkName);
//DeleteDevice( dicn->SymbolicLinkName);
}
else
DebugPrint("Some other device event: %T", dicn->SymbolicLinkName);

return STATUS_SUCCESS;
}

#pragma code_seg("INIT") // start INIT section

/////////////////////////////////////////////////////////////////////////////
// RegisterForPnpNotification: Ask for device interface change events

NTSTATUS RegisterForPnpNotification( IN PDRIVER_OBJECT DriverObject)
{
DebugPrintMsg("RegisterForPnpNotification");

NTSTATUS status = IoRegisterPlugPlayNotification(
EventCategoryDeviceInterfaceChange,
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)&GUID_CLASS_INPUT, DriverObject,
HidKbdDicCallback, DriverObject,
&diNotificationEntry);
return status;
}

/////////////////////////////////////////////////////////////////////////////
// DriverEntry:
//
// Description:
// This function initializes the driver, and creates
// any objects needed to process I/O requests.
//
// Arguments:
// Pointer to the Driver object
// Registry path string for driver service key
//
// Return Value:
// This function returns STATUS_XXX

extern "C"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;

DebugPrintInit("vHidSk1 Entry");
DebugPrint("Registry_Path is %T",RegistryPath);

// Export other driver entry points...
DriverObject->DriverExtension->AddDevice = HidRdrAddDevice;
DriverObject->DriverUnload = HidRdrUnload;

DriverObject->MajorFunction[IRP_MJ_CREATE] = HidRdrCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidRdrClose;

DriverObject->MajorFunction[IRP_MJ_CLEANUP] = HidRdrCleanup;

DriverObject->MajorFunction[IRP_MJ_PNP] = HidRdrPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = HidRdrPower;

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidRdrDeviceControl;

DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
HidRdrInternalDeviceControl;

DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidRdrSystemControl;

// Initialise spin lock which protects access to shared memory buffer
ExInitializeFastMutex(&g_StateLock);
RtlZeroBytes(g_ReaderName, 10 * sizeof(ULONG *));

RegisterForPnpNotification(DriverObject);

DebugPrint("DriverEntry completed %x", status);

return status;
}
#pragma code_seg() // end INIT section

//////////////////////////////////////////////////////////////////////////////
// HidRdrUnload
//
// Description:
// Unload the driver by removing any remaining objects, etc.
//
// Arguments:
// Pointer to the Driver object
//
// Return Value:
// None

#pragma code_seg("PAGE") // start PAGE section

//////////////////////////////////////////////////////////////////////////////
// UnregisterForPnpNotification: Stop device interface change events

void UnregisterForPnpNotification()
{
//DeleteDevice(NULL);
DebugPrintMsg("UnregisterForPnpNotification");
if( diNotificationEntry!=NULL)
{
IoUnregisterPlugPlayNotification(diNotificationEntry);
diNotificationEntry = NULL;
}
}

VOID HidRdrUnload(IN PDRIVER_OBJECT DriverObject)
{
DebugPrintMsg("HidRdrUnload");
DebugPrintClose();

UnregisterForPnpNotification();

return;
}