Why are you setting the next stack location and then copying it to the next? So that you have a valid stack location in your completion routine? This is a sync operation so I would think the c.r. just sets the event (via context) and that is it. Are you sure there are enough remaining stack locations to burn one like this? It is odd that you are passing your device object to MyFltrBuildIrp and not TargetDeviceObject
d
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Monday, April 27, 2009 2:18 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] write IRPs to boot disk fails upon shutdown
I wrote a simplified version of the same code in diskperf to reproduce the problem. In total I receive 3 IRP_MJ_SHUTDOWN irps. Reads sent after receiving these shutdown irps completed successfully while first 2 writes failed with STATUS_ACCESS_DENIED and 3rd write never came back keeping the thread wait in MyFltrSendIrp (). Following is the code. Can anybody point out what is missing here? Thanks.
PIRP MyFltrBuildIrp (IN PDEVICE_OBJECT DeviceObject,
IN UCHAR ReqCode,
IN ULONG LBA,
IN ULONG Count,
PUCHAR Buffer)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIRP irp;
PIO_STACK_LOCATION stack;
LARGE_INTEGER startingOffset;
ULONG numOfBytes;
startingOffset.QuadPart = (LONGLONG)LBA * 512;
numOfBytes = Count * 512;
irp = IoAllocateIrp (DeviceObject->StackSize, FALSE);
if (!irp) {
ASSERT (0);
return (NULL);
}
IoSetNextIrpStackLocation (irp);
stack = IoGetCurrentIrpStackLocation (irp);
stack->MajorFunction = ReqCode;
switch (ReqCode) {
case IRP_MJ_WRITE:
stack->Parameters.Write.Length = numOfBytes;
stack->Parameters.Write.ByteOffset = startingOffset;
break;
case IRP_MJ_READ:
stack->Parameters.Read.Length = numOfBytes;
stack->Parameters.Read.ByteOffset = startingOffset;
break;
default:
ASSERT (0);
break;
}
IoCopyCurrentIrpStackLocationToNext (irp);
irp->IoStatus.Information = 0;
ASSERT (deviceExtension->TargetDeviceObject->Flags & DO_DIRECT_IO);
irp->MdlAddress = IoAllocateMdl (Buffer,
numOfBytes,
FALSE,
FALSE,
NULL);
if (!irp->MdlAddress) {
ASSERT (0);
IoFreeIrp (irp);
return (NULL);
}
MmBuildMdlForNonPagedPool (irp->MdlAddress);
return (irp);
}
VOID MyFltrSendIrp (IN PDEVICE_OBJECT DeviceObject,
IN UCHAR ReqCode,
IN ULONG LBA,
IN ULONG Count,
IN PUCHAR Buffer)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIRP irp;
KEVENT event;
NTSTATUS status;
irp = MyFltrBuildIrp (DeviceObject, ReqCode, LBA, Count, Buffer);
if (!irp) {
ASSERT (0);
return;
}
KeInitializeEvent (&event, NotificationEvent, FALSE);
IoSetCompletionRoutine (irp,
MyFltrIrpCompletion,
&event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver (deviceExtension->TargetDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
status = irp->IoStatus.Status;
if (!NT_SUCCESS (status)) {
switch (ReqCode) {
case IRP_MJ_WRITE:
DbgPrintEx (DPFLTR_IHVDRIVER_ID,
DPFLTR_ERROR_LEVEL,
“MyFltrSendIrp: WRITE FAILED with Status [0x%x] !!!.”
“Information = 0x%x\n”,
status,
irp->IoStatus.Information);
break;
case IRP_MJ_READ:
DbgPrintEx (DPFLTR_IHVDRIVER_ID,
DPFLTR_ERROR_LEVEL,
“MyFltrSendIrp: READ FAILED with Status [0x%x] !!!.”
“Information = 0x%x\n”,
status,
irp->IoStatus.Information);
break;
default:
ASSERT (0);
}
}
}
if (irp->MdlAddress) {
PMDL mdl, nextMdl;
for (mdl = irp->MdlAddress; mdl != NULL; mdl = nextMdl) {
nextMdl = mdl->Next;
IoFreeMdl (mdl);
}
irp->MdlAddress = NULL;
}
IoFreeIrp (irp);
}
VOID MyFltrTestSyncReadWrite (IN PDEVICE_OBJECT DeviceObject)
{
ULONG lba, cnt;
UCHAR buffer[512];
lba = 0x1600000;
cnt = 0x1;
RtlZeroMemory (buffer, 512);
// send a read
MyFltrSendIrp (DeviceObject, IRP_MJ_READ, lba, cnt, buffer);
// send a write
MyFltrSendIrp (DeviceObject, IRP_MJ_WRITE, lba, cnt, buffer);
}
NTSTATUS
MyFltrShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called for a shutdown and flush IRPs. These are sent by the
system before it actually shuts down or when the file system does a flush.
Arguments:
DriverObject - Pointer to device object to being shutdown by system.
Irp - IRP involved.
Return Value:
NT Status
–*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation (Irp);
DebugPrint((2, “MyFltrShutdownFlush: DeviceObject %X Irp %X\n”,
DeviceObject, Irp));
switch (stack->MajorFunction) {
case IRP_MJ_FLUSH_BUFFERS:
break;
case IRP_MJ_SHUTDOWN:
DbgPrintEx (DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
MyFltrShutdownFlush: DeviceObject [0x%X], PendingIrpCnt [0x%x]\n",
DeviceObject,
InterlockedCompareExchange (&deviceExtension->PendingIrpCnt, 0, 0));
ASSERT (KeGetCurrentIrql () == PASSIVE_LEVEL);
MyFltrTestSyncReadWrite (DeviceObject);
break;
default:
ASSERT (0);
break;
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end MyFltrShutdownFlush()
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer