KMDF filter driver enumerating child PDO and in crash.

Hi,
I have a KMDF 1.15 filter driver for a USB device that enumerates one static child PDO.
This filter has EvtDevicePrepareHardware/EvtDeviceReleaseHardware and EvtCleanupCallback/EvtDestroyCallback callbacks installed (also D0 enter/exit callbacks).
The filter creates a single PDO in its EvtDevicePrepareHardware callback. This seems to work fine and child device is seen in the device manager as expected.
The filter reports the child PDO missing in its EvtDeviceReleaseHardware callback. However, walking the filter device’s list of child PDO’s in its EvtDeviceReleaseHardware results in no child PDO.
WdfFdoLockStaticChildListForIteration(Device);
while ((hChild = WdfFdoRetrieveNextStaticChild(Device, hChild, WdfRetrieveAddedChildren)) != NULL) {
WdfPdoMarkMissing(hChild);
KdPrint((“hChild = 0x%p\n”, hChild ));
}
WdfFdoUnlockStaticChildListFromIteration(Device);

In this case the driver assumes the PDO is no longer available and does nothing and exists from EvtDeviceReleaseHardware.

However this follows with a crash after unloading. This is because: EvtDestroyCallback gets called after EvtDriverUnload is called (ie: after driver is unloaded). Why?
The sequence of events observed are as follows:

  1. Unplug the USB hardware form the USB port

  2. EvtDeviceD0Exit called

  3. EvtDeviceReleaseHardware called

  4. EvtCleanupCallback called

  5. EvtDriverUnload called. Then

  6. EvtDestroyCallback called with WDFDEVICE 0x000053fde5e0d5f8 which is the right FDO that the filter created in its AddDevice routine. Though the EvtDriverUnload is called I am assuming that the driver is still in memory. WDFDEVICE 0x000053fde5e0d5f8 is junk at this point (deleted by the framework?) and that why it crashes with access violation ( ffffffffc0000005 )

    0: kd> !wdfkd.wdfdevice 0x000053fd`e5e0d5f8
    Treating handle as a KMDF handle!

    Dumping WDFDEVICE 0x000053fde5e0d5f8

    WDM PDEVICE_OBJECTs: self 0000000000000000, attached 0000000000000000, pdo ffffac021c2ac060

Why does the framework calls EvtDestroyCallback after calling EvtDriverUnload? The filter does not do any WdfObjectReference on the FDO.

The driver functions normally if the the child PDO creation code is commented out. In which case USB unplug results in the following sequence:

  1. Unplug the USB hardware form the USB port
  2. EvtDeviceD0Exit called
  3. EvtDeviceReleaseHardware called
  4. EvtCleanupCallback called
  5. EvtDestroyCallback called
  6. EvtDriverUnload called
    The driver unloads normally and no crash.

Why does the framework calls EvtDestroyCallback after calling EvtDriverUnload? What am I missing?
Observing this on a Windows 10 1909 build 18362.

Update: No crash with child PDO code back in but after commenting out EvtDestroyCallback. Driver unloads just fine.

Can anyone explain what’s going on here?