My Win2K/XP serial filter driver snoops on the PPP negotiation between Windows and a modem and needs to generate an IRP_MJ_WRITE request from scratch and pass it down to the lower driver. However, it seems I'm missing an important step since IoCallDriver fails.
Here's my latest code. I am getting a STATUS_UNSUCCESSFUL from IoCallDriver. I took a look at passed down IRP_MJ_WRITE requests that the driver forwards to the next lower driver and have taken a look at the related IRP and IO_STACK_LOCATION structures, hoping to find an answer to my problem. However, the structures are similar to what mine look like. The only major difference I've been seeing is in the Flags member of the IRP structure: I have seen a value of 0x40000200 on IRP_MJ_WRITE requests, which means IRP_WRITE_OPERATION (0x200) and something else that I haven't been able to track down (the 0x40000000).
I'm about to go insane with this. Top few lines just pass the current request down without doing anything with it (and it works fine). Please note that this code is all part of the master dispatch handler of my driver. Also note that pbFakeWrite has been allocated from NonPagedPool.
// Pass request down without additional processing
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
return CompleteRequest(Irp, status, 0);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
// my extra code to send a custom IRP_MJ_WRITE to the lower driver
if(pbFakeWrite != NULL)
NTSTATUS status2 = STATUS_SUCCESS;
PIRP pNewIrp = NULL;
PIO_STACK_LOCATION pStack = NULL;
startingOffset.QuadPart = 0;
pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE, pdx->LowerDeviceObject, pbFakeWrite, ulFakeWriteLen, &startingOffset, NULL);
if(pNewIrp == NULL)
status2 = STATUS_INSUFFICIENT_RESOURCES;
pNewIrp->Flags |= IRP_WRITE_OPERATION; // not sure if that is needed
status2 = IoAcquireRemoveLock(&pdx->RemoveLock, pNewIrp);
pStack = IoGetNextIrpStackLocation(pNewIrp); // for debugging purposes
KdPrint(("pStack->Parameters.Write: %d\n", pStack->Parameters.Write.Length));
IoSetCompletionRoutine(pNewIrp, (PIO_COMPLETION_ROUTINE)CompletionRoutine, pdx, TRUE, TRUE, TRUE);
status2 = IoCallDriver(pdx->LowerDeviceObject, pNewIrp);
KdPrint(("IoCallDriver failed (%08X)\n", status2));