0

Starting with the ndisprot sample from Microsoft I try to write a NDIS protocol driver. From User space I try to read and write to the device simultaneous (out of two threads). Since I don't receive any packets, the ReadFile system call blocks. I'm not able to complete a WriteFile system call in this state.

CHAR            NdisProtDevice[] = "\\\\.\\\\NDISprot";
CHAR *          pNdisProtDevice = &NdisProtDevice[0];

this.iHandle = CreateFile(pNdisProtDevice,
            GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// Blocks, because no frames arrive

bSuccess = (BOOLEAN)ReadFile(Handle,
                             (LPVOID)pReadBuf,
                             PacketLength,
                             &BytesRead,
                             NULL);

...
// Called some seconds later from another thread, while ReadFile still blocking...
bSuccess = (BOOLEAN)WriteFile(Handle,
                              pWriteBuf,
                              PacketLength,
                              &BytesWritten,
                              NULL); 

I added some debug messages and discovered that the driver function associated with IRP_MJ_WRITE (NdisprotWrite) gets not even called! Something between the user space application and the driver blocks concurrent access to the device \Device\NDISprot.

How can I concurrent Read and Write to the file?

falstaff
  • 3,413
  • 2
  • 25
  • 26
  • If `ReadFile` isn't called until several seconds after `WriteFile`, how can it be responsible for the write blocking? – Harry Johnston May 20 '13 at 03:42
  • Because the ReadFile is still blocking... As soon as I send a packet to that machine, ReadFile succeed, and WriteFile is immediately executed... – falstaff May 21 '13 at 07:01
  • Improved code comment – falstaff May 21 '13 at 07:02
  • I've some interesting findings: The NdisprotRead function (which is bound to IRP_MJ_READ) returns STATUS_PENDING. The IoCompleteRequest, which will complete this IO request is executed later when a new Network frame arrive. The question remains: How can use the WriteFile system call while the driver is in Pending state? Is there a way to make the File read and writeable synchronously? Or do I need to add another File (e.g. one for Reads, one for Writes)? – falstaff May 21 '13 at 16:13
  • 1
    Your code now says that ReadFile is called while ReadFile is still blocking. Are you making two calls to ReadFile? What is the actual order of events? Have you tried opening two handles, one for reading and one for writing? – Harry Johnston May 21 '13 at 19:20
  • Sorry, I mixed up the ReadFile/WriteFile calls... I do a ReadFile first, which blocks, and then the WriteFile call doesn't work. Thanks for the hint using two handles, did not thought about this. I'm going to try that. – falstaff May 23 '13 at 15:09
  • Thanks, the trick with the two handles works. Initially, this didn't work since the driver only allowed one handle to bind to a specific interface. But I had to alter the driver to allow multiple clients to be connected anyway. So now every client connects twice, once for read and once for write... – falstaff May 23 '13 at 15:33

1 Answers1

2

By default, you can only have one outstanding I/O request per usermode handle. Either open multiple handles, or open your one handle with FILE_FLAG_OVERLAPPED. (Once you use FILE_FLAG_OVERLAPPED, you also generally need to use OVERLAPPED structures - make sure you've got the gist of it by skimming this and this.)

Jeffrey Tippet
  • 3,146
  • 1
  • 14
  • 15