KMDF Verifier Complains About Filtering Create

Let’s say you are a KMDF filter driver. Let’s say you need to filter IRP_MJ_CREATE calls. Let’s say there are some create calls you don’t really care about, so you just WdfRequestSend with WDF_SEND_OPTIONS_SEND_AND_FORGET. If you do that while the KMDF verifier is on, it will blue screen with an assert, complaining that it must have a completion routine and be post-processed. Why? What disaster is it trying to avoid? What post-processing do they expect me to do??

Juuuuussst to be sure: You don’t that SEND_AND_FORGET to a Local I/O Target, yes? I know you said “filter” but that doesn’t necessarily mean you’re passing your Create through to the in-stack target. That’s the #1 issue I’ve seen with SEND_AND_FORGET… people trying to use it to send to non-local Targets.

Aside from that, I can’t IMAGINE what it thinks its trying to avoid. Have you looked at the WDF Sources?

Peter

For the same of completeness, looking at the sources on github, I can’t see why this would fail:

https://github.com/microsoft/Windows-Driver-Frameworks/blob/e56019d083eaecb0b554f0d9246e89241e4a93c0/src/framework/shared/core/fxrequestapi.cpp#L1925

Very mysterious,

P

You can blame me :slight_smile:

https://github.com/microsoft/Windows-Driver-Frameworks/blob/master/src/framework/shared/core/fxrequest.cpp#L1096

    // You cannot fire and forget a create irp if we created a WDFFILEOBJECT
    // for it since you must post process the status of the create because
    // the create can fail in the driver to which we are sending the irp.
    //
    if ((m_Irp.GetMajorFunction() == IRP_MJ_CREATE)
        &&
        (FxFileObjectClassNormalize(GetDevice()->GetFileObjectClass()) !=
            WdfFileObjectNotRequired)) {

        DoTraceLevelMessage(
            FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGREQUEST,
            "WDFREQUEST %p cannot send and forget a create request which "
            "has a WDFFILEOBJECT created for it, it must have a completion "
            "routine and be post processsed", GetHandle());

        FxVerifierDbgBreakPoint(FxDriverGlobals);
    }

Yes, I found that in the source, because the text wasn’t in the in-flight recorder logs for some reason. I was hoping Doron would respond, because I was pretty sure it came from him. Neither the message nor the comments tells me WHAT post-processing I’m expected to do. I don’t see that the framework is doing anything special when calling WdfRequestComplete with IRP_MJ_CREATE and a failure code. Do you remember what prompted this?

LOL… thanks for “fessing up” Doron. At least we now know who to blame :wink:

So, the issue here is that WDF might have to “tear down” the WDFFILEOBJECT that it created.

Surely the code could handle this with its own internal completion routine, no??

Well, I’m happy to learn something at least. Nice issue. Thanks for posting it, Mr. Roberts.

Peter

At the time, we didn’t want to “steal” the driver’s io stack location in the fire and forget case and we didn’t want to always allocate an extra io stack location just for the framework (which we had in very early implementations when packages were supposed to be the layering abstraction layering). The documentation is going to be updated to say that when you configure to create WDFFILEOBJECTs you need to complete the request in some fashion. BTW, the existing behavior is tucked away in the docs (emphasis is mine)

https://docs.microsoft.com/en-us/windows-hardware/drivers/wdf/framework-file-objects

If a driver forwards a creation request to an I/O target, the driver cannot set the WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET flag if the framework has created a framework file object for the creation request. Therefore, the driver cannot set the WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET flag for a creation request unless it also sets the WdfFileObjectNotRequired flag.

OK, so what I’ve done is replace the “send-and-forget” with nothing more than a “send-synchronously” and a “WdfRequestComplete(request, WdfRequestGetStatus(request));”. That does satisfy the verifier, and from the documentation, that seems like it should be enough.

I’m glad I asked.