⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pnp.c

📁 虚拟Scsi Disk源程序 版权归原作者
💻 C
📖 第 1 页 / 共 3 页
字号:
// pnp.c
//
// Generated by C DriverWizard 3.2.0 (Build 2485)
// Requires DDK Only
// File created on 5/18/2005
//

#include "pch.h"
#ifdef VSCSIDISK_WMI_TRACE
#include "pnp.tmh"
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////
//  VScsiDiskPnpDispatch
//      Dispatch routine to handle PnP requests
//
//  Arguments:
//      IN  DeviceObject
//              pointer to our device object
//
//      IN  Irp
//              pointer to the PnP IRP
//
//  Return Value:
//      NT status code
//
NTSTATUS VScsiDiskPnpDispatch(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
{
    PVSCSIDISK_DEVICE_EXTENSION    deviceExtension;
    PIO_STACK_LOCATION              irpStack;
    NTSTATUS                        status;
    PDEVICE_CAPABILITIES            deviceCapabilities;
    ULONG                           requestCount;
    ULONG                           index;
    PPNP_DEVICE_STATE               deviceState;
    PVSCSIDISK_PDO_DEVICE_EXTENSION       pdoExtension;
    PLIST_ENTRY                     listEntry;
    PDEVICE_RELATIONS               oldDeviceRelations;
    PDEVICE_RELATIONS               newDeviceRelations;
    ULONG                           pdoCount;
    ULONG                           oldCount;
    POWER_STATE                     powerState;

    VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);
    
    // check if the IRP is for PDO
    if (VScsiDiskIsPdo(DeviceObject))
    {
        return VScsiDiskPdoPnpDispatch(DeviceObject, Irp);
    }
	VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"fdo");
    VScsiDiskDumpIrp(Irp);

    // Get our device extension from the device object
    deviceExtension = (PVSCSIDISK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // Get our current IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Make sure we can accept IRPs
    if (!VScsiDiskAcquireRemoveLock(deviceExtension))
    {
        status = STATUS_NO_SUCH_DEVICE;

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

        VScsiDiskDebugPrint(DBG_PNP, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

        return status;
    }

    switch (irpStack->MinorFunction) 
    {
    case IRP_MN_START_DEVICE:

        // The device stack must be started from the bottom up.  
        // So, we send the IRP down the stack and wait so that 
        // all devices below ours have started before we process 
        // this IRP and start ourselves.
        status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);
        if (!NT_SUCCESS(status))
        {
            // Someone below us failed to start, so just complete with error
            break;
        }

        // Lower drivers have finished their start operation, so now
        // we process ours.

        // Start is an implicit power-up so 
        // we set our device power state accordingly 
        deviceExtension->DevicePowerState = PowerDeviceD0;
        powerState.DeviceState = deviceExtension->DevicePowerState;

        PoSetPowerState(deviceExtension->DeviceObject, DevicePowerState, powerState);

        status = VScsiDiskGetDeviceCapabilities(deviceExtension);
        if (!NT_SUCCESS(status))
        {
            VScsiDiskFreeResources(deviceExtension);
            break;
        }

        status = VScsiDiskStartDevice(deviceExtension, Irp);
        if (!NT_SUCCESS(status))
        {
            VScsiDiskFreeResources(deviceExtension);
            break;
        }

        // Update our PnP state
        deviceExtension->PnpState = PnpStateStarted;

        // restart any stalled queues
        VScsiDiskRestartQueues(deviceExtension);

        VScsiDiskCreatePdo(deviceExtension, g_Data.InstanceCount);
        break;

    case IRP_MN_QUERY_STOP_DEVICE:

        if (VScsiDiskIsStoppable(deviceExtension)) 
        {
            // Device is stoppable.

            // pause io request processing
            VScsiDiskStallQueues(deviceExtension);

            // Update our PnP state
            deviceExtension->PreviousPnpState = deviceExtension->PnpState;
            deviceExtension->PnpState = PnpStateStopPending;

            // We must set Irp->IoStatus.Status to STATUS_SUCCESS before
            // passing it down.
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation (Irp);
            status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);

            // Decrement the active I/O count
            VScsiDiskReleaseRemoveLock(deviceExtension);

            VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

            return status;
        }
        else
        {
            // device is not currently stoppable, fail the request
            status = STATUS_UNSUCCESSFUL;
        }

        break;

   case IRP_MN_CANCEL_STOP_DEVICE:

        // Send this IRP down and wait for it to come back,
        // restart our stall fifo,
        // and process all the previously queued up IRPs.

        // First check to see whether we received a query before this
        // cancel. This could happen if someone above us failed a query
        // and passed down the subsequent cancel.
        if (deviceExtension->PnpState == PnpStateStopPending) 
        {
            status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject,Irp);
            if (NT_SUCCESS(status))
            {
                // restore previous pnp state
                deviceExtension->PnpState = deviceExtension->PreviousPnpState;

                // restart the queues
                VScsiDiskRestartQueues(deviceExtension);
            } 
            else 
            {
                // Somebody below us failed the cancel
                // this is a fatal error.
                ASSERTMSG("Cancel stop failed!", FALSE);
                VScsiDiskDebugPrint(DBG_PNP, DBG_ERR, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
            }
        } 
        else 
        {
            // Spurious cancel so we just complete the request.
            status = STATUS_SUCCESS;
        }

        break;

    case IRP_MN_STOP_DEVICE:
        // Mark the device as stopped.
        deviceExtension->PnpState = PnpStateStopped;

        // release our resources
        VScsiDiskFreeResources(deviceExtension);

        // send the request down, and we are done
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);

        VScsiDiskReleaseRemoveLock(deviceExtension);

        VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

        return status;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        if (VScsiDiskIsRemovable(deviceExtension)) 
        {
            // pause io request processing
            VScsiDiskStallQueues(deviceExtension);

            // Update our PnP state
            deviceExtension->PreviousPnpState = deviceExtension->PnpState;
            deviceExtension->PnpState = PnpStateRemovePending;

            // Now just send the request down and we are done
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation (Irp);

            status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);

            // decrement the I/O count
            VScsiDiskReleaseRemoveLock(deviceExtension);

            VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

            return status;
        }
        else
        {
            // Our device is not removable, just fail the request
            status = STATUS_UNSUCCESSFUL;
        }

        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        // First check to see whether we have received a prior query
        // remove request. It could happen that we did not if
        // someone above us failed a query remove and passed down the
        // subsequent cancel remove request.
        if (PnpStateRemovePending == deviceExtension->PnpState)
        {
            status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);

            if (NT_SUCCESS(status))
            {
                // restore pnp state, since remove was canceled
                deviceExtension->PnpState = deviceExtension->PreviousPnpState;

                // restart the queues
                VScsiDiskRestartQueues(deviceExtension);
            }
            else
            {
                // Nobody can fail this IRP. This is a fatal error.
                ASSERTMSG("IRP_MN_CANCEL_REMOVE_DEVICE failed. Fatal error!", FALSE);

                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
            }
        }
        else
        {
            // Spurious cancel remove request so we just complete it
            status = STATUS_SUCCESS;
        }

        break;

   case IRP_MN_SURPRISE_REMOVAL:

        // The device has been unexpectedly removed from the machine
        // and is no longer available for I/O.
        // We must return device and memory resources,
        // disable interfaces. We will defer failing any outstanding
        // request to IRP_MN_REMOVE.

        // stall all the queues
        VScsiDiskStallQueues(deviceExtension);

        // flush pending io list
        VScsiDiskInvalidateIo(&deviceExtension->IoLock, STATUS_NO_SUCH_DEVICE);

        // update pnp state
        deviceExtension->PnpState = PnpStateSurpriseRemoved;
        
        ExAcquireFastMutex(&deviceExtension->PdoListLock);

        while (!IsListEmpty(&deviceExtension->PdoListHead))
        {
            listEntry = RemoveHeadList(&deviceExtension->PdoListHead);
            pdoExtension = CONTAINING_RECORD(listEntry, VSCSIDISK_PDO_DEVICE_EXTENSION, PdoListEntry);

            InitializeListHead(&pdoExtension->PdoListEntry);
            pdoExtension->ParentDeviceObject = NULL;
            pdoExtension->DeleteOnRemove = TRUE;
        }

        ExReleaseFastMutex(&deviceExtension->PdoListLock);

        // Return any resources acquired during device startup.
        VScsiDiskFreeResources(deviceExtension);

        // We must set Irp->IoStatus.Status to STATUS_SUCCESS before
        // passing it down.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -