📄 pnp.c
字号:
/*++
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 + -