Zw(Read|Write)File not working in driver dispatch routine.

Hello everyone,

I am new to driver development and am having a bit of trouble with a particular aspect of my driver. In particular it seems that in my driver dispatch routines for IRP_MJ_READ and IRP_MJ_WRITE when I call ZwReadFile and then if it returns STATUS_PENDING and I ZwWaitForSingleObject, that it is not actually able to read/write. (Not returning STATUS_FAILURE, but when I check my data it is not there). What is stumping me is that it doesn’t occur all the time. From what I have read it appears that it could be because driver dispatch routines execute in arbitrary thread context, so that when I wait on the object the context that created the file handle is no longer valid and thus the read/write “fail”.

One interesting thing that I have noticed is that I do similar: read, modify, write cycles in my EvtDeviceAdd routine and these all succeed. From what I know, EvtDeviceAdd is guaranteed to run in the system process context, so this further points to a thread/process context issue for my problem in the driver dispatch routines. I will post the code that I am using below. Any and all suggestions would be greatly appreciated. I feel like what I need to do is either A) setup a dedicated system thread to do reads/writes in my dispatch routines, or B) Somehow “switch” my dispatch routines to be in the system process/thread context. Thanks for the help.

*Note: Neither ZwReadFile() or ZwWaitForSingleObject() return a STATUS_FAILURE. When I say that, “the function is unable to read”, I mean that when I look at the buffer
nothing was read.

#if 1
if (KeAreApcsDisabled()) {
KdPrint((“APCs are disabled!!!\n”));
}
{
HANDLE h;
h = PsGetCurrentProcessId();
if (h != 4) {
KdPrint((“******** pid: %p\n”, h));
}
}
#endif
status = ZwReadFile(mm->volumeHandle,
NULL,
NULL,
NULL,
&ioStatus,
cluster,
mm->clusterSize,
&offset,
NULL);
if (status == STATUS_PENDING) {
//status = ZwWaitForSingleObject(mm->volumeHandle, FALSE, NULL);
status = ZwWaitForSingleObject(mm->volumeHandle, TRUE, NULL);
}
#if 1
if (status == STATUS_ALERTED)
KdPrint((“%s STATUS_ALERTED\n”, FUNCTION));
else if (status == STATUS_TIMEOUT)
KdPrint((“%s STATUS_TIMEOUT\n”, FUNCTION));
else if (status == STATUS_USER_APC)
KdPrint((“%s STATUS_USER_APC\n”, FUNCTION));

#endif
if(!NT_SUCCESS(status)){
KdPrint(("read failed (offset=%#I64x, size=%#x, status=%#x) – ",
offset, mm->clusterSize, status));
ExFreePoolWithTag(cluster,ENTRY_DATA_TAG);
return 0;
}