locked
GUID_DEVICE_INTERFACE_ARRIVAL does not reach for a raw pdo RRS feed

  • Question

  • My purpose was communicate between the mouse filter (WDK's firefly  Sample) and the keyboard filter (WDK's firefly sample).

    I used the origin code of the kbfilter Sample. I added the underlying code within the firefly:

    status = IoRegisterPlugPlayNotification(
    EventCategoryDeviceInterfaceChange,
    PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
    (PVOID)&GUID_DEVINTERFACE_KBFILTER,
    WdfDriverWdmGetDriverObject(WdfDeviceGetDriver(device)),
    (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)
    fireflyPnpNotifyInterfaceChange,
    (PVOID)deviceExtension,
    &deviceExtension->NotificationHandle);

    the GUID_DEVINTERFACE_KBFILTER was the kbfilter's raw-PDO Device Interface.  It's unable to reach the callback.

    when I used the common device Interface. It's worked very well. I don't know what's the problem and how to solve it.

    Monday, August 3, 2015 5:58 PM

All replies

  • are you sure the  raw PDO started successfully?

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, August 3, 2015 9:01 PM
  • I started the test application. and It work well. so I make sure the raw-pdo started successfully. Am I right?
    Tuesday, August 4, 2015 1:04 AM
  • did the IoRegister callback succeed?

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, August 4, 2015 4:30 AM
  • yes. it return 0x0
    Tuesday, August 4, 2015 8:01 AM
  • Yes. It return 0x0. the target device was a PS/2 Keyboard on the virtual machine.
    Tuesday, August 4, 2015 8:04 AM
  • keyboard's raw-PDO create function:

    NTSTATUS                    status;
        PWDFDEVICE_INIT             pDeviceInit = NULL;
        PRPDO_DEVICE_DATA           pdoData = NULL;
        WDFDEVICE                   hChild = NULL;
        WDF_OBJECT_ATTRIBUTES       pdoAttributes;
        WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
        WDF_IO_QUEUE_CONFIG         ioQueueConfig;
        WDFQUEUE                    queue;
        WDF_DEVICE_STATE            deviceState;
        PDEVICE_EXTENSION           devExt;
        DECLARE_CONST_UNICODE_STRING(deviceId,KBFILTR_DEVICE_ID );
        DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID );
        DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" );
        DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);

        DebugPrint(("Entered KbFiltr_CreateRawPdo\n"));

        //
        // Allocate a WDFDEVICE_INIT structure and set the properties
        // so that we can create a device object for the child.
        //
        pDeviceInit = WdfPdoInitAllocate(Device);

        if (pDeviceInit == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }

        //
        // Mark the device RAW so that the child device can be started
        // and accessed without requiring a function driver. Since we are
        // creating a RAW PDO, we must provide a class guid.
        //
        status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVCLASS_KEYBOARD);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // Since keyboard is secure device, we must protect ourselves from random
        // users sending ioctls and creating trouble.
        //
        status = WdfDeviceInitAssignSDDLString(pDeviceInit,
                                               &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID
        //
        status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // For RAW PDO, there is no need to provide BusQueryHardwareIDs
        // and BusQueryCompatibleIDs IDs unless we are running on
        // Windows 2000.
        //
        if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) {
            //
            // On Win2K, we must provide a HWID for the device to get enumerated.
            // Since we are providing a HWID, we will have to provide a NULL inf
            // to avoid the "found new device" popup and get the device installed
            // silently.
            //
            status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId);
            if (!NT_SUCCESS(status)) {
                goto Cleanup;
            }
        }

    WdfDeviceInitSetExclusive(pDeviceInit, FALSE);


        //
        // We could be enumerating more than one children if the filter attaches
        // to multiple instances of keyboard, so we must provide a
        // BusQueryInstanceID. If we don't, system will throw CA bugcheck.
        //
        status =  RtlUnicodeStringPrintf(&buffer, L"%02d", InstanceNo);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // Provide a description about the device. This text is usually read from
        // the device. In the case of USB device, this text comes from the string
        // descriptor. This text is displayed momentarily by the PnP manager while
        // it's looking for a matching INF. If it finds one, it uses the Device
        // Description from the INF file to display in the device manager.
        // Since our device is raw device and we don't provide any hardware ID
        // to match with an INF, this text will be displayed in the device manager.
        //
        status = RtlUnicodeStringPrintf(&buffer,L"Keyboard_Filter_%02d", InstanceNo );
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // You can call WdfPdoInitAddDeviceText multiple times, adding device
        // text for multiple locales. When the system displays the text, it
        // chooses the text that matches the current locale, if available.
        // Otherwise it will use the string for the default locale.
        // The driver can specify the driver's default locale by calling
        // WdfPdoInitSetDefaultLocale.
        //
        status = WdfPdoInitAddDeviceText(pDeviceInit,
                                            &buffer,
                                            &deviceLocation,
                                            0x409
                                            );
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);
        
        //
        // Initialize the attributes to specify the size of PDO device extension.
        // All the state information private to the PDO will be tracked here.
        //
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA);

        //
        // Set up our queue to allow forwarding of requests to the parent
        // This is done so that the cached Keyboard Attributes can be retrieved
        //
        WdfPdoInitAllowForwardingRequestToParent(pDeviceInit);

        status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // Get the device context.
        //
        pdoData = PdoGetData(hChild);

        pdoData->InstanceNo = InstanceNo;

        //
        // Get the parent queue we will be forwarding to
        //
        devExt = FilterGetData(Device);
        pdoData->ParentQueue = devExt->rawPdoQueue;

        //
        // Configure the default queue associated with the control device object
        // to be Serial so that request passed to EvtIoDeviceControl are serialized.
        // A default queue gets all the requests that are not
        // configure-fowarded using WdfDeviceConfigureRequestDispatching.
        //

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                        WdfIoQueueDispatchSequential);

        ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlForRawPdo;

        status = WdfIoQueueCreate(hChild,
                                            &ioQueueConfig,
                                            WDF_NO_OBJECT_ATTRIBUTES,
                                            &queue // pointer to default queue
                                            );
        if (!NT_SUCCESS(status)) {
            DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status));
            goto Cleanup;
        }

        //
        // Set some properties for the child device.
        //
        WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

        pnpCaps.Removable         = WdfTrue;
        pnpCaps.SurpriseRemovalOK = WdfTrue;
        pnpCaps.NoDisplayInUI     = WdfTrue;

        pnpCaps.Address  = InstanceNo;
        pnpCaps.UINumber = InstanceNo;

        WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

        //
        // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we
        // have to do the following to hide the device. Following call
        // tells the framework to report the device state in
        // IRP_MN_QUERY_DEVICE_STATE request.
        //
        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.DontDisplayInUI = WdfTrue;
        WdfDeviceSetDeviceState(hChild, &deviceState);

        //
        // Tell the Framework that this device will need an interface so that
        // application can find our device and talk to it.
        //
        status = WdfDeviceCreateDeviceInterface(
                     hChild,
                     &GUID_DEVINTERFACE_KBFILTER,
                     NULL
                 );

        if (!NT_SUCCESS (status)) {
            DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));
            goto Cleanup;
        }

        //
        // Add this device to the FDO's collection of children.
        // After the child device is added to the static collection successfully,
        // driver must call WdfPdoMarkMissing to get the device deleted. It
        // shouldn't delete the child device directly by calling WdfObjectDelete.
        //
        status = WdfFdoAddStaticChild(Device, hChild);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }

        //
        // pDeviceInit will be freed by WDF.
        //
        return STATUS_SUCCESS;

    Cleanup:

        DebugPrint(("KbFiltr_CreatePdo failed %x\n", status));

        //
        // Call WdfDeviceInitFree if you encounter an error while initializing
        // a new framework device object. If you call WdfDeviceInitFree,
        // do not call WdfDeviceCreate.
        //
        if (pDeviceInit != NULL) {
            WdfDeviceInitFree(pDeviceInit);
        }

        if(hChild) {
            WdfObjectDelete(hChild);
        }

        return status;

    Tuesday, August 4, 2015 12:18 PM