📄 plugplay.cpp
字号:
// Plug and Play handlers for Generic driver
// Copyright (C) 1999 by Walter Oney
// All rights reserved
#include "stddcls.h"
#include "driver.h"
#include "GenericPower.h"
NTSTATUS DefaultPnpHandler(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleCancelRemove(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleCancelStop(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleQueryCapabilities(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleQueryRemove(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleQueryState(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleQueryStop(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleRemoveDevice(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleStartDevice(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleStopDevice(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleSurpriseRemoval(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleUsageNotification(PGENERIC_EXTENSION pdx, PIRP Irp);
NTSTATUS OnNotificationComplete(PDEVICE_OBJECT fdo, PIRP Irp, PGENERIC_EXTENSION pdx);
VOID AdjustDeviceCapabilities(PDEVICE_CAPABILITIES pdc);
VOID AdjustWakeCapabilities(PGENERIC_EXTENSION pdx, PDEVICE_CAPABILITIES pdc, DEVICE_POWER_STATE dstate);
VOID DeregisterInterface(PGENERIC_EXTENSION pdx, PINTERFACE_RECORD ifp);
VOID DeregisterAllInterfaces(PGENERIC_EXTENSION pdx);
VOID EnableAllInterfaces(PGENERIC_EXTENSION pdx, BOOLEAN enable);
PINTERFACE_RECORD FindInterfaceRecord(PGENERIC_EXTENSION pdx, const GUID* guid);
#if DBG
VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list);
static char* statenames[] = {
"STOPPED",
"WORKING",
"PENDINGSTOP",
"PENDINGREMOVE",
"SURPRISEREMOVED",
"REMOVED",
};
static char* sname[] = {
"PowerSystemUnspecified",
"PowerSystemWorking",
"PowerSystemSleeping1",
"PowerSystemSleeping2",
"PowerSystemSleeping3",
"PowerSystemHibernate",
"PowerSystemShutdown",
};
static char* dname[] = {
"PowerDeviceUnspecified",
"PowerDeviceD0",
"PowerDeviceD1",
"PowerDeviceD2",
"PowerDeviceD3",
};
#endif
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
GENERICAPI NTSTATUS GENERIC_EXPORT GenericDispatchPnp(PGENERIC_EXTENSION pdx, PIRP Irp)
{ // GenericDispatchPnp
PAGED_CODE();
NTSTATUS status = STATUS_SUCCESS;
if (pdx->RemoveLock && !NT_SUCCESS(status = IoAcquireRemoveLock(pdx->RemoveLock, Irp)))
return CompleteRequest(Irp, status);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(stack->MajorFunction == IRP_MJ_PNP);
static NTSTATUS (*fcntab[])(PGENERIC_EXTENSION pdx, 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
DefaultPnpHandler, // 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
HandleQueryState, // IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
HandleUsageNotification,// IRP_MN_DEVICE_USAGE_NOTIFICATION
HandleSurpriseRemoval, // IRP_MN_SURPRISE_REMOVAL
};
ULONG fcn = stack->MinorFunction;
if (fcn >= arraysize(fcntab))
{ // unknown function
status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
if (pdx->RemoveLock)
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(("%s - PNP Request (%s)\n", pdx->DebugName, fcnname[fcn]));
#endif // DBG
status = (*fcntab[fcn])(pdx, Irp);
if (fcn != IRP_MN_REMOVE_DEVICE && pdx->RemoveLock)
IoReleaseRemoveLock(pdx->RemoveLock, Irp);
return status;
} // GenericDispatchPnp
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
GENERICAPI NTSTATUS GENERIC_EXPORT GenericDeregisterInterface(PGENERIC_EXTENSION pdx, const GUID* guid)
{ // GenericDeregisterInterface
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
NTSTATUS status;
KeEnterCriticalRegion();
KeWaitForSingleObject(&pdx->iflock, Executive, KernelMode, FALSE, NULL);
PINTERFACE_RECORD ifp = FindInterfaceRecord(pdx, guid);
if (ifp)
{
DeregisterInterface(pdx, ifp);
status = STATUS_SUCCESS;
}
else
status = STATUS_INVALID_PARAMETER;
KeSetEvent(&pdx->iflock, EVENT_INCREMENT, FALSE);
KeLeaveCriticalRegion();
return status;
} // GenericDeregisterInterface
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
GENERICAPI NTSTATUS GENERIC_EXPORT GenericEnableInterface(PGENERIC_EXTENSION pdx, const GUID* guid, BOOLEAN enable)
{ // GenericEnableInterface
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
NTSTATUS status;
KeEnterCriticalRegion();
KeWaitForSingleObject(&pdx->iflock, Executive, KernelMode, FALSE, NULL);
PINTERFACE_RECORD ifp = FindInterfaceRecord(pdx, guid);
if (ifp)
{ // enable/disable this interface
if (ifp->enabled != enable)
IoSetDeviceInterfaceState(&ifp->linkname, enable);
ifp->enabled = enable;
status = STATUS_SUCCESS;
} // enable/disable this interface
else
status = STATUS_INVALID_PARAMETER;
KeSetEvent(&pdx->iflock, EVENT_INCREMENT, FALSE);
KeLeaveCriticalRegion();
return status;
} // GenericEnableInterface
///////////////////////////////////////////////////////////////////////////////
// GenericGetDeviceCapabilities (added 2.0) returns the device capabilties.
// If necessary, it retrieves them.
#pragma LOCKEDCODE
GENERICAPI PDEVICE_CAPABILITIES GENERIC_EXPORT GenericGetDeviceCapabilities(PGENERIC_EXTENSION pdx)
{ // GenericGetDeviceCapabilities
// If necessary, ask the bus driver for this device's capabilities. We must be
// at PASSIVE_LEVEL to do this (requirement for sending the IRP).
if (!pdx->GotCapabilities)
{ // fetch capabilities
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return NULL;
PDEVICE_CAPABILITIES pdc = (PDEVICE_CAPABILITIES) ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
if (!pdc)
return NULL;
RtlZeroMemory(pdc, sizeof(*pdc));
pdc->Size = sizeof(*pdc);
pdc->Version = 1;
pdc->Address = -1;
pdc->UINumber = -1;
KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IO_STATUS_BLOCK iosb;
PDEVICE_OBJECT tdo = IoGetAttachedDeviceReference(pdx->Pdo);
PIRP Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, tdo, NULL, 0, NULL, &event, &iosb);
if (!Irp)
return NULL;
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
stack->Parameters.DeviceCapabilities.Capabilities = pdc;
NTSTATUS status = IoCallDriver(tdo, Irp);
if (status == STATUS_PENDING)
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ExFreePool(pdc);
ObDereferenceObject(tdo);
} // fetch capabilities
return &pdx->devcaps;
} // GenericGetDeviceCapabilities
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
GENERICAPI NTSTATUS GENERIC_EXPORT GenericRegisterInterface(PGENERIC_EXTENSION pdx, const GUID* guid)
{ // GenericRegisterInterface
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
NTSTATUS status;
KeEnterCriticalRegion();
KeWaitForSingleObject(&pdx->iflock, Executive, KernelMode, FALSE, NULL);
PINTERFACE_RECORD ifp = FindInterfaceRecord(pdx, guid);
if (ifp)
status = STATUS_INVALID_PARAMETER;
else
{ // register new interface
ifp = (PINTERFACE_RECORD) ExAllocatePool(NonPagedPool, sizeof(INTERFACE_RECORD));
if (ifp)
{ // initialize new interface record
status = IoRegisterDeviceInterface(pdx->Pdo, guid, NULL, &ifp->linkname);
if (NT_SUCCESS(status))
{ // interface registered
ifp->guid = *guid;
ifp->enabled = FALSE;
InsertHeadList(&pdx->iflist, &ifp->list);
} // interface registered
else
ExFreePool(ifp);
} // initialize new interface record
else
status = STATUS_INSUFFICIENT_RESOURCES;
} // register new interface
KeSetEvent(&pdx->iflock, EVENT_INCREMENT, FALSE);
KeLeaveCriticalRegion();
return status;
} // GenericRegisterInterface
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
GENERICAPI VOID GENERIC_EXPORT GenericSetDeviceState(PGENERIC_EXTENSION pdx, PNP_DEVICE_STATE pnpstate)
{ // GenericSetDeviceState
pdx->pnpstatemask = (pnpstate ^ pdx->pnpstate); // mask for things that changed
pdx->pnpstate |= pnpstate;
// Inform PnP manager that our state has changed.
IoInvalidateDeviceState(pdx->Pdo);
} // GenericSetDeviceState
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// AdjustDeviceCapabilities corrects the reported device capabilities to
// workaround the fact that many back-level bus drivers simply don't report
// them correctly. Cf. toaster.sys sample in the DDK and talk given by
// Adrian Oney (no relation) at WinHEC 2002.
#pragma PAGEDCODE
__inline SYSTEM_POWER_STATE& operator++(SYSTEM_POWER_STATE& ss) {ss = (SYSTEM_POWER_STATE) (ss + 1); return ss;}
__inline SYSTEM_POWER_STATE& operator--(SYSTEM_POWER_STATE& ss) {ss = (SYSTEM_POWER_STATE) (ss - 1); return ss;}
VOID AdjustDeviceCapabilities(PGENERIC_EXTENSION pdx, PDEVICE_CAPABILITIES pdc)
{ // AdjustDeviceCapabilities
// Make sure that the device state for S0 is D0
if (pdc->DeviceState[PowerSystemWorking] != PowerDeviceD0)
{
KdPrint(("%s - DeviceState[PowerSystemWorking] is D%d instead of D0!\n", pdx->DebugName, pdc->DeviceState[PowerSystemWorking] - 1));
pdc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
}
// Check for silly value of SystemWake
if (pdc->SystemWake > PowerSystemHibernate)
{
KdPrint(("%s - SystemWake has the silly value %s\n", pdx->DebugName, sname[pdc->SystemWake]));
}
// Adjust power capabilities to compensate for bus driver written to
// WDM 1.0 spec. First infer D1 and D2 capabilities from S->D state map.
for (SYSTEM_POWER_STATE sstate = PowerSystemSleeping1; sstate <= PowerSystemHibernate; ++sstate)
{ // for each S-state
if (pdc->DeviceState[sstate] == PowerDeviceD1 && !pdc->DeviceD1)
{
KdPrint(("%s - Inferring DeviceD1 from DeviceState[%s]\n", pdx->DebugName, sname[sstate]));
pdc->DeviceD1 = TRUE;
}
if (pdc->DeviceState[sstate] == PowerDeviceD2 && !pdc->DeviceD2)
{
KdPrint(("%s - Inferring DeviceD2 from DeviceState[%s]\n", pdx->DebugName, sname[sstate]));
pdc->DeviceD2 = TRUE;
}
} // for each S-state
// Set the WakeFromDx flags based on the reported DeviceWake state and
// on the D-state corresponding to the reported SystemWake state
AdjustWakeCapabilities(pdx, pdc, pdc->DeviceWake);
if (pdc->SystemWake != PowerSystemUnspecified)
AdjustWakeCapabilities(pdx, pdc, pdc->DeviceState[pdc->SystemWake]);
// Make sure the device state for S5 is D3. Do this after adjusting wakeup capabilities
// because USBHUB uncritically assumes that a device can be in D2 from S1 through SystemWakeup.
// So if SystemWakeup happens to be S5 because of some ACPI mistake, changing the device
// state entry too soon would cause us to pick D3 as the DeviceWake value, which is more wrong
// than what we were starting with...
if (pdc->DeviceState[PowerSystemShutdown] != PowerDeviceD3)
{
KdPrint(("%s - DeviceState[PowerSystemShutdown] is D%d instead of D3!\n", pdx->DebugName, pdc->DeviceState[PowerSystemShutdown] - 1));
pdc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
}
// Find the deepest D-state from which this device can wake the system
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -