Scott Noone wrote:
What behavior are you experiencing that led you down the path of looking at
the I/O completion processing?
Are you handling IRP_MJ_READ/WRITE IRP_MN_MDL requests?
Yes, I am handling IRP_MN_MDL requests. The specific issue that I described above was with IRP_MN_QUERY_DIRECTORY.
My QueryDirectory tests would work fine when using the file system directly, but would fail mysteriously when running under SRV2. Running them under WinDbg I would see that my FSD would return STATUS_SUCCESS, but my tests would still fail. Running them under FileSpy, showed that while my FSD would return STATUS_SUCCESS, SRV2 would convert that response to STATUS_INVALID_NETWORK_RESPONSE.
After double and triple checking that my response buffer was correctly formed and that the Irp->IoStatus.Information was properly set to the response length, I started suspecting other issues. Then I noticed that SRV2 QueryDirectory IRP’s are “different”, they always seem to have a non-NULL Irp->MdlAddress and they always seem to have a completion routine of SrvPostOnCompletionAndClearCancel.
Now for reasons that I will not go into here, my QueryDirectory handler (sometimes) uses the SystemBuffer and sets the IRP up with IRP_BUFFERED_IO | IRP_INPUT_OPERATION | IRP_DEALLOCATE_BUFFER, because it expects normal IRP completion processing to happen. It turns out that SRV2 circumvents normal IRP completion processing by returning STATUS_MORE_PROCESSING_REQUIRED. Thus my nicely formed response in the SystemBuffer was never copied back into the UserBuffer and the SystemBuffer was never freed. Upon IRP completion SRV2 saw garbage in the UserBuffer and responded with STATUS_INVALID_NETWORK_RESPONSE.
A similar issue with the same symptoms was reported to this list a few years ago without resolution: http://www.osronline.com/ShowThread.cfm?link=180361
[ASIDE:
FastFat does not get into this trap for QueryDirectory, because it uses the Irp->MdlAddress when it needs to postpone IRP handling (because it cannot acquire locks, etc.) This works in the SRV2 case, because SRV2 has “helpfully” set the Irp->MdlAddress for it.
I expect that I will hear people saying: “just do what FastFat does”. That is not always possible; my FSD is not FastFat and has very different functionality (the primary difference regarding IRP handling is that I have to potentially pend pretty much every IRP that I receive).
]
While I have fixed this particular issue, I am looking to better understand SRV2 “flavored” IRP’s and how to correctly identify and handle them. I often have to do the SystemBuffer trick, because I often have to pend IRP’s. For example, I also do it in IRP_MJ_QUERY_SECURITY (although my tests pass there – I intend to investigate nevertheless).
Thank you for your attention.
Bill