It’s a lowerfilter for hidusb.sys. It succeeds a number of times
and then the system crashes. There is no pageable code. It’s
because of the completion routine but why? In many ways it seems
like a stack problem the way it works and then the system crashes.
Someone please give me a clue. This is the complete source of
the test driver.
//*****************
#include <ntddk.h>
#include <gameport.h>
#include <usbdi.h>
#include <usbdlib.h>
#include <usbioctl.h>
#include “hidport.h”
// You can find hidport.h in the ddk examples
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT Self;
PDEVICE_OBJECT PDO;
PDEVICE_OBJECT NextDevice ;
DEVICE_POWER_STATE DeviceState;
BOOLEAN Started;
BOOLEAN SurpriseRemoved;
BOOLEAN Removed;
} DEVICE_EXTENSION, PDEVICE_EXTENSION;
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING) ;
NTSTATUS Major_DefaultHandler(PDEVICE_OBJECT, PIRP) ;
NTSTATUS Major_AddDevice(PDRIVER_OBJECT, PDEVICE_OBJECT);
NTSTATUS Major_CreateClose(PDEVICE_OBJECT, PIRP);
NTSTATUS Major_DispatchPassThrough(PDEVICE_OBJECT, PIRP);
NTSTATUS Major_InternalIoctl(PDEVICE_OBJECT, PIRP);
NTSTATUS Major_IoCtl(PDEVICE_OBJECT, PIRP);
NTSTATUS Major_PnP(PDEVICE_OBJECT, PIRP);
NTSTATUS Major_Power(PDEVICE_OBJECT, PIRP);
VOID Major_Unload(PDRIVER_OBJECT) ;
NTSTATUS Complete(PDEVICE_OBJECT, PIRP, PVOID) ;
NTSTATUS InterruptTransferComplete(PDEVICE_OBJECT, PIRP, PVOID) ;
// There is no paged code or data aside from possibly DriverEntry
// It seems to work for a couple dozen transfers and then blamo
// Why???
#pragma alloc_text (INIT, DriverEntry)
//#pragma alloc_text (PAGE, Major_AddDevice)
//#pragma alloc_text (PAGE, Major_CreateClose)
//#pragma alloc_text (PAGE, Major_Unload)
//#pragma alloc_text (PAGE, Major_PnP)
//#pragma alloc_text (PAGE, Major_Power)
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
ULONG i ;
UNREFERENCED_PARAMETER (RegistryPath) ;
for (i = 0 ; i < IRP_MJ_MAXIMUM_FUNCTION ; i++)
DriverObject->MajorFunction[i] = Major_DefaultHandler ;
DriverObject->MajorFunction[IRP_MJ_CREATE] = Major_CreateClose ;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Major_CreateClose ;
DriverObject->MajorFunction[IRP_MJ_PNP] = Major_PnP ;
DriverObject->MajorFunction[IRP_MJ_POWER] = Major_Power ;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Major_InternalIoctl ;
DriverObject->DriverExtension->AddDevice = Major_AddDevice ;
DriverObject->DriverUnload = Major_Unload ;
DbgPrint(“JoyJoyFilter-> Filter Loaded\n”) ;
DbgPrint(“JoyFilter Version 4\n”) ;
return STATUS_SUCCESS ;
} ;
NTSTATUS Major_DefaultHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp) ;
PDEVICE_EXTENSION devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension ;
NTSTATUS status ;
DbgPrint(“JoyFilter-> Major_DefaultHandler\n”) ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
return status ;
} ;
NTSTATUS Major_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO)
{
PDEVICE_EXTENSION devExt ;
IO_ERROR_LOG_PACKET errorLogEntry ;
PDEVICE_OBJECT device ;
NTSTATUS status = STATUS_SUCCESS ;
DbgPrint(“JoyFilter-> Major_AddDevice\n”) ;
status = IoCreateDevice(Driver, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &device) ;
if (!NT_SUCCESS(status))
{
DbgPrint(“Major_AddDevice Returns Error: %08X\n”, status) ;
return (status) ;
} ;
RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION)) ;
devExt = (PDEVICE_EXTENSION)device->DeviceExtension ;
devExt->NextDevice = IoAttachDeviceToDeviceStack(device, PDO) ;
if (!(devExt->NextDevice))
{
DbgPrint(“IoAttachDeviceToDeviceStack Returns Error: %08X (Failed to attach)\n”, status) ;
IoDeleteDevice(device);
return STATUS_UNSUCCESSFUL;
} ;
devExt->Self = device ;
devExt->PDO = PDO ;
devExt->DeviceState = PowerDeviceD0 ;
devExt->SurpriseRemoved = FALSE ;
devExt->Removed = FALSE ;
devExt->Started = FALSE ;
device->Flags |= (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH) ;
device->Flags &= ~DO_DEVICE_INITIALIZING ;
DbgPrint(“Major_AddDevice Returns (Success!!!)\n”) ;
return status ;
} ;
VOID Major_Unload(PDRIVER_OBJECT Driver)
{
// PAGED_CODE() ;
DbgPrint(“JoyFilter-> Major_Unload\n”) ;
UNREFERENCED_PARAMETER(Driver) ;
} ;
NTSTATUS Major_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpStack ;
NTSTATUS status ;
PDEVICE_EXTENSION devExt ;
// PAGED_CODE() ;
irpStack = IoGetCurrentIrpStackLocation(Irp) ;
devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension ;
status = Irp->IoStatus.Status ;
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DbgPrint(“JoyFilter-> Major_CreateClose IRP_MJ_CREATE\n”) ;
break ;
case IRP_MJ_CLOSE:
DbgPrint(“JoyFilter-> Major_CreateClose IRP_MJ_CLOSE\n”) ;
break ;
} ;
Irp->IoStatus.Status = status ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
return status ;
} ;
NTSTATUS Major_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_EXTENSION devExt ;
PIO_STACK_LOCATION irpStack ;
NTSTATUS status = STATUS_SUCCESS ;
KIRQL oldIrql ;
KEVENT event ;
// PAGED_CODE() ;
DbgPrint(“JoyFilter-> Major_PnP\n”) ;
devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension ;
irpStack = IoGetCurrentIrpStackLocation(Irp) ;
switch (irpStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
{
DbgPrint(“JoyFilter-> PNP IRP_MN_START_DEVICE”) ;
IoCopyCurrentIrpStackLocationToNext(Irp) ;
KeInitializeEvent(&event, NotificationEvent, FALSE) ;
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)Complete, &event, TRUE, TRUE, TRUE) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
if (STATUS_PENDING == status) KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL) ;
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status))
{
devExt->Started = TRUE ;
devExt->Removed = FALSE ;
devExt->SurpriseRemoved = FALSE ;
} ;
Irp->IoStatus.Status = status ;
Irp->IoStatus.Information = 0 ;
IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
break ;
} ;
case IRP_MN_REMOVE_DEVICE:
DbgPrint(“JoyFilter-> PNP IRP_MN_REMOVE_DEVICE”) ;
devExt->Removed = TRUE ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
IoDetachDevice(devExt->NextDevice) ;
IoDeleteDevice(DeviceObject) ;
break ;
case IRP_MN_SURPRISE_REMOVAL:
DbgPrint(“JoyFilter-> PNP IRP_MN_SURPRISE_REMOVAL”) ;
devExt->SurpriseRemoved = TRUE ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
break ;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_RELATIONS:
case IRP_MN_QUERY_INTERFACE:
case IRP_MN_QUERY_CAPABILITIES:
case IRP_MN_QUERY_DEVICE_TEXT:
case IRP_MN_QUERY_RESOURCES:
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
case IRP_MN_READ_CONFIG:
case IRP_MN_WRITE_CONFIG:
case IRP_MN_EJECT:
case IRP_MN_SET_LOCK:
case IRP_MN_QUERY_ID:
case IRP_MN_QUERY_PNP_DEVICE_STATE:
default:
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
break ;
} ;
return status ;
} ;
NTSTATUS Major_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpStack ;
PDEVICE_EXTENSION devExt ;
POWER_STATE powerState ;
POWER_STATE_TYPE powerType ;
// PAGED_CODE() ;
DbgPrint(“JoyFilter-> Major_Power\n”) ;
devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension ;
irpStack = IoGetCurrentIrpStackLocation(Irp) ;
PoStartNextPowerIrp(Irp) ;
IoSkipCurrentIrpStackLocation(Irp) ;
return PoCallDriver(devExt->NextDevice, Irp) ;
} ;
NTSTATUS ProcessUrb(PDEVICE_EXTENSION devExt, PIRP Irp)
{
PURB urb ;
PIO_STACK_LOCATION IrpStack ;
NTSTATUS status = STATUS_SUCCESS ;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
urb = IrpStack->Parameters.Others.Argument1 ;
switch(urb->UrbHeader.Function)
{
case URB_FUNCTION_SELECT_CONFIGURATION:
DbgPrint(“URB Function: URB_FUNCTION_SELECT_CONFIGURATION\n”) ;
break ;
case URB_FUNCTION_SELECT_INTERFACE:
DbgPrint(“URB Function: URB_FUNCTION_SELECT_INTERFACE\n”) ;
break ;
case URB_FUNCTION_ABORT_PIPE:
DbgPrint(“URB Function: URB_FUNCTION_ABORT_PIPE\n”) ;
break ;
/ If you don’t use a completion routine it works
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
DbgPrint(“URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n”) ;
IoCopyCurrentIrpStackLocationToNext(Irp) ;
IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
return status ;
} ;
*/
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
{
KIRQL Irql ;
KEVENT event ;
DbgPrint(“URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n”) ;
Irql = KeGetCurrentIrql() ;
if (Irql == PASSIVE_LEVEL)
DbgPrint(“IRQL: PASSIVE_LEVEL (%u)\n”, Irql) ;
else if (Irql == APC_LEVEL)
DbgPrint(“IRQL: APC_LEVEL (%u)\n”, Irql) ;
else if (Irql == DISPATCH_LEVEL)
DbgPrint(“IRQL: DISPATCH_LEVEL (%u)\n”, Irql) ;
else DbgPrint(“IRQL: %u\n”, Irql) ;
KeInitializeEvent(&event, NotificationEvent, FALSE) ;
IoCopyCurrentIrpStackLocationToNext(Irp) ;
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)InterruptTransferComplete, &event, TRUE, TRUE, TRUE) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL) ;
DbgPrint(“Continue and Complete\n”) ;
IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
return status ;
} ;
case URB_FUNCTION_RESET_PIPE:
DbgPrint(“URB Function: URB_FUNCTION_RESET_PIPE\n”) ;
break ;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
DbgPrint(“URB Function: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n”) ;
break ;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
DbgPrint(“URB Function: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\n”) ;
break ;
case URB_FUNCTION_CLASS_INTERFACE:
DbgPrint(“URB Function: URB_FUNCTION_CLASS_INTERFACE\n”) ;
break ;
default:
DbgPrint(“URB Function: %X”, urb->UrbHeader.Function) ;
break ;
} ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
return status ;
} ;
NTSTATUS Major_InternalIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS status ;
PDEVICE_EXTENSION devExt ;
PIO_STACK_LOCATION irpStack ;
irpStack = IoGetCurrentIrpStackLocation(Irp) ;
devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension ;
switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_GET_PHYSICAL_DESCRIPTOR:
DbgPrint(“JoyFilter-> IOCTL_GET_PHYSICAL_DESCRIPTOR\n”) ;
break ;
case IOCTL_HID_ACTIVATE_DEVICE:
DbgPrint(“JoyFilter-> IOCTL_HID_ACTIVATE_DEVICE\n”) ;
break ;
case IOCTL_HID_DEACTIVATE_DEVICE:
DbgPrint(“JoyFilter-> IOCTL_HID_DEACTIVATE_DEVICE\n”) ;
break ;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_DEVICE_ATTRIBUTES\n”) ;
break ;
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_DEVICE_DESCRIPTOR\n”) ;
break ;
case IOCTL_HID_GET_FEATURE:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_FEATURE\n”) ;
break ;
case IOCTL_HID_GET_INDEXED_STRING:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_INDEXED_STRING\n”) ;
break ;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_REPORT_DESCRIPTOR\n”) ;
break ;
case IOCTL_HID_GET_STRING:
DbgPrint(“JoyFilter-> IOCTL_HID_GET_STRING\n”) ;
break ;
case IOCTL_HID_READ_REPORT:
DbgPrint(“JoyFilter-> IOCTL_HID_READ_REPORT\n”) ;
break ;
case IOCTL_HID_SET_FEATURE:
DbgPrint(“JoyFilter-> IOCTL_HID_SET_FEATURE\n”) ;
break ;
case IOCTL_HID_WRITE_REPORT:
DbgPrint(“JoyFilter-> IOCTL_HID_WRITE_REPORT\n”) ;
break ;
case IOCTL_GAMEENUM_PORT_PARAMETERS:
DbgPrint(“JoyFilter-> IOCTL_GAMEENUM_PORT_PARAMETERS\n”) ;
break ;
case IOCTL_INTERNAL_USB_SUBMIT_URB:
status = ProcessUrb(devExt, Irp) ;
return status ;
default:
DbgPrint(“JoyFilter-> IOCTL? %08Xh\n”, irpStack->Parameters.DeviceIoControl.IoControlCode) ;
break ;
} ;
IoSkipCurrentIrpStackLocation(Irp) ;
status = IoCallDriver(devExt->NextDevice, Irp) ;
return status ;
} ;
// Simulate Blocking
NTSTATUS Complete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
PKEVENT event ;
if (Irp->PendingReturned)
{
DbgPrint(“Pending Returned”) ;
IoMarkIrpPending(Irp) ;
} ;
event = (PKEVENT) Context ;
KeSetEvent(event, 0, FALSE) ;
DbgPrint(“JoyFilter-> Complete\n”) ;
return STATUS_MORE_PROCESSING_REQUIRED ;
} ;
NTSTATUS InterruptTransferComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Data)
{
PKEVENT event ;
DbgPrint(“InterruptTrandferComplete\n”) ;
// Shouldn’t matter because we are signaling an event to continue in
// the dispatch function.
//
// if (Irp->PendingReturned)
// {
// DbgPrint(“IoMarkIrpPending\n”) ;
// IoMarkIrpPending(Irp) ;
// } ;
event = (PKEVENT)Data ;
KeSetEvent(event, 0, FALSE) ;
if (NT_SUCCESS(Irp->IoStatus.Status))
DbgPrint(“Transfer Success\n”) ;
else DbgPrint(“Transfer Error\n”) ;
return STATUS_MORE_PROCESSING_REQUIRED ;
} ;</usbioctl.h></usbdlib.h></usbdi.h></gameport.h></ntddk.h>