⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plugplay.cpp

📁 Programming the Microsoft Windows driver model.2nd 随书光盘。内有很多作者送的实用工具和随书源码。WDM编程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -