From: Chris Telting [telting-ml@mindspring.com]
Sent: Thursday, October 26, 2000 6:42 AM
To: NT Developers Interest List
Subject: [ntdev] Can any one tell me what's wrong with this filter code?

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 ;
   } ;


---
You are currently subscribed to ntdev as: GlennEverhart@FirstUSA.com
To unsubscribe send a blank email to leave-ntdev-247T@lists.osr.com