📄 plugplaypdo.cpp
字号:
// Plug and Play handlers for child device PDOs
// Copyright (C) 1999 by Walter Oney
// All rights reserved
#include "stddcls.h"
#include "driver.h"
#include <initguid.h>
#include "suballoc.h"
static NTSTATUS HandleQueryId(PDEVICE_OBJECT pdo, PIRP Irp);
static NTSTATUS HandleQueryInterface(PDEVICE_OBJECT pdo, PIRP Irp);
static NTSTATUS HandleQueryRelations(PDEVICE_OBJECT pdo, PIRP Irp);
static NTSTATUS IgnoreRequest(PDEVICE_OBJECT pdo, PIRP Irp);
static NTSTATUS OnRepeaterComplete(PDEVICE_OBJECT tdo, PIRP subirp, PVOID needsvote);
static NTSTATUS RepeatRequest(PDEVICE_OBJECT pdo, PIRP Irp);
static NTSTATUS SucceedRequest(PDEVICE_OBJECT pdo, PIRP Irp);
static VOID SuballocInterfaceReference(PDEVICE_EXTENSION fdx);
static VOID SuballocInterfaceDereference(PDEVICE_EXTENSION fdx);
static NTSTATUS GetChildResources(PDEVICE_EXTENSION fdx, PDEVICE_OBJECT pdo, PCM_RESOURCE_LIST* raw, PCM_RESOURCE_LIST* translated);
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
NTSTATUS DispatchPnpPdo(IN PDEVICE_OBJECT pdo, IN PIRP Irp)
{ // DispatchPnpPdo
PAGED_CODE();
PPDO_EXTENSION pdx = (PPDO_EXTENSION) pdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(stack->MajorFunction == IRP_MJ_PNP);
ASSERT(pdx->flags & ISPDO);
NTSTATUS status;
static NTSTATUS (*fcntab[])(IN PDEVICE_OBJECT pdo, IN PIRP Irp) = {
SucceedRequest, // IRP_MN_START_DEVICE
SucceedRequest, // IRP_MN_QUERY_REMOVE_DEVICE
SucceedRequest, // IRP_MN_REMOVE_DEVICE
SucceedRequest, // IRP_MN_CANCEL_REMOVE_DEVICE
SucceedRequest, // IRP_MN_STOP_DEVICE
SucceedRequest, // IRP_MN_QUERY_STOP_DEVICE
SucceedRequest, // IRP_MN_CANCEL_STOP_DEVICE
HandleQueryRelations, // IRP_MN_QUERY_DEVICE_RELATIONS
HandleQueryInterface, // IRP_MN_QUERY_INTERFACE
RepeatRequest, // IRP_MN_QUERY_CAPABILITIES
SucceedRequest, // IRP_MN_QUERY_RESOURCES
SucceedRequest, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
IgnoreRequest, // IRP_MN_QUERY_DEVICE_TEXT
SucceedRequest, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
SucceedRequest, //
RepeatRequest, // IRP_MN_READ_CONFIG
RepeatRequest, // IRP_MN_WRITE_CONFIG
RepeatRequest, // IRP_MN_EJECT
RepeatRequest, // IRP_MN_SET_LOCK
HandleQueryId, // IRP_MN_QUERY_ID
RepeatRequest, // IRP_MN_QUERY_PNP_DEVICE_STATE
RepeatRequest, // IRP_MN_QUERY_BUS_INFORMATION
RepeatRequest, // IRP_MN_DEVICE_USAGE_NOTIFICATION
SucceedRequest, // IRP_MN_SURPRISE_REMOVAL
RepeatRequest, // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
};
ULONG fcn = stack->MinorFunction;
if (fcn >= arraysize(fcntab))
{ // unknown function
status = IgnoreRequest(pdo, Irp); // some function we don't know about
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",
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION",
};
KdPrint((DRIVERNAME " (PDO) - PNP Request (%s)\n", fcnname[fcn]));
#endif // DBG
status = (*fcntab[fcn])(pdo, Irp);
return status;
} // DispatchPnp
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
static NTSTATUS HandleQueryId(PDEVICE_OBJECT pdo, PIRP Irp)
{ // HandleQueryId
PPDO_EXTENSION pdx = (PPDO_EXTENSION) pdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PWCHAR idstring;
switch (stack->Parameters.QueryId.IdType)
{ // select based on id type
case BusQueryInstanceID:
idstring = L"0000";
break;
// For the device ID, we need to supply an enumerator name plus a device identifer.
// The enumerator name is something you should choose to be unique, which is why
// I used the name of the driver in this instance.
case BusQueryDeviceID:
idstring = (pdx->flags & CHILDTYPEA) ? LDRIVERNAME L"\\*WCO1104" : LDRIVERNAME L"\\*WCO1105";
break;
case BusQueryHardwareIDs:
idstring = (pdx->flags & CHILDTYPEA) ? L"*WCO1104" : L"*WCO1105";
break;
case BusQueryCompatibleIDs:
default:
return CompleteRequest(Irp, STATUS_NOT_SUPPORTED, 0);
} // select based on id type
ULONG nchars = wcslen(idstring);
ULONG size = (nchars + 2) * sizeof(WCHAR);
PWCHAR id = (PWCHAR) ExAllocatePool(PagedPool, size);
if (!id)
return CompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
wcscpy(id, idstring);
id[nchars+1] = 0; // extra null terminator
return CompleteRequest(Irp, STATUS_SUCCESS, (ULONG_PTR) id);
} // HandleQueryId
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
static NTSTATUS HandleQueryInterface(PDEVICE_OBJECT pdo, PIRP Irp)
{ // HandleQueryInterface
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
// See if caller is asking for the resource suballocation interface. If not,
// repeat this request in the parent device stack. Even though the DDK doc says
// you shouldn't do this, there is no other way for a child-stack driver to get
// at one of the interfaces implemented by a parent-stack driver. And, yes, it
// is true that the parent stack can't be removed until all references to such
// interfaces are released, but that's not especially fascinating news.
if (*stack->Parameters.QueryInterface.InterfaceType != GUID_RESOURCE_SUBALLOCATE_STANDARD)
return RepeatRequest(pdo, Irp);
// Determine what version of the interface to return.
USHORT version = RESOURCE_SUBALLOCATE_STANDARD_VERSION; // assume current version
if (version > stack->Parameters.QueryInterface.Version)
version = stack->Parameters.QueryInterface.Version; // negotiate down to requested version
if (version == 0)
return CompleteRequest(Irp, Irp->IoStatus.Status); // fail -- no compatible version supported
PPDO_EXTENSION pdx = (PPDO_EXTENSION) pdo->DeviceExtension;
PDEVICE_OBJECT fdo = pdx->Fdo;
PDEVICE_EXTENSION fdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Fill in caller's interface descriptor structure
switch (version)
{ // fill in specified version of interface structure
case 1:
{ // version 1
if (stack->Parameters.QueryInterface.Size < sizeof(RESOURCE_SUBALLOCATE_STANDARD))
return CompleteRequest(Irp, STATUS_INVALID_PARAMETER); // not big enough
PRESOURCE_SUBALLOCATE_STANDARD ifp = (PRESOURCE_SUBALLOCATE_STANDARD) stack->Parameters.QueryInterface.Interface;
ifp->Size = sizeof(RESOURCE_SUBALLOCATE_STANDARD);
ifp->Version = 1;
ifp->Context = (PVOID) fdx;
ifp->InterfaceReference = (PINTERFACE_REFERENCE) SuballocInterfaceReference;
ifp->InterfaceDereference = (PINTERFACE_DEREFERENCE) SuballocInterfaceDereference;
ifp->GetResources = (PGETRESOURCES) GetChildResources;
break;
} // version 1
default:
ASSERT(FALSE); // version negotiation above went awry
return CompleteRequest(Irp, Irp->IoStatus.Status);
} // fill in specified version of interface structure
SuballocInterfaceReference(fdx);
return CompleteRequest(Irp, STATUS_SUCCESS, 0);
} // HandleQueryInterface
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
static NTSTATUS HandleQueryRelations(PDEVICE_OBJECT pdo, PIRP Irp)
{ // HandleQueryRelations
PDEVICE_RELATIONS oldrel = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
PDEVICE_RELATIONS newrel = NULL;
NTSTATUS status = Irp->IoStatus.Status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
if (stack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -