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

📄 pnp.c

📁 一个简单的wdm驱动开发实例,可以大概看开发流程作为入门
💻 C
字号:
// pnp.c
//
// Generated by C DriverWizard 3.1.0 (Build 1722)
// Requires DDK Only
// File created on 1/23/2009
//

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

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSamplePnpDispatch
//      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 CharSamplePnpDispatch(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
{
    PCHARSAMPLE_DEVICE_EXTENSION    deviceExtension;
    PIO_STACK_LOCATION              irpStack;
    NTSTATUS                        status;
    PDEVICE_CAPABILITIES            deviceCapabilities;
    ULONG                           requestCount;
    ULONG                           index;
    PPNP_DEVICE_STATE               deviceState;

    CharSampleDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    CharSampleDumpIrp(Irp);

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

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

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

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

        CharSampleDebugPrint(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 = CharSampleSubmitIrpSync(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.

        status = CharSampleStartDevice(deviceExtension, Irp);
        if (!NT_SUCCESS(status))
        {
            CharSampleFreeResources(deviceExtension);
            break;
        }

        // Enable the device interface. 
        status = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, TRUE);
        if (!NT_SUCCESS(status))
        {
            CharSampleFreeResources(deviceExtension);
            break;
        }

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

        // restart any stalled queues
        CharSampleRestartQueues(deviceExtension);
        break;

    case IRP_MN_QUERY_STOP_DEVICE:

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

            // pause io request processing
            CharSampleStallQueues(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
            CharSampleReleaseRemoveLock(deviceExtension);

            CharSampleDebugPrint(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 = CharSampleSubmitIrpSync(deviceExtension->LowerDeviceObject,Irp);
            if (NT_SUCCESS(status))
            {
                // restore previous pnp state
                deviceExtension->PnpState = deviceExtension->PreviousPnpState;

                // restart the queues
                CharSampleRestartQueues(deviceExtension);
            } 
            else 
            {
                // Somebody below us failed the cancel
                // this is a fatal error.
                ASSERTMSG("Cancel stop failed!", FALSE);
                CharSampleDebugPrint(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
        CharSampleFreeResources(deviceExtension);

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

        CharSampleReleaseRemoveLock(deviceExtension);

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

        return status;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        if (CharSampleIsRemovable(deviceExtension)) 
        {
            // pause io request processing
            CharSampleStallQueues(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
            CharSampleReleaseRemoveLock(deviceExtension);

            CharSampleDebugPrint(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 = CharSampleSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);

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

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

                CharSampleDebugPrint(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
        CharSampleStallQueues(deviceExtension);

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

        // update pnp state
        deviceExtension->PnpState = PnpStateSurpriseRemoved;

        // disable our interface
        IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);

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

        // 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);

        // Adjust the active I/O count
        CharSampleReleaseRemoveLock(deviceExtension);

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

        return status;

   case IRP_MN_REMOVE_DEVICE:

        // The Plug & Play system has dictated the removal of this device.  We
        // have no choice but to detach and delete the device object.

        if (deviceExtension->PnpState != PnpStateSurpriseRemoved)
        {
            // flush pending io list
            CharSampleInvalidateIo(&deviceExtension->IoLock, STATUS_NO_SUCH_DEVICE);

            IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);

            CharSampleFreeResources(deviceExtension);
        }

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

        CharSampleReleaseRemoveLock(deviceExtension);
        CharSampleWaitForSafeRemove(deviceExtension);

        // Send the remove IRP down the stack.
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (deviceExtension->LowerDeviceObject, Irp);

        // Detach our device object from the device stack
        IoDetachDevice(deviceExtension->LowerDeviceObject);

        // free InterfaceName memory
        RtlFreeUnicodeString(&deviceExtension->InterfaceName);

        // attempt to delete our device object
        IoDeleteDevice(deviceExtension->DeviceObject);

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

        return status;

    case IRP_MN_QUERY_CAPABILITIES:

        // Check the device capabilities struct
        deviceCapabilities = 
            irpStack->Parameters.DeviceCapabilities.Capabilities;

        if (deviceCapabilities->Version != 1 ||
            deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
        {
            // We don't support this version. Fail the request
            break;
        }

        // Pass the IRP down
        status = CharSampleSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);

        // Lower drivers have finished their operation, so now
        // we can finish ours.
        if (NT_SUCCESS(status)) 
        {
            //*****************************************************************
            //*****************************************************************
            // TODO: Override the device capabilities 
            //       set by the underlying drivers here.
            //*****************************************************************
            //*****************************************************************
        }

        break;

    default:
        // Pass down any unknown requests.
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);

        // Adjust our active I/O count
        CharSampleReleaseRemoveLock(deviceExtension);

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

        return status;
    }

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

    // Adjust the active I/O count
    CharSampleReleaseRemoveLock(deviceExtension);

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

    return status;
}

⌨️ 快捷键说明

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