Beispiel #1
0
NTSTATUS
Bus_EjectDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )

/*++

Routine Description:

    The user application has told us to eject the device from the bus.
    In a real situation the driver gets notified by an interrupt when the
    user presses the Eject button on the device.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/

{
    PPDO_DEVICE_DATA pdoData;
    BOOLEAN          ejectAll;
    WDFDEVICE        hChild;
    NTSTATUS         status = STATUS_INVALID_PARAMETER;

    PAGED_CODE ();

    //
    // Scan the list to find matching PDOs
    //
    ejectAll = (0 == SerialNo) ? TRUE : FALSE;
    hChild = NULL;

    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                                       hChild,
                                       WdfRetrieveAddedChildren)) != NULL) {

        pdoData = PdoGetData(hChild);

        if (ejectAll || SerialNo == pdoData->SerialNo) {

            status = STATUS_SUCCESS;
            WdfPdoRequestEject(hChild);
            if (!ejectAll) {
                break;
            }
        }
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);

    return status;
}
Beispiel #2
0
/**
 * @brief handles child device processing on device removal.
 * 
 * @param[in] Device handle to the WDFDEVICE created by FdoEvtDeviceAdd().
 * 
 */
VOID RemoveAllChildDevices(
    IN WDFDEVICE Device)
{
    WdfFdoLockStaticChildListForIteration(Device);

    WDFDEVICE  hChild = NULL;

    while ((hChild = WdfFdoRetrieveNextStaticChild(
        Device, 
        hChild,
        WdfRetrieveAddedChildren)) != NULL) 
    {
        NTSTATUS Status = WdfPdoMarkMissing(hChild);
        if (!NT_SUCCESS(Status))
        {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
                __FUNCTION__": Device %p WdfPdoMarkMissing %p error %x\n",
                Device,
                hChild,
                Status);
            XXX_TODO("What to do with a pdo we can't mark missing?\n");
        }
        else
        {
            TraceEvents(TRACE_LEVEL_WARNING, TRACE_DEVICE,
                __FUNCTION__": Device %p WdfPdoMarkMissing %p\n",
                Device,
                hChild);

            WDF_DEVICE_STATE    deviceState;
            WDF_DEVICE_STATE_INIT (&deviceState);
            deviceState.Removed = WdfTrue;

            WdfDeviceSetDeviceState(hChild,
                &deviceState);
        }
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);
}
Beispiel #3
0
NTSTATUS
Bus_UnPlugDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )
/*++

Routine Description:

    The application has told us a device has departed from the bus.

    We therefore need to flag the PDO as no longer present
    and then tell Plug and Play about it.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/

{
    PPDO_DEVICE_DATA pdoData;
    BOOLEAN          found = FALSE;
    BOOLEAN          plugOutAll;
    WDFDEVICE        hChild;
    NTSTATUS         status = STATUS_INVALID_PARAMETER;

    PAGED_CODE ();

    plugOutAll = (0 == SerialNo) ? TRUE : FALSE;

    hChild = NULL;

    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                            hChild, WdfRetrieveAddedChildren)) != NULL) {

        if (plugOutAll) {

            status = WdfPdoMarkMissing(hChild);
            if(!NT_SUCCESS(status)) {
                KdPrint(("WdfPdoMarkMissing failed 0x%x\n", status));
                break;
            }

            found = TRUE;
        }
        else {
            pdoData = PdoGetData(hChild);

            if (SerialNo == pdoData->SerialNo) {

                status = WdfPdoMarkMissing(hChild);
                if(!NT_SUCCESS(status)) {
                    KdPrint(("WdfPdoMarkMissing failed 0x%x\n", status));
                    break;
                }

                found = TRUE;
                break;
            }
        }
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);

    if (found) {
        status = STATUS_SUCCESS;
    }

    return status;
}
Beispiel #4
0
NTSTATUS
Bus_PlugInDevice(
    _In_ WDFDEVICE  Device,
    _In_ PWCHAR     HardwareIds,
    _In_ ULONG      SerialNo
    )

/*++

Routine Description:

    The user application has told us that a new device on the bus has arrived.

    We therefore need to create a new PDO, initialize it, add it to the list
    of PDOs for this FDO bus, and then tell Plug and Play that all of this
    happened so that it will start sending prodding IRPs.

--*/

{
    NTSTATUS         status = STATUS_SUCCESS;
    BOOLEAN          unique = TRUE;
    WDFDEVICE        hChild;
    PPDO_DEVICE_DATA pdoData;
    PFDO_DEVICE_DATA deviceData;

    PAGED_CODE ();

    //
    // First make sure that we don't already have another device with the
    // same serial number.
    // Framework creates a collection of all the child devices we have
    // created so far. So acquire the handle to the collection and lock
    // it before walking the item.
    //
    deviceData = FdoGetData(Device);
    hChild = NULL;

    //
    // We need an additional lock to synchronize addition because
    // WdfFdoLockStaticChildListForIteration locks against anyone immediately
    // updating the static child list (the changes are put on a queue until the
    // list has been unlocked).  This type of lock does not enforce our concept
    // of unique IDs on the bus (ie SerialNo).
    //
    // Without our additional lock, 2 threads could execute this function, both
    // find that the requested SerialNo is not in the list and attempt to add
    // it.  If that were to occur, 2 PDOs would have the same unique SerialNo,
    // which is incorrect.
    //
    // We must use a passive level lock because you can only call WdfDeviceCreate
    // at PASSIVE_LEVEL.
    //
    WdfWaitLockAcquire(deviceData->ChildLock, NULL);
    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                            hChild, WdfRetrieveAddedChildren)) != NULL) {
        //
        // WdfFdoRetrieveNextStaticChild returns reported and to be reported
        // children (ie children who have been added but not yet reported to PNP).
        //
        // A surprise removed child will not be returned in this list.
        //
        pdoData = PdoGetData(hChild);

        //
        // It's okay to plug in another device with the same serial number
        // as long as the previous one is in a surprise-removed state. The
        // previous one would be in that state after the device has been
        // physically removed, if somebody has an handle open to it.
        //
        if (SerialNo == pdoData->SerialNo) {
            unique = FALSE;
            status = STATUS_INVALID_PARAMETER;
            break;
        }
    }

    if (unique) {
        //
        // Create a new child device.  It is OK to create and add a child while
        // the list locked for enumeration.  The enumeration lock applies only
        // to enumeration, not addition or removal.
        //
        status = Bus_CreatePdo(Device, HardwareIds, SerialNo);
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);
    WdfWaitLockRelease(deviceData->ChildLock);

    return status;
}