📄 pnp.c
字号:
/*++
Copyright (c) 2005 Changzhi Zhou All Rights Reserved
Module Name:
pnp.c
Abstract:
This module works for the handles Plug&Play dispatch.
Environment:
Kernel mode
Revision History:
Changzhi Zhou Dec 20 2004
--*/
#include <ntddk.h>
#include <initguid.h>
#include "main.h"
#include "tdiclient.h"
#include "..\inc\wdmioctl.h"
NTSTATUS
SamplePnpDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these the driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
KEVENT event;
KIRQL oldIrql;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
DebugPrint(("Sample %s IRP:0x%x \n", PnPMinorFunctionString(irpStack->MinorFunction), Irp));
if ( Removed == deviceExtension->DevicePnPState) {
status = STATUS_DELETE_PENDING;
return CompleteRequest(Irp, status, 0 );
}
status = STATUS_SUCCESS;
SampleIoIncrement( deviceExtension );
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
status = PnpStartDevice( DeviceObject, Irp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
status = PnpQueryStopDevice( DeviceObject, Irp );
return status;
case IRP_MN_CANCEL_STOP_DEVICE:
status = PnpCancelStopDevice( DeviceObject, Irp );
break;
case IRP_MN_STOP_DEVICE:
SET_NEW_PNP_STATE(deviceExtension, Stopped);
SampleIoDecrement( deviceExtension );
status = DefaultPnpHandler( DeviceObject, Irp );
return status;
case IRP_MN_QUERY_REMOVE_DEVICE:
status = PnpQueryRemoveDevice( DeviceObject, Irp );
return status;
case IRP_MN_CANCEL_REMOVE_DEVICE:
status = PnpCancelRemoveDevice( DeviceObject, Irp );
break;
case IRP_MN_REMOVE_DEVICE:
status = PnpRemoveDevice( DeviceObject, Irp );
return status;
case IRP_MN_SURPRISE_REMOVAL:
status = PnpSurpriseRemoval( DeviceObject, Irp );
SampleIoDecrement( deviceExtension );
return status;
case IRP_MN_QUERY_CAPABILITIES:
return PnpQueryCapabilities( DeviceObject, Irp );
default:
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);
SampleIoDecrement(deviceExtension);
return status;
}
CompleteRequest( Irp, status, 0 );
SampleIoDecrement(deviceExtension);
return status;
}
NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
/*++
Routine Description:
Pnp handler to IRP_MN_START_DEVICE.
Arguments:
deviceExtension - pointer to a device object extension.
Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
Return Value:
NT status code.
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
status = ForwardAndWait( DeviceObject, Irp);
if ( !NT_SUCCESS( status ) )
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
irpStack = IoGetCurrentIrpStackLocation( Irp );
//status = CreateWorkThread( deviceExtension );
// Open transport address, set clienteventhandler and initialize recvContext.
status = InitializeConnection( deviceExtension );
if( NT_SUCCESS( status ) && NT_SUCCESS( Irp->IoStatus.Status ) ){
status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, TRUE );
if( !NT_SUCCESS( status )){
DebugPrint(( "StartDevice: IoSetDeviceInterfaceState failed (%x)\n", status ));
}
SET_NEW_PNP_STATE( deviceExtension, Working );
}
return status;
}
NTSTATUS
PnpQueryStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Pnp handler to IRP_MN_QUERY_STOP_DEVICE.
Arguments:
deviceExtension - pointer to a device object extension.
Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
Return Value:
NT status code.
--*/
{
KIRQL oldIrql;
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// If we can stop the device, we need to set the QueueState to
// PendingStop so further requests will be queued.
//
SET_NEW_PNP_STATE(deviceExtension, PendingStop);
SampleIoDecrement( deviceExtension );
KeWaitForSingleObject(&deviceExtension->StopEvent,
Executive,
KernelMode,
FALSE,
NULL);
status = DefaultPnpHandler( DeviceObject, Irp );
return status;
}
NTSTATUS
PnpCancelStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Pnp handler to IRP_MN_CANCEL_STOP_DEVICE.
Arguments:
deviceExtension - pointer to a device object extension.
Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
Return Value:
NT status code.
--*/
{
KIRQL oldIrql;
KEVENT event;
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// Send this IRP down and wait for it to come back.
// Set the QueueState flag to AllowRequests,
// and process all the previously queued up IRPs.
//
//
// 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(PendingStop == deviceExtension->DevicePnPState) {
status = ForwardAndWait( DeviceObject, Irp );
if(NT_SUCCESS( status )) {
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
}
}
else {
status = STATUS_SUCCESS;
}
return status;
}
NTSTATUS
PnpQueryRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Pnp handler to IRP_MN_QUERY_REMOVE_DEVICE.
Arguments:
deviceExtension - pointer to a device object extension.
Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
Return Value:
NT status code.
--*/
{
#define WDM_DELAY_VALUE (ULONG)(-1 * 20000 * 1000) // 2s
KIRQL oldIrql;
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
LARGE_INTEGER deltaTime;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
SampleIoDecrement( deviceExtension );
deltaTime.LowPart = WDM_DELAY_VALUE;
deltaTime.HighPart = -1;
//
// Wait deltaTime for all the requests to be completed.
// If timeout, that means some Irps haven't be completed.
// So we will simply return Device_Busy and not pass down to lower driver.
//
status = KeWaitForSingleObject(&deviceExtension->StopEvent,
Executive,
KernelMode,
FALSE,
&deltaTime);
if( STATUS_TIMEOUT == status )
return CompleteRequest( Irp, STATUS_DEVICE_BUSY, 0 );
//
// If we can allow removal of the device, we should set the QueueState
// to HoldRequests so further requests will be queued. This is required
// so that we can process queued up requests in cancel-remove just in
// case somebody else in the stack fails the query-remove.
//
SET_NEW_PNP_STATE(deviceExtension, PendingRemove );
status = DefaultPnpHandler( DeviceObject, Irp );
return status;
}
NTSTATUS
PnpCancelRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Pnp handler to IRP_MN_CANEL_REMOVE_DEVICE.
Arguments:
deviceExtension - pointer to a device object extension.
Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
Return Value:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -