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

📄 pnp.c

📁 一个简单实现windows游戏杆的驱动示例-hidgame
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1998 - 1999  Microsoft Corporation

Module Name:

    pnp.c

Abstract: This module contains PnP Start, Stop, Remove,
          Power dispatch routines and IRP cancel routine.

Environment:

    Kernel mode

--*/

#include "hidgame.h"

#ifdef ALLOC_PRAGMA
    #pragma alloc_text (PAGE, HGM_RemoveDevice)
    #pragma alloc_text (PAGE, HGM_PnP)
    #pragma alloc_text (PAGE, HGM_InitDevice)
    #pragma alloc_text (PAGE, HGM_GetResources)
    #pragma alloc_text (PAGE, HGM_Power)
#endif


/*****************************************************************************
 *
 *  @doc    INTERNAL
 *
 *  @func   NTSTATUS  | HGM_IncRequestCount |
 *
 *          Try to increment the request count but fail if the device is 
 *          being removed.
 *
 *  @parm   IN PDEVICE_EXTENSION | DeviceExtension |
 *
 *          Pointer to the device extension.
 *
 *  @rvalue STATUS_SUCCESS | success
 *  @rvalue STATUS_DELETE_PENDING | PnP IRP received after device was removed
 *
 *****************************************************************************/
NTSTATUS  EXTERNAL
    HGM_IncRequestCount
    (
    IN PDEVICE_EXTENSION DeviceExtension
    )
{
    NTSTATUS    ntStatus;

    InterlockedIncrement( &DeviceExtension->RequestCount );
    ASSERT( DeviceExtension->RequestCount > 0 );
    
    if( DeviceExtension->fRemoved )
    {
        /*
         *  PnP has already told us to remove the device so fail and make 
         *  sure that the event has been set.
         */
        if( 0 == InterlockedDecrement( &DeviceExtension->RequestCount ) ) 
        {
            KeSetEvent( &DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE );
        }
        ntStatus = STATUS_DELETE_PENDING;
    }
    else
    {
        ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}
    



/*****************************************************************************
 *
 *  @doc    INTERNAL
 *
 *  @func   VOID  | HGM_DecRequestCount |
 *
 *          Decrement the request count and set event if this is the last.
 *
 *  @parm   IN PDEVICE_EXTENSION | DeviceExtension |
 *
 *          Pointer to the device extension.
 *
 *****************************************************************************/
VOID EXTERNAL
    HGM_DecRequestCount
    (
    IN PDEVICE_EXTENSION DeviceExtension
    )
{
    LONG        LocalCount;

    LocalCount = InterlockedDecrement( &DeviceExtension->RequestCount );

    ASSERT( DeviceExtension->RequestCount >= 0 );
    
    if( LocalCount == 0 )
    {
        /*
         *  PnP has already told us to remove the device so the PnP remove 
         *  code should have set device as removed and should be waiting on
         *  the event.
         */
        ASSERT( DeviceExtension->fRemoved );
        KeSetEvent( &DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE );
    }

    return;
}
    

/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   VOID  | HGM_RemoveDevice |
 *
 *          FDO Remove routine 
 *
 *  @parm   IN PDEVICE_EXTENSION | DeviceExtension |
 *
 *          Pointer to the device extension.
 *
 *****************************************************************************/
VOID INTERNAL
    HGM_RemoveDevice
    (
    PDEVICE_EXTENSION DeviceExtension
    )
{
    if (DeviceExtension->fSurpriseRemoved) {
        return;
    }

    DeviceExtension->fSurpriseRemoved = TRUE;

    /*
     *  Acquire mutex before modifying the Global Linked list of devices
     */
    ExAcquireFastMutex (&Global.Mutex);
    
    /*
     * Remove this device from the linked list of devices
     */
    RemoveEntryList(&DeviceExtension->Link);
    
    /*
     *  Release the mutex
     */
    ExReleaseFastMutex (&Global.Mutex);
} /* HGM_RemoveDevice */

/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS  | HGM_PnP |
 *
 *          Plug and Play dispatch routine for this driver.
 *
 *  @parm   IN PDEVICE_OBJECT | DeviceObject |
 *
 *          Pointer to the device object.
 *
 *  @parm   IN PIRP | Irp |
 *
 *          Pointer to an I/O request packet.
 *
 *  @rvalue   STATUS_SUCCESS | success
 *  @rvalue   STATUS_DELETE_PENDING | PnP IRP received after device was removed
 *  @rvalue   ???   | Return from IoCallDriver() or HGM_InitDevice()
 *
 *****************************************************************************/
NTSTATUS  EXTERNAL
    HGM_PnP
    (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS ntStatus;
    PDEVICE_EXTENSION DeviceExtension;
    KEVENT            StartEvent;

    PAGED_CODE();

    HGM_DBGPRINT(FILE_PNP | HGM_FENTRY,\
                   ("HGM_PnP(DeviceObject=0x%x,Irp=0x%x)",\
                    DeviceObject, Irp ));
    /*
     * Get a pointer to the device extension
     */
    DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);

    ntStatus = HGM_IncRequestCount( DeviceExtension );
    if (!NT_SUCCESS (ntStatus))
    {
        /*
         * Someone sent us another plug and play IRP after removed
         */

        HGM_DBGPRINT(FILE_PNP | HGM_ERROR,\
                       ("HGM_PnP: PnP IRP after device was removed\n"));
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = ntStatus;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
    } else
    {
        PIO_STACK_LOCATION IrpStack;

        /*
         * Get a pointer to the current location in the Irp
         */
        IrpStack = IoGetCurrentIrpStackLocation (Irp);

        switch(IrpStack->MinorFunction)
        {
            case IRP_MN_START_DEVICE:

                HGM_DBGPRINT(FILE_PNP | HGM_BABBLE,\
                               ("HGM_Pnp: IRP_MN_START_DEVICE"));
                /*
                 * We cannot touch the device (send it any non pnp irps) until a
                 * start device has been passed down to the lower drivers.
                 */
                KeInitializeEvent(&StartEvent, NotificationEvent, FALSE);

                IoCopyCurrentIrpStackLocationToNext (Irp);
                IoSetCompletionRoutine (Irp, HGM_PnPComplete, &StartEvent, TRUE, TRUE, TRUE);
                ntStatus = IoCallDriver (GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);

                if( NT_SUCCESS(ntStatus ) )
                {
                    ntStatus = KeWaitForSingleObject
                               (
                               &StartEvent,
                               Executive,   /* Waiting for reason of a driver */
                               KernelMode,  /* Waiting in kernel mode         */
                               FALSE,       /* No allert                      */
                               NULL         /* No timeout                     */
                               );
                }

                if(NT_SUCCESS(ntStatus))
                {
                    ntStatus = Irp->IoStatus.Status;
                }

                if(NT_SUCCESS (ntStatus))
                {
                    /*
                     * As we are now back from our start device we can do work.
                     */
                    ntStatus = HGM_InitDevice (DeviceObject, Irp);
                } else
                {
                    HGM_DBGPRINT(FILE_PNP | HGM_ERROR,\
                                   ("HGM_Pnp: IRP_MN_START_DEVICE ntStatus =0x%x",\
                                    ntStatus));
                }


                DeviceExtension->fStarted = TRUE;

                /*
                 *      Return Status
                 */
                Irp->IoStatus.Information = 0;
                Irp->IoStatus.Status = ntStatus;
                IoCompleteRequest (Irp, IO_NO_INCREMENT);

                break;

            case IRP_MN_STOP_DEVICE:

                HGM_DBGPRINT(FILE_PNP | HGM_BABBLE,\
                               ("HGM_Pnp: IRP_MN_STOP_DEVICE"));
                /*
                 * After the start IRP has been sent to the lower driver object, the bus may
                 * NOT send any more IRPS down ``touch'' until another START has occured.
                 * Whatever access is required must be done before Irp passed on.
                 */

                DeviceExtension->fStarted = FALSE;

                /*
                 * We don't need a completion routine so fire and forget.
                 * Set the current stack location to the next stack location and
                 * call the next device object.
                 */

                IoSkipCurrentIrpStackLocation (Irp);
                ntStatus = IoCallDriver (GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
                break;

            case IRP_MN_SURPRISE_REMOVAL:
                HGM_DBGPRINT(FILE_PNP | HGM_BABBLE,\
                               ("HGM_Pnp: IRP_MN_SURPRISE_REMOVAL"));

                HGM_RemoveDevice(DeviceExtension);

                Irp->IoStatus.Status = STATUS_SUCCESS;
                IoSkipCurrentIrpStackLocation(Irp);
                ntStatus = IoCallDriver (GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);

                break;

            case IRP_MN_REMOVE_DEVICE:
                HGM_DBGPRINT(FILE_PNP | HGM_BABBLE,\
                               ("HGM_Pnp: IRP_MN_REMOVE_DEVICE"));

                /*
                 * The PlugPlay system has dictacted the removal of this device. We
                 * have no choice but to detach and delete the device object.
                 * (If we wanted to express an interest in preventing this removal,
                 * we should have filtered the query remove and query stop routines.)
                 * Note: we might receive a remove WITHOUT first receiving a stop.
                 */

                /*
                 *  Make sure we do not allow more IRPs to start touching the device
                 */
                DeviceExtension->fRemoved = TRUE;

                /*
                 * Stop the device without touching the hardware.
                 */
                HGM_RemoveDevice(DeviceExtension);

                /*
                 * Send on the remove IRP
                 */
                IoSkipCurrentIrpStackLocation (Irp);
                ntStatus = IoCallDriver (GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);


                /*
                 *  Remove this IRPs hold which should leave the initial 1 plus 
                 *  any other IRP holds.
                 */
                {
                    LONG RequestCount = InterlockedDecrement( &DeviceExtension->RequestCount );
                    ASSERT( RequestCount > 0 );
                }

                /*
                 *  If someone has already started, wait for them to finish
                 */
                if( InterlockedDecrement( &DeviceExtension->RequestCount ) > 0 )
                {
                    KeWaitForSingleObject( &DeviceExtension->RemoveEvent,
                        Executive, KernelMode, FALSE, NULL );
                }

                ntStatus = STATUS_SUCCESS;

                HGM_EXITPROC(FILE_IOCTL|HGM_FEXIT_STATUSOK, "HGM_PnP Exit 1", ntStatus);

                return ntStatus;

⌨️ 快捷键说明

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