Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.
Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/
Hello.
This is my first excursion into both Windows development and Windows drivers.
I use the Microsoft example for NDIS protocol driver (ndisprot630).
Reading and writing ethernet frames with synchronous I/O has not shown any problems.
But what I'm using the driver for needs non-blocking read/write. I only send one frame and receive one frame over and over again so I've decided to use asynchronous I/O with callbacks.
This is what I have:
static VOID reset_overlap(LPOVERLAPPED lpOverlapped) { if (lpOverlapped->hEvent == NULL) { lpOverlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (lpOverlapped->hEvent == NULL) { DEBUGP("Couldn't create event\n"); } } else { ResetEvent(lpOverlapped->hEvent); } lpOverlapped->Internal = 0; lpOverlapped->InternalHigh = 0; lpOverlapped->Offset = 0; lpOverlapped->OffsetHigh = 0; } static VOID CALLBACK read_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { if (dwErrorCode != 0) { DEBUGP("read cb %lu\n", dwErrorCode); } if (dwNumberOfBytesTransfered == 0) { DEBUGP("read cb len %lu\n", dwNumberOfBytesTransfered); } reset_overlap(&ReadOverlap); ReadBufferReadBytes = dwNumberOfBytesTransfered; OverlapReadStarted = FALSE; } INT read_async( HANDLE Handle, LPVOID Data, UINT DataLen ) { INT retval = 0; DWORD status = WaitForSingleObjectEx(Handle, 0, TRUE); if ((status != WAIT_IO_COMPLETION) && (status != WAIT_TIMEOUT)) { DEBUGP("Async read wait status %lu %lu %u %u %llu %llu\n", status, GetLastError(), ReadBufferReadBytes, OverlapReadStarted, ReadOverlap.Internal, ReadOverlap.InternalHigh); } if (ReadBufferReadBytes > 0) { memcpy(Data, ReadBuffer, ReadBufferReadBytes); retval = ReadBufferReadBytes; ReadBufferReadBytes = 0; } if (!OverlapReadStarted) { // DEBUGP("Async read starting %lu\n", status); if (!ReadFileEx(Handle, ReadBuffer, MAX_PACKET_LEN, &ReadOverlap, read_callback)) { DEBUGP("ReadFileEx error %lu\n", GetLastError()); } else { DWORD error = GetLastError(); if (error != ERROR_SUCCESS) { DEBUGP("ReadFileEx ok %lu\n", error); } OverlapReadStarted = TRUE; } } return retval; }
This works for some frames but eventually I get stuck with an incoming frame that is not read and the completion routine isn't called. I also get lots of these debug messages
LIB DEBUG: Async read wait status 0 0 0 1 0 0
Handle signaled state is something that changes from when it's working but I can't figure out why and how to get out of it.
ReadFileEx() call does not generate any debug-prints.
Adding more debug-prints seem to help in it working for longer.
So any problems or hints on how this should be done would be greatly appreciated.
Upcoming OSR Seminars | ||
---|---|---|
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead! | ||
Kernel Debugging | 13-17 May 2024 | Live, Online |
Developing Minifilters | 1-5 Apr 2024 | Live, Online |
Internals & Software Drivers | 11-15 Mar 2024 | Live, Online |
Writing WDF Drivers | 26 Feb - 1 Mar 2024 | Live, Online |
Comments
Turns out it wasn't an incoming frame that was missing but the write that didn't send the previous frame and there was no reply to read. Sorry about that! Not sure if I can close discussion myself.
Was it your intention to not wait for the handle to be signaled here:
DWORD status = WaitForSingleObjectEx(Handle, 0, TRUE);
'0' results in just polling the handle signal state. If you intended to block until the handle is signaled you want to use 'INFINITE'. The return status '0' indicates that the Handle is currently set. (WAIT_OBJECT_0).