📄 plugplayfdo.cpp
字号:
// Plug and Play handlers for main device FDO in MULFUNC driver sample
// Copyright (C) 1999 by Walter Oney
// All rights reserved
#include "stddcls.h"
#include "driver.h"
static NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleCancelRemove(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleCancelStop(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleQueryRelations(PDEVICE_OBJECT fdo, PIRP Irp);
static NTSTATUS HandleQueryRemove(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleQueryStop(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
static NTSTATUS StartDevice(PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated);
static VOID StopDevice(PDEVICE_OBJECT fdo, BOOLEAN oktouch);
#if DBG
static VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list);
static char* statenames[] = {
"STOPPED",
"WORKING",
"PENDINGSTOP",
"PENDINGREMOVE",
"SURPRISEREMOVED",
"REMOVED",
};
#endif
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
NTSTATUS DispatchPnpFdo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // DispatchPnpFdo
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(stack->MajorFunction == IRP_MJ_PNP);
static NTSTATUS (*fcntab[])(IN PDEVICE_OBJECT fdo, IN PIRP Irp) = {
HandleStartDevice, // IRP_MN_START_DEVICE
HandleQueryRemove, // IRP_MN_QUERY_REMOVE_DEVICE
HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE
HandleCancelRemove, // IRP_MN_CANCEL_REMOVE_DEVICE
HandleStopDevice, // IRP_MN_STOP_DEVICE
HandleQueryStop, // IRP_MN_QUERY_STOP_DEVICE
HandleCancelStop, // IRP_MN_CANCEL_STOP_DEVICE
HandleQueryRelations, // IRP_MN_QUERY_DEVICE_RELATIONS
DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
HandleQueryCapabilities,// IRP_MN_QUERY_CAPABILITIES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
DefaultPnpHandler, //
DefaultPnpHandler, // IRP_MN_READ_CONFIG
DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
DefaultPnpHandler, // IRP_MN_EJECT
DefaultPnpHandler, // IRP_MN_SET_LOCK
DefaultPnpHandler, // IRP_MN_QUERY_ID
DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
HandleSurpriseRemoval, // IRP_MN_SURPRISE_REMOVAL
};
ULONG fcn = stack->MinorFunction;
if (fcn >= arraysize(fcntab))
{ // unknown function
status = DefaultPnpHandler(fdo, Irp); // some function we don't know about
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // unknown function
#if DBG
static char* fcnname[] = {
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
};
KdPrint((DRIVERNAME " (FDO) - PNP Request (%s)\n", fcnname[fcn]));
#endif // DBG
status = (*fcntab[fcn])(fdo, Irp);
if (fcn != IRP_MN_REMOVE_DEVICE)
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchPnp
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CreateChild(PDEVICE_EXTENSION pdx, ULONG flags, PDEVICE_OBJECT* ppdo)
{ // CreateChild
NTSTATUS status;
PDEVICE_OBJECT child;
status = IoCreateDevice(pdx->DriverObject, sizeof(PDO_EXTENSION), NULL,
FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &child);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - IoCreateDevice (child) failed - %X\n", status));
return status;
}
PPDO_EXTENSION px = (PPDO_EXTENSION) child->DeviceExtension;
px->flags = ISPDO | flags;
px->DeviceObject = child;
px->Fdo = pdx->DeviceObject;
child->Flags &= ~DO_DEVICE_INITIALIZING;
*ppdo = child;
return STATUS_SUCCESS;
} // CreateChild
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // DefaultPnpHandler
IoSkipCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
return IoCallDriver(pdx->LowerDeviceObject, Irp);
} // DefaultPnpHandler
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleCancelRemove(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleCancelRemove
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
if (pdx->state == PENDINGREMOVE)
{ // we succeeded earlier query
// Lower-level drivers are presumably in the pending-remove state as
// well, so we need to tell them that the remove has been cancelled
// before we start sending IRPs down to them.
NTSTATUS status = ForwardAndWait(fdo, Irp); // wait for lower layers
if (NT_SUCCESS(status))
{ // completed successfully
KdPrint((DRIVERNAME " - To %s from PENDINGREMOVE\n", statenames[pdx->prevstate]));
if ((pdx->state = pdx->prevstate) == WORKING)
{ // back to working state
} // back to working state
} // completed successfully
else
KdPrint((DRIVERNAME " - Status %8.8lX returned by PDO for IRP_MN_CANCEL_REMOVE_DEVICE", status));
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
} // we succeeded earlier query
return DefaultPnpHandler(fdo, Irp); // unexpected cancel
} // HandleCancelRemove
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleCancelStop(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleCancelStop
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
if (pdx->state == PENDINGSTOP)
{ // we succeeded earlier query
// Lower level drivers are presumably in the pending-stop state as
// well, so we need to tell them that the stop has been cancelled
// before we start sending IRPs down to them.
NTSTATUS status = ForwardAndWait(fdo, Irp); // wait for lower layers
if (NT_SUCCESS(status))
{ // completed successfully
KdPrint((DRIVERNAME " - To WORKING from PENDINGSTOP\n"));
pdx->state = WORKING;
} // completed successfully
else
KdPrint((DRIVERNAME " - Status %8.8lX returned by PDO for IRP_MN_CANCEL_STOP_DEVICE", status));
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
} // we succeeded earlier query
return DefaultPnpHandler(fdo, Irp); // unexpected cancel
} // HandleCancelStop
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleQueryCapabilities
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_CAPABILITIES pdc = stack->Parameters.DeviceCapabilities.Capabilities;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Check to be sure we know how to handle this version of the capabilities structure
if (pdc->Version < 1)
return DefaultPnpHandler(fdo, Irp);
NTSTATUS status = ForwardAndWait(fdo, Irp);
if (NT_SUCCESS(status))
{ // IRP succeeded
stack = IoGetCurrentIrpStackLocation(Irp);
pdc = stack->Parameters.DeviceCapabilities.Capabilities;
// TODO Modify any capabilities that must be set on the way back up
pdx->devcaps = *pdc; // save capabilities for whoever needs to see them
} // IRP succeeded
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
} // HandleQueryCapabilities
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleQueryRelations(PDEVICE_OBJECT fdo, PIRP Irp)
{ // HandleQueryRelations
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
return DefaultPnpHandler(fdo, Irp);
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_RELATIONS oldrel = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
PDEVICE_RELATIONS newrel;
if (oldrel)
{ // extend existing list
ULONG size = sizeof(DEVICE_RELATIONS) + (oldrel->Count + 1) * sizeof(PDEVICE_OBJECT);
newrel = (PDEVICE_RELATIONS) ExAllocatePool(PagedPool, size);
if (newrel)
{ // copy & extend
RtlCopyMemory(newrel, oldrel, size - 2 * sizeof(PDEVICE_OBJECT));
ExFreePool(oldrel);
} // copy & extend
} // extend existing list
else
{ // create new list
newrel = (PDEVICE_RELATIONS) ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT));
newrel->Count = 0;
} // create new list
if (newrel)
{ // build new list
if (pdx->ChildA)
{
ObReferenceObject(pdx->ChildA);
newrel->Objects[newrel->Count++] = pdx->ChildA;
}
if (pdx->ChildB)
{
ObReferenceObject(pdx->ChildB);
newrel->Objects[newrel->Count++] = pdx->ChildB;
}
Irp->IoStatus.Information = (ULONG_PTR) newrel;
} // build new list
else
status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = status;
return DefaultPnpHandler(fdo, Irp);
} // HandleQueryRelations
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleQueryRemove(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleQueryRemove
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -