Driver asynchronous I/O problem.

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.

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).