user app to process IRP_MJ_READ packets

I want my WIN32 application (not the driver) to process IRP_MJ_READ
packets data. What should I do ?

My SYS driver is based on M$ ramdisk example and is quite simple.
Assume, that the application is always active and running. Please do not
worry about it.

Note that on IRP_MJ_READ event I have to send some data (like starting
sector number) to my application, then prepare new data (sector
contents) in that application, send it back to the driver, then complete
IRP_MJ_READ packet. Preparing returning sector data by my application
may take up to 3 seconds.

I know how to exchange data between the driver and my application using
private IOCTL commands. I suppose I should notify my application when
IRP_MJ_READ packet is received. This is the thing that I can do. But how
to “hold” that IRP_MJ_READ packet until my app returns new data ?
Any ideas and/or examples with source code ?

Jurkie (newbie/novice)

What is it that you want to do in an application but can’t do in a
driver? You’re asking for a pretty big performance hit here, as well as
potential security headaches.

Anyway, what you want to do is pend the IRP while you handle it. Any
good driver book will contain all the necessary information (as does the
DDK documentation for that matter). Walter Oney’s Programming the
Microsoft Windows Driver Model, 2nd Edition is highly recommended here.

jurkie wrote:

I want my WIN32 application (not the driver) to process IRP_MJ_READ
packets data. What should I do ?

My SYS driver is based on M$ ramdisk example and is quite simple.
Assume, that the application is always active and running. Please do not
worry about it.

Note that on IRP_MJ_READ event I have to send some data (like starting
sector number) to my application, then prepare new data (sector
contents) in that application, send it back to the driver, then complete
IRP_MJ_READ packet. Preparing returning sector data by my application
may take up to 3 seconds.

I know how to exchange data between the driver and my application using
private IOCTL commands. I suppose I should notify my application when
IRP_MJ_READ packet is received. This is the thing that I can do. But how
to “hold” that IRP_MJ_READ packet until my app returns new data ?
Any ideas and/or examples with source code ?

Jurkie (newbie/novice)


…/ray..

Please remove “.spamblock” from my email address if you need to contact
me outside the newsgroup.

> What is it that you want to do in an application but can’t do in a

driver?

There are no reasons to put this big code with all those big arrays, GUI
procedures etc. into the driver.

OK, then let’s simplify my problem.

There are 2 private IOCTLs in my driver in IRP_MJ_DEVICE_CONTROL
dispatch routine:

#define MYDEV 0x8000
#define IOCTL_PEND CTL_CODE(MYDEV, 0x801, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_COMP CTL_CODE(MYDEV, 0x802, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)


case IOCTL_PEND:
IoMarkIrpPending(Irp);
devExt->NotifyIrp = Irp; // store this IRP
return STATUS_PENDING;

case IOCTL_COMP:
nfyirp = devExt->NotifyIrp; // restore IRP
nfyirp->IoStatus.Status = STATUS_SUCCESS;
nfyirp->IoStatus.Information = 0;
IoCompleteRequest(nfyirp, IO_NO_INCREMENT);
break;

IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;

My application opens the driver like this:

Dev = CreateFile(volumename, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, NULL);

then creates a thread in which it posts one waiting IRP:

DeviceIoControl(Dev, IOCTL_PEND, NULL,0,NULL,0,&bytret,NULL);
(it waits for a completion, i.e. hangs here - that’s OK for me)

then several seconds later my application (main thread) calls:

DeviceIoControl(Dev, IOCTL_COMP, NULL,0,NULL,0,&bytret,NULL);

that hangs, too ! WHY ???

I wanted that call to complete IOCTL_PEND packet, then complete itself
(IOCTL_COMP packet). Is it possible to pend one IRP, then complete it
posting second IRP from the same application ?

> then creates a thread in which it posts one waiting IRP:

DeviceIoControl(Dev, IOCTL_PEND, NULL,0,NULL,0,&bytret,NULL);
(it waits for a completion, i.e. hangs here - that’s OK for me)

then several seconds later my application (main thread) calls:

DeviceIoControl(Dev, IOCTL_COMP, NULL,0,NULL,0,&bytret,NULL);

that hangs, too ! WHY ???

Because you didn’t open the file with FILE_FLAG_OVERLAPPED, so you can only
do one IO at a time on the file handle. (With some minor exceptions like
Cancel.)

The simplest solution in your existing design is to create two overlap
structures, one in each thread.

In the waiter thread, do the ioctl with the last parameter pointing to the
initialized overlap structurre, then do a GetOverlappedResult (blah blah,
TRUE) on that structure to wait for the ioctl to complete. Look at what
happens with an overlapped io - you will have to get some of the results
from the overlap structure itself rather than from return fields on the
original call.

In the main thread you probably want to do exactly the same thing, since I
assume you want a synchronous IO there to. But you need a separate overlap
structure.

Remember to close event handles and the like when your program ends.

I wanted that call to complete IOCTL_PEND packet, then complete itself
(IOCTL_COMP packet). Is it possible to pend one IRP, then complete it
posting second IRP from the same application ?

Certainly, as above. Note though that the driver has to cooperate. If you
are using a single queue for all IRPs, it won’t work, because it will be
blocking the queue on the PEND IRP.

You also have to consider what happens if you get a COMP and don’t have a
PEND active, which is certainly a possibility with two threads as you have
shown. Note though that it woudl be quite possible to do it with a single
thread, which could then assure the correct ordering of the requests to the
driver.

Loren

Thank you very much. Looks like now, with these overlapped structures
used, it is working as I wanted to!

I hope it is normal that DeviceIoControl(Dev, IOCTL_PEND,…) returns
FALSE, where GetLastError() reads “Overlapped I/O operation in
progress” here. Other functions return with no errors.

> […] that hangs, too ! WHY ???

Because you didn’t open the file with FILE_FLAG_OVERLAPPED, so you can only
do one IO at a time on the file handle. (With some minor exceptions like
Cancel.)

The simplest solution in your existing design is to create two overlap
structures, one in each thread. […]