Ejemplo n.º 1
0
NTSTATUS Bus_DestroyPdo(PDEVICE_OBJECT Device, PPDO_DEVICE_DATA PdoData)
{
    PFDO_DEVICE_DATA fdoData;
    PAGED_CODE();

	fdoData = FDO_FROM_PDO(PdoData);
	fdoData->NumPDOs--;

    if (PdoData->InterfaceName.Buffer != NULL)
	{
        ExFreePool(PdoData->InterfaceName.Buffer);
        RtlZeroMemory(&PdoData->InterfaceName, sizeof(UNICODE_STRING));
    }

    if (PdoData->HardwareIDs)
	{
        ExFreePool(PdoData->HardwareIDs);
        PdoData->HardwareIDs = NULL;
    }

    Bus_KdPrint(("\tDeleting PDO: 0x%p\n", Device));
    IoDeleteDevice(Device);

    return STATUS_SUCCESS;
}
Ejemplo n.º 2
0
NTSTATUS
Bus_PDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PPDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:
    Handle requests from the Plug & Play system for the devices on the BUS

--*/
{
    NTSTATUS                status;

    PAGED_CODE ();


    //
    // NB: Because we are a bus enumerator, we have no one to whom we could
    // defer these irps.  Therefore we do not pass them down but merely
    // return them.
    //

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Here we do what ever initialization and ``turning on'' that is
        // required to allow others to access this device.
        // Power up the device.
        //
        DeviceData->DevicePowerState = PowerDeviceD0;
        SET_NEW_PNP_STATE(DeviceData, Started);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Here we shut down the device and give up and unmap any resources
        // we acquired for the device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);
        status = STATUS_SUCCESS;
        break;


    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // No reason here why we can't stop the device.
        // If there were a reason we should speak now, because answering success
        // here may result in a stop device irp.
        //

        SET_NEW_PNP_STATE(DeviceData, StopPending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The stop was canceled.  Whatever state we set, or resources we put
        // on hold in anticipation of the forthcoming STOP device IRP should be
        // put back to normal.  Someone, in the long list of concerned parties,
        // has failed the stop device query.
        //

        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if someone
        // above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS;// We must not fail this IRP.
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // Check to see whether the device can be removed safely.
        // If not fail this request. This is the last opportunity
        // to do so.
        //
        if (DeviceData->ToasterInterfaceRefCount){
            //
            // Somebody is still using our interface.
            // We must fail remove.
            //
            status = STATUS_UNSUCCESSFUL;
            break;
        }

        SET_NEW_PNP_STATE(DeviceData, RemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // Clean up a remove that did not go through.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS; // We must not fail this IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // We should stop all access to the device and relinquish all the
        // resources. Let's just mark that it happened and we will do
        // the cleanup later in IRP_MN_REMOVE_DEVICE.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // Present is set to true when the pdo is exposed via PlugIn IOCTL.
        // It is set to FALSE when a UnPlug IOCTL is received.
        // We will delete the PDO only after we have reported to the
        // Plug and Play manager that it's missing.
        //

        if (DeviceData->ReportedMissing) {
            PFDO_DEVICE_DATA fdoData;

            SET_NEW_PNP_STATE(DeviceData, Deleted);

            //
            // Remove the PDO from the list and decrement the count of PDO.
            // Don't forget to synchronize access to the FDO data.
            // If the parent FDO is deleted before child PDOs, the ParentFdo
            // pointer will be NULL. This could happen if the child PDO
            // is in a SurpriseRemovePending state when the parent FDO
            // is removed.
            //

            if (DeviceData->ParentFdo) {
                fdoData = FDO_FROM_PDO(DeviceData);
                ExAcquireFastMutex (&fdoData->Mutex);
                RemoveEntryList (&DeviceData->Link);
                fdoData->NumPDOs--;
                ExReleaseFastMutex (&fdoData->Mutex);
            }
            //
            // Free up resources associated with PDO and delete it.
            //
            status = Bus_DestroyPdo(DeviceObject, DeviceData);
            break;

        }
        if (DeviceData->Present) {
            //
            // When the device is disabled, the PDO transitions from
            // RemovePending to NotStarted. We shouldn't delete
            // the PDO because a) the device is still present on the bus,
            // b) we haven't reported missing to the PnP manager.
            //

            SET_NEW_PNP_STATE(DeviceData, NotStarted);
            status = STATUS_SUCCESS;
        } else {
            ASSERT(DeviceData->Present);
            status = STATUS_SUCCESS;
        }
        break;

    case IRP_MN_QUERY_CAPABILITIES:

        //
        // Return the capabilities of a device, such as whether the device
        // can be locked or ejected..etc
        //

        status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_ID:

        // Query the IDs of the device

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                ("\tQueryId Type: %s\n",
                DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)));

        status = Bus_PDO_QueryDeviceId(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_TEXT:

        status = Bus_PDO_QueryDeviceText(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCES:

        status = Bus_PDO_QueryResources(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:

        status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_BUS_INFORMATION:

        status = Bus_PDO_QueryBusInformation(DeviceData, Irp);

        break;

    case IRP_MN_DEVICE_USAGE_NOTIFICATION:

        //
        // OPTIONAL for bus drivers.
        // This bus drivers any of the bus's descendants
        // (child device, child of a child device, etc.) do not
        // contain a memory file namely paging file, dump file,
        // or hibernation file. So we  fail this Irp.
        //

        status = STATUS_UNSUCCESSFUL;
        break;

    case IRP_MN_EJECT:

        //
        // For the device to be ejected, the device must be in the D3
        // device power state (off) and must be unlocked
        // (if the device supports locking). Any driver that returns success
        // for this IRP must wait until the device has been ejected before
        // completing the IRP.
        //
        DeviceData->Present = FALSE;

        status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_INTERFACE:
        //
        // This request enables a driver to export a direct-call
        // interface to other drivers. A bus driver that exports
        // an interface must handle this request for its child
        // devices (child PDOs).
        //
        status = Bus_PDO_QueryInterface(DeviceData, Irp);
        break;

    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP to a device
        // stack so filter and function drivers can adjust the
        // resources required by the device, if appropriate.
        //

        //break;

    //case IRP_MN_QUERY_PNP_DEVICE_STATE:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP after the drivers for
        // a device return success from the IRP_MN_START_DEVICE
        // request. The PnP Manager also sends this IRP when a
        // driver for the device calls IoInvalidateDeviceState.
        //

        // break;

    //case IRP_MN_READ_CONFIG:
    //case IRP_MN_WRITE_CONFIG:

        //
        // Bus drivers for buses with configuration space must handle
        // this request for their child devices. Our devices don't
        // have a config space.
        //

        // break;

    //case IRP_MN_SET_LOCK:

        //
        // Our device is not a lockable device
        // so we don't support this Irp.
        //

        // break;

    default:

        //
        //Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,("\t Not handled\n"));
        // For PnP requests to the PDO that we do not understand we should
        // return the IRP WITHOUT setting the status or information fields.
        // These fields may have already been set by a filter (eg acpi).
        status = Irp->IoStatus.Status;

        break;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}
Ejemplo n.º 3
0
NTSTATUS
Bus_PDO_QueryDeviceCaps(
    __in PPDO_DEVICE_DATA     DeviceData,
    __in  PIRP   Irp )
/*++

Routine Description:

    When a device is enumerated, but before the function and
    filter drivers are loaded for the device, the PnP Manager
    sends an IRP_MN_QUERY_CAPABILITIES request to the parent
    bus driver for the device. The bus driver must set any
    relevant values in the DEVICE_CAPABILITIES structure and
    return it to the PnP Manager.

Arguments:

    DeviceData - Pointer to the PDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT STATUS

--*/
{

    PIO_STACK_LOCATION      stack;
    PDEVICE_CAPABILITIES    deviceCapabilities;
    DEVICE_CAPABILITIES     parentCapabilities;
    NTSTATUS                status;

    PAGED_CODE ();

    stack = IoGetCurrentIrpStackLocation (Irp);

    //
    // Get the packet.
    //
    deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;

    //
    // Set the capabilities.
    //

    if (deviceCapabilities->Version != 1 ||
            deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
    {
       return STATUS_UNSUCCESSFUL;
    }

    //
    // Get the device capabilities of the parent
    //
    status = Bus_GetDeviceCapabilities(
        FDO_FROM_PDO(DeviceData)->NextLowerDriver, &parentCapabilities);
    if (!NT_SUCCESS(status)) {

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tQueryDeviceCaps failed\n"));
        return status;

    }

    //
    // The entries in the DeviceState array are based on the capabilities
    // of the parent devnode. These entries signify the highest-powered
    // state that the device can support for the corresponding system
    // state. A driver can specify a lower (less-powered) state than the
    // bus driver.  For eg: Suppose the toaster bus controller supports
    // D0, D2, and D3; and the Toaster Device supports D0, D1, D2, and D3.
    // Following the above rule, the device cannot specify D1 as one of
    // it's power state. A driver can make the rules more restrictive
    // but cannot loosen them.
    // First copy the parent's S to D state mapping
    //

    RtlCopyMemory(
        deviceCapabilities->DeviceState,
        parentCapabilities.DeviceState,
        (PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE)
        );

    //
    // Adjust the caps to what your device supports.
    // Our device just supports D0 and D3.
    //

    deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping1] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD1;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping2] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;

    if (deviceCapabilities->DeviceState[PowerSystemSleeping3] != PowerDeviceD0)
        deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;

    // We can wake the system from D1
    deviceCapabilities->DeviceWake = PowerDeviceD1;

    //
    // Specifies whether the device hardware supports the D1 and D2
    // power state. Set these bits explicitly.
    //

    deviceCapabilities->DeviceD1 = TRUE; // Yes we can
    deviceCapabilities->DeviceD2 = FALSE;

    //
    // Specifies whether the device can respond to an external wake
    // signal while in the D0, D1, D2, and D3 state.
    // Set these bits explicitly.
    //

    deviceCapabilities->WakeFromD0 = FALSE;
    deviceCapabilities->WakeFromD1 = TRUE; //Yes we can
    deviceCapabilities->WakeFromD2 = FALSE;
    deviceCapabilities->WakeFromD3 = FALSE;


    // We have no latencies

    deviceCapabilities->D1Latency = 0;
    deviceCapabilities->D2Latency = 0;
    deviceCapabilities->D3Latency = 0;

    // Ejection supported

    deviceCapabilities->EjectSupported = TRUE;

    //
    // This flag specifies whether the device's hardware is disabled.
    // The PnP Manager only checks this bit right after the device is
    // enumerated. Once the device is started, this bit is ignored.
    //
    deviceCapabilities->HardwareDisabled = FALSE;

    //
    // Out simulated device can be physically removed.
    //
    deviceCapabilities->Removable = TRUE;
    //
    // Setting it to TURE prevents the warning dialog from appearing
    // whenever the device is surprise removed.
    //
    deviceCapabilities->SurpriseRemovalOK = TRUE;

    // We don't support system-wide unique IDs.

    deviceCapabilities->UniqueID = FALSE;

    //
    // Specify whether the Device Manager should suppress all
    // installation pop-ups except required pop-ups such as
    // "no compatible drivers found."
    //

    deviceCapabilities->SilentInstall = FALSE;

    //
    // Specifies an address indicating where the device is located
    // on its underlying bus. The interpretation of this number is
    // bus-specific. If the address is unknown or the bus driver
    // does not support an address, the bus driver leaves this
    // member at its default value of 0xFFFFFFFF. In this example
    // the location address is same as instance id.
    //

    deviceCapabilities->Address = DeviceData->SerialNo;

    //
    // UINumber specifies a number associated with the device that can
    // be displayed in the user interface.
    //
    deviceCapabilities->UINumber = DeviceData->SerialNo;

    return STATUS_SUCCESS;

}