Hello,
AT the moment i’m faced with a bizarre crash that occurs on NT 4.0
with a SCSIPORT filter driver.
To get a better handle on this problem, i’ve stripped away all but
just enough to recreate this problem from development version of
the SCSIPORT filter driver i’m working on.
This sample is nothing more than a passthru SCSIPORT filter driver,
enough to reproduce the crash, consistently.
Bit of background is in order. The driver loads fine, attaches to
\Device\ScsiPort2 device object okay and i’m able to see that the
dispatch routine gets called as ASPI32.SYS sends down the internal
IRP to SCSIPORT for processing.
Note that this sample omits codes that handle the
SRB_FUNCTION_CLAIM_DEVICE so this sample will not filter SCSI
I/O requests from Windows SCSI disk class driver.
I have an ASPI-based SCSI test application that can send SCSI
requests that i can use to test this sample filter driver.
The problem comes up whenever i try to send SCSI command that
involves data read or write, eg. READ, INQUIRY, WRITE where it
will crash the system. Without the filter driver installed these
commands work just fine. Non-data commands such as TEST UNIT READY,
START STOP UNIT, and alike works okay.
I’m sure there’s something wrong with this simple passthru filter
driver, but i don’t see it.
All this passthru filter driver does is pass down the IRP. This
driver has a common dispatch routine for all IRP_MJ_XXX, and that
dispatch routine does nothing more than call the SCSIPORT driver
passing down the IRP that it received, for instance from ASPI32.SYS.
I have instrumented this sample driver with lots of debug prints
that dumps the IRP, I/O Stack and SRB parameter in the I/O Stack and
even used 3rd party application such as “DeviceFilter v2.2” to
analyze for potential bad values in them, but nothing so far.
All i know is that without this sample filter driver present,
no crash, but soon as filter driver is used to pass down the IRP
from DiskPerfPassThru dispatch to SCSIPORT, i get crash. And
this dispatch absolutely does no processing on IRP it gets. Simple
passthru, that’s all.
If anyone’s interested in more detail, feel free to ask and i
can provide whatever is needed.
So the question is, is there some sort of trick to be used to
pass down IRP_MJ_INTERNAL_DEVICE_CONTROL that has I/O control
code of 0 with SRB_FUNCTION_EXECUTE_SCSI to SCSIPORT?
Using development version of the SCSIPORT filter driver that also
filters SCSI disk class IRPs (that code is not shown in the sample
here, but if anyone’s interested i can share that too), going through
the same passthru mechanism, passing those IRPs down to SCSIPORT
works fine. Only from ASPI32.SYS i get the crash.
This is really bizzare…
I’m currently in conversation with Microsoft DDK support engineer
and we’ve gone few days exchanging phone conversations, notes, windbg
debugging, ideas, etc, with no success in trying to grasp the
nature of this crash. I’ve sent him a crash dump so hopefully
that would shed some insight into this problem.
I’ve included below few dumps from windbg if anyone’s interested.
Thanks much,
-gshin
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
kd> k
ChildEBP RetAddr
fbf24d68 80111b3f passthru!DiskPerfPassThru+0x890
[C:\MSDN\NT4DDK\src\storage\filter\passthru\passthru.c @ 1705]
WARNING: Stack unwind information not available. Following frames may be
wrong.
fbf24db4 f73215ce nt!IofCallDriver+0x37
fbf24de4 80111b3f Aspi32+0x15ce
fbf24e14 8016fe12 nt!IofCallDriver+0x37
fbf24ea0 8016a194 nt!NtWriteFile+0x2584
fbf24ed4 8013e394 nt!NtDeviceIoControlFile+0x28
fbf24f04 00000000 nt!KiReleaseSpinLock+0x9c4
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A fatal system error has occurred.
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
* *
* The Symbol Path can be set by: *
* using the _NT_SYMBOL_PATH environment variable. *
* using the -y <symbol_path> argument when starting the debugger. *
* using .sympath and .sympath+ *
**************************************************************
ERROR: Symbol file could not be found. Defaulted to export symbols
for ntoskrnl.exe -
*
Bugcheck Analysis *
*
Use !analyze -v to get detailed debugging information.
BugCheck A, {18, 2, 0, 801dbe19}
Kernel symbols are WRONG. Please fix symbols to do analysis.
ERROR: Symbol file could not be found. Defaulted to export symbols
for SCSIPORT.SYS -
Probably caused by : Unknown_Image (
SCSIPORT!ScsiPortConvertPhysicalAddressToUlong+3a5 )
Followup: MachineOwner
---------
nt!DbgBreakPointWithStatus+0x4:
8012ff7c cc int 3
kd> !analyze -v
*
Bugcheck Analysis *
*
IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address
at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000018, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: 801dbe19, address which referenced memory
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include “ntddk.h”
#include “stdarg.h”
#include “stdio.h”
#include “ntdddisk.h”
#include “ntddscsi.h”
#include “srb.h”
#include “scsi.h”
#define FILE_DEVICE_PASSTHRU_FILTER 0x0000BEEF
//
// Remap DiskPerfDump to local routine.
//
#define DiskPerfDump(X) DiskPerfDebugPrint X
//
// Device Extension
//
typedef struct _DEVICE_EXTENSION
{
//
// Back pointer to device object
//
PDEVICE_OBJECT DeviceObject;
//
// Target Device Object
//
PDEVICE_OBJECT TargetDeviceObject;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
//
// Function declarations
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
DiskPerfPassThru(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
DiskPerfDebugPrint(
ULONG DebugPrintLevel,
PCCHAR DebugMessage,
…
);
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension = NULL;
CCHAR ntNameBuffer[64];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
ULONG irpnum=0;
//
// Set up the device driver entry points.
//
for (irpnum=0; irpnum < IRP_MJ_MAXIMUM_FUNCTION+1; irpnum++)
{
DriverObject->MajorFunction[irpnum] = DiskPerfPassThru;
}
//
// Create unnamed Device Object and attach it to the Device Object named
// \Device\ScsiPort2 Device Object created by the SCSI port driver.
//
status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_PASSTHRU_FILTER,
0,
FALSE,
&deviceObject);
deviceExtension = deviceObject->DeviceExtension;
//
// Create device name for the physical adapter driver. Note that in
// NTDDSCSI.H there’s a define, DD_SCSI_DEVICE_NAME that has the same
// Device Object name.
//
sprintf(ntNameBuffer, “\Device\ScsiPort2”);
RtlInitAnsiString(&ntNameString, ntNameBuffer);
RtlAnsiStringToUnicodeString(&ntUnicodeString, &ntNameString, TRUE);
status = IoAttachDevice(deviceObject,
&ntUnicodeString,
&deviceExtension->TargetDeviceObject);
RtlFreeUnicodeString(&ntUnicodeString);
return status;
} // DriverEntry
NTSTATUS
DiskPerfPassThru (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status;
//
// Pass on this unrecognized I/O request down to SCSI Port driver, i.e.
// SCSIPORT.
//
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
return status;
} // end DiskPerfPassThru()
ULONG DiskPerfDebug = 3;
#if DBG
VOID
DiskPerfDebugPrint (
IN ULONG DebugPrintLevel,
IN PCCHAR DebugMessage,
…
)
{
va_list ap;
va_start( ap, DebugMessage );
if (DebugPrintLevel <= DiskPerfDebug)
{
char buffer[128];
vsprintf(buffer, DebugMessage, ap);
DbgPrint(buffer);
}
va_end(ap);
} // end DiskPerfDebugPrint
#endif // DBG</symbol_path>