Hi all,
I have a problem with notification on device interface change - it does not work for me at all I spent last few days on this, read (probaly) all MS documentation and other sources, tried many posibilities and still canāt have it working. I fill that Iām in the aā¦, so I need any suggestion, ideas, something, pleaseā¦
The main idea is exactly like described here: http://www.osronline.com/article.cfm^id=24.htm
Some facts:
Iām creating two independent drivers (in the meaning: not belonging to the same driver stack), for Win10/11:
the āmainā driver, which is the root enumerated software driver, exposing two interfaces: one for userspace communication (using IOCTLs), and the second one for inter-driver communcation (query interface);
the ācardā driver, which is the driver for specific (custom) hardware (PCIe card), it doesnāt expose any interface, but registers āitselfā as a subscriber for the PnP notifications about inter-driver communication interface state changes (an then communicates with āmainā driver using this interface - but it is not important here).
So, in the āmainā driver:
in the āadd deviceā handler Iām creating device, then Iām creating the interface using WdfDeviceAddQueryInterface() (of course the dedicated unique GUID is used), and finally Iām enabling this interface using WdfDeviceSetDeviceInterfaceState() with TRUE parameter;
in the ādevice cleanupā event handler Iām disabling this interface using WdfDeviceSetDeviceInterfaceState() with FALSE parameter (of course there are other things done too, but not important here).
And, in the ācardā driver:
in the EvtDeviceSelfManagedIoInit handler Iām registering subscription for notifications about interface state changed, using IoRegisterPlugPlayNotification() with parameters: EventCategoryDeviceInterfaceChange and PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, own callback function, and the same GUID as used in the āmainā driver for creation and enabling/disabling the interface;
in the EvtDeviceSelfManagedIoCleanup handler Iām unregistering subscription for these notifications using IoUnregisterPlugPlayNotificationEx();
of course the NotificationEntry pointer is saved on registering and used for unregistering.
All the above code executes without any problems (Iāve logged entry/exit from all my functions/handlers, and all statuses not equal to STATUS_SUCCESS), all the flow paths are processed, event handlers are fired-up, butā¦ unfortunately Iām not receiving any notifications about interface arrival/romoval: my notification callback function is never fired-up
As I understand the idea of such notifications, I should get the callback call on loading the āmainā driver (so on creating the interface and enabling it), and the second call on unloading the āmainā driver (so on disabling the interface).
Unfortunately, the callback is not called at all
Do you have any ideas, suggestions, what I should check, or maybe Iām totally wrong in my understanding of such notifications?
And the additional question: is there any tool for āspyingā the PnP notifications sent by PnP Manager? Or is there any other way allowing to check that the PnP Manager can see the interface changes made by āmainā driver, and sends the notifications to the ācardā driver?
Oughā¦ Probably found the reason: in the āmainā driver Iām creating interface in āadd deviceā handler after creating the device (it is OK) and iām enabling the interface in the same functionā¦ so probably too early So the interface is never enabled - am I right?
But: where it should be enabled???
I added interface enable/disable inside EvtDeviceD0Entry/EvtDeviceD0Exit handlers in the āmainā driver. Andā¦ it still doesnāt work I can see (in my logs) that these handlers are executed (so the interface is enabled/disabled for sure), but the notification callback in the ācardā driver (subscriber) is not fired-up still :(
Ok, so it seems that I can safely remove handling of the D0 transitions (it is used only for enabling/disabling the query interface).
Regarding to the interfaces: of course, Iām using two different GUIDs - one for interface created with WdfDeviceCreateDeviceInterface, dedicated for communication with userspace (IOCTL), and the different one for the query interface. And, of course, this second GUID is used for registering for notifications in the second driver. So, it should work - but it doesnāt How to investigate this issue? Iāve no idea, really
query interface != device interface. there is no eventing (pub/sub) infrastructure for arrival and departure. Query interface is purely a v-table contract. Which device stack you ask query for the contract (querying for the interface) is separate from the contract itself.
In your scenario the card driver registers for device interface notifications for guid #2. When notified, it opens the interface (WdfIoTargetOpen) and then sends the query interface request (WdfIoTargetQueryForInterface).
You can choose to use one device interface (eliminate #2) to notify the card driver if you want. If the user mode application opens the main driver exclusively it makes sense to have separate device interfaces to advertise the user mode ācontractā and the query interface contract
Ok, I understand how to use the query interface (including INTERFACE structure and so on) - and, if I understand you correctly - I canāt register (in the second driver) any subscriptions for notifications related to the query interface, because it is not the ārealā (whatever it means) interface? Am I right? If so, it seems that I didnāt fully understand this beforeā¦
So, going forward, I have 2 options here:
create additional āfakeā (you called it ākernel modeā) interface in the āmainā driver, acting only as the source of PnP notifications (arrival/removal),
or
use existing āuser-modeā interface as the source of such notifications.
Am I right?
correct. are you enforcing exclusive user mode handles? IOW are you calling WdfDeviceInitSetExclusive ? if so, the open from the kernel driver may fail if the user mode application already has an open handle. One choice would be to remove the WdfDeviceInitSetExclusive call and manage exclusive state yourself, restricting UserMode opens to exclusive and allowing KernelMode regardless of the UserMode open count.
Ok, I implemented this using additional āfakeā interface (as described in pt.1 in my previous post), andā¦ it WORKS!!! @Doron_Holan , thank you very, very much!!! You made my day (or, more precisely, my night - because in Poland there is 02:18AM)! And especially thank you for showing me what I didnāt understand! If we ever meet, I have a great beer for you BTW: I decided not to use the existing āuser modeā interface because it can be temporary disabled in some situations (some things related to improper authorisation of the usermode app - customer/client expectations ), and this should have no effect on the communication between drivers.
Thanks once more!