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

📄 plugplay.cpp

📁 WDM驱动程序的范例程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:


	DEVICE_POWER_STATE wakestate = PowerDeviceUnspecified;	// assume no wakeup capability



	if (pdc->WakeFromD3)

		wakestate = PowerDeviceD3;

	else if (pdc->WakeFromD2)

		wakestate = PowerDeviceD2;

	else if (pdc->WakeFromD1)

		wakestate = PowerDeviceD1;

	else if (pdc->WakeFromD0)

		wakestate = PowerDeviceD0;



	if (pdc->DeviceWake != wakestate)

		{

		KdPrint(("%s - DeviceWake is %s, but should be %s\n", pdx->DebugName, dname[pdc->DeviceWake], dname[wakestate]));

		pdc->DeviceWake = wakestate;

		}



	// If SystemWake is specified, the corresponding D-state had better be at

	// least as powered as the state we just discovered, or else there's a bug

	// in our bus driver. It may just be that we got a bogus SystemWake value,

	// so don't do anything about it.



	if (pdc->SystemWake != PowerSystemUnspecified)

		{

		if (pdc->DeviceState[pdc->SystemWake] > wakestate)

			{

			KdPrint(("%s - DeviceState[SystemWake] is less powered than minimum wake state (%s)!\n", pdx->DebugName, dname[wakestate]));

			}

		}



	// If SystemWake wasn't specified, infer it from the S->D state map by

	// finding the lowest S-state whose D-state is at least as powered as the

	// lowest D-state from which wakeup is possible (I think I got that right...)



	else if (wakestate != PowerDeviceD0 && wakestate != PowerDeviceUnspecified)

		{						// infer system wake state

		for (sstate = PowerSystemSleeping3; sstate >= PowerSystemWorking; --sstate)

			{					// for each S-state

			if (pdc->DeviceState[sstate] != PowerDeviceUnspecified

				&& pdc->DeviceState[sstate] <= wakestate)

				{				// found the S-state

				KdPrint(("%s - Inferring that wakeup from S%d state possible\n", pdx->DebugName, sstate - 1));

				pdc->SystemWake = sstate;

				break;

				}				// found the S-state

			}					// for each S-state

		}						// infer system wake state

	}							// AdjustDeviceCapabilities



///////////////////////////////////////////////////////////////////////////////

// AdjustWakeCapabilities adjusts the wakeup capabilities for a device.	



VOID AdjustWakeCapabilities(PGENERIC_EXTENSION pdx, PDEVICE_CAPABILITIES pdc, DEVICE_POWER_STATE dstate)

	{							// AdjustWakeCapabilities

	switch (dstate)

		{						// select on D-state

	case PowerDeviceUnspecified:

		break;

	case PowerDeviceD0:

		if (!pdc->WakeFromD0)

			KdPrint(("%s - AdjustWakeCapabilities Inferring WakeFromD0\n", pdx->DebugName));

		pdc->WakeFromD0 = TRUE;

		break;

	case PowerDeviceD1:

		if (!pdc->WakeFromD1)

			KdPrint(("%s - AdjustWakeCapabilities Inferring WakeFromD1\n", pdx->DebugName));

		if (!pdc->DeviceD1)

			KdPrint(("%s - AdjustWakeCapabilities Inferring DeviceD1\n", pdx->DebugName));

		pdc->DeviceD1 = TRUE;

		pdc->WakeFromD1 = TRUE;

		break;

	case PowerDeviceD2:

		if (!pdc->WakeFromD2)

			KdPrint(("%s - AdjustWakeCapabilities Inferring WakeFromD2\n", pdx->DebugName));

		if (!pdc->DeviceD2)

			KdPrint(("%s - AdjustWakeCapabilities Inferring DeviceD2\n", pdx->DebugName));

		pdc->DeviceD2 = TRUE;

		pdc->WakeFromD2 = TRUE;

		break;

	case PowerDeviceD3:

		if (!pdc->WakeFromD3)

			KdPrint(("%s - AdjustWakeCapabilities Inferring WakeFromD3\n", pdx->DebugName));

		pdc->WakeFromD3 = TRUE;

		break;

	default:

		ASSERT(FALSE);

		}						// select on D-state

	}							// AdjustWakeCapabilities



///////////////////////////////////////////////////////////////////////////////



VOID CallStopDevice(PGENERIC_EXTENSION pdx)

	{							// CallStopDevice

	GenericWakeupControl(pdx, CancelWaitWake);

	BOOLEAN oktouch = pdx->HardwareWorking;

	pdx->HardwareWorking = FALSE;

	(*pdx->StopDevice)(pdx->DeviceObject, oktouch);

	}							// CallStopDevice



///////////////////////////////////////////////////////////////////////////////



VOID CallRemoveDevice(PGENERIC_EXTENSION pdx)

	{							// CallRemoveDevice

	(*pdx->RemoveDevice)(pdx->DeviceObject);

	}							// CallRemoveDevice



///////////////////////////////////////////////////////////////////////////////



NTSTATUS DefaultPnpHandler(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// DefaultPnpHandler

	IoSkipCurrentIrpStackLocation(Irp);

	return IoCallDriver(pdx->LowerDeviceObject, Irp);

	}							// DefaultPnpHandler



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



VOID DeregisterAllInterfaces(PGENERIC_EXTENSION pdx)

	{							// DeregisterAllInterfaces

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	

	KeEnterCriticalRegion();

	KeWaitForSingleObject(&pdx->iflock, Executive, KernelMode, FALSE, NULL);



	while (!IsListEmpty(&pdx->iflist))

		{						// for each interface

		PLIST_ENTRY list = RemoveHeadList(&pdx->iflist);

		PINTERFACE_RECORD ifp = CONTAINING_RECORD(list, INTERFACE_RECORD, list);

		DeregisterInterface(pdx, ifp);

		}						// for each interface



	KeSetEvent(&pdx->iflock, EVENT_INCREMENT, FALSE);

	KeLeaveCriticalRegion();

	}							// DeregisterAllInterfaces



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



VOID DeregisterInterface(PGENERIC_EXTENSION pdx, PINTERFACE_RECORD ifp)

	{							// DeregisterInterface

	if (ifp->enabled)

		IoSetDeviceInterfaceState(&ifp->linkname, FALSE);

	RtlFreeUnicodeString(&ifp->linkname);

	RemoveEntryList(&ifp->list);

	ExFreePool(ifp);

	}							// DeregisterInterface



///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE



VOID EnableAllInterfaces(PGENERIC_EXTENSION pdx, BOOLEAN enable)

	{							// EnableAllInterfaces

	for (PLIST_ENTRY list = pdx->iflist.Flink; list != &pdx->iflist; list = list->Flink)

		{						// search for specified interface record

		PINTERFACE_RECORD ifp = CONTAINING_RECORD(list, INTERFACE_RECORD, list);

		if (ifp->enabled != enable)

			IoSetDeviceInterfaceState(&ifp->linkname, enable);

		ifp->enabled = enable;

		}

	}							// EnableAllInterfaces



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



PINTERFACE_RECORD FindInterfaceRecord(PGENERIC_EXTENSION pdx, const GUID* guid)

	{							// FindInterfaceRecord

	PAGED_CODE();



	for (PLIST_ENTRY list = pdx->iflist.Flink; list != &pdx->iflist; list = list->Flink)

		{						// search for specified interface record

		PINTERFACE_RECORD ifp = CONTAINING_RECORD(list, INTERFACE_RECORD, list);

		if (ifp->guid == *guid)

			return ifp;

		}

	return NULL;

	}							// FindInterfaceRecord



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleCancelRemove(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleCancelRemove

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE);

	Irp->IoStatus.Status = STATUS_SUCCESS;	// flag that we handled this IRP



	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(pdx, Irp); // wait for lower layers

		if (NT_SUCCESS(status))

			{					// completed successfully

			KdPrint(("%s - To %s from PENDINGREMOVE\n", pdx->DebugName, statenames[pdx->prevstate]));

			RestartAllRequests(pdx->queues, pdx->nqueues, pdx->DeviceObject);

			GenericWakeupControl(pdx, ManageWaitWake);	// reissue wait-wake if necessary

			}					// completed successfully

		else

			KdPrint(("%s - Status %8.8lX returned by PDO for IRP_MN_CANCEL_REMOVE_DEVICE", pdx->DebugName, status));



		return CompleteRequest(Irp, status);

		}						// we succeeded earlier query

	

	return DefaultPnpHandler(pdx, Irp); // unexpected cancel

	}							// HandleCancelRemove



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleCancelStop(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleCancelStop

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE);

	Irp->IoStatus.Status = STATUS_SUCCESS;	// flag that we handled this IRP



	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(pdx, Irp); // wait for lower layers

		if (NT_SUCCESS(status))

			{					// completed successfully

			KdPrint(("%s - To WORKING from PENDINGSTOP\n", pdx->DebugName));

			pdx->state = WORKING;

			RestartAllRequests(pdx->queues, pdx->nqueues, pdx->DeviceObject);

			GenericWakeupControl(pdx, ManageWaitWake);	// reissue wait-wake if necessary

			}					// completed successfully

		else

			KdPrint(("%s - Status %8.8lX returned by PDO for IRP_MN_CANCEL_STOP_DEVICE", pdx->DebugName, status));

		

		return CompleteRequest(Irp, status);

		}						// we succeeded earlier query



	return DefaultPnpHandler(pdx, Irp); // unexpected cancel

	}							// HandleCancelStop



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleQueryCapabilities(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleQueryCapabilities

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_QUERY_CAPABILITIES);



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	PDEVICE_CAPABILITIES pdc = stack->Parameters.DeviceCapabilities.Capabilities;



	// Check to be sure we know how to handle this version of the capabilities structure



	if (pdc->Version < 1)

		return DefaultPnpHandler(pdx, Irp);



	NTSTATUS status = ForwardAndWait(pdx, Irp);

	if (NT_SUCCESS(status))

		{						// IRP succeeded

		stack = IoGetCurrentIrpStackLocation(Irp);

		pdc = stack->Parameters.DeviceCapabilities.Capabilities;

		if (pdx->Flags & GENERIC_SURPRISE_REMOVAL_OK)

			pdc->SurpriseRemovalOK = TRUE;

		AdjustDeviceCapabilities(pdx, pdc);	// compensate for bus driver shortcoming

		pdx->devcaps = *pdc;	// save capabilities for whoever needs to see them

		pdx->GotCapabilities = TRUE;	// flag for GenericGetDeviceCapabilities

		GenericWakeupControl(pdx, ManageWaitWake);	// in case capabilities now allow WAIT_WAKE

		}						// IRP succeeded



	return CompleteRequest(Irp, status);

	}							// HandleQueryCapabilities



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleQueryRemove(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleQueryRemove

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE);

	Irp->IoStatus.Status = STATUS_SUCCESS;	// flag that we handled this IRP



	if (pdx->state == WORKING)

		{						// currently working



	#ifdef _X86_



		// Win98 doesn't check for open handles before allowing a remove to proceed,

		// and it may deadlock in IoReleaseRemoveLockAndWait if handles are still

		// open.



		if (win98 && pdx->DeviceObject->ReferenceCount)

			{

			KdPrint(("%s - Failing removal query due to open handles\n", pdx->DebugName));

			return CompleteRequest(Irp, STATUS_DEVICE_BUSY);

			}



	#endif



		// See if it's okay to remove this device. The test includes asking the client

		// driver. Then stall the queue for the duration of the query. The TOASTER sample

		// in the DDK drains the queue here instead of stalling it, by the way.



		if (!OkayToRemove(pdx))

			return CompleteRequest(Irp, STATUS_UNSUCCESSFUL); // can't remove because busy



		StallAllRequests(pdx->queues, pdx->nqueues);

		if (pdx->FlushPendingIo)

			(*pdx->FlushPendingIo)(pdx->DeviceObject, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE, PowerDeviceUnspecified, PowerDeviceUnspecified);

		WaitForCurrentIrps(pdx->queues, pdx->nqueues);

		GenericWakeupControl(pdx, CancelWaitWake);	// cancel any pending wait-wake



		KdPrint(("%s - To PENDINGREMOVE from %s\n", pdx->DebugName, statenames[pdx->state]));

		}						// currently working



	// Save current state for restoration if the query gets cancelled.

	// (We can now be stopped or working)



	pdx->prevstate = pdx->state;

	pdx->state = PENDINGREMOVE;

	return DefaultPnpHandler(pdx, Irp);

	}							// HandleQueryRemove



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleQueryState(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleQueryState

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE);



	// Note that you can't use sizeof in a #if expression, so it's not possible to use

	// conditional compilation to choose between 32- and 64-bit exchanges in the

	// following statement. If the size of a PNP_DEVICE_STATE changes to be bigger than

	// 32 bits, therefore, you have to change this by hand. The ASSERT will alert you to

	// the problem...



	PNP_DEVICE_STATE mask = InterlockedExchange((PLONG) &pdx->pnpstatemask, 0);

	ASSERT(sizeof(PNP_DEVICE_STATE) == sizeof(LONG));



	if (mask)

		{						// some status flags have changed

		Irp->IoStatus.Status = STATUS_SUCCESS; // indicate we've handled this IRP

		Irp->IoStatus.Information &= ~(ULONG_PTR) mask; // clear all changed flags

		Irp->IoStatus.Information |= pdx->pnpstate & mask; // set all flags that were changed to "1"

		}						// some status flags have changed



	// DDK doc says you handle this IRP on the way down, but TOASTER handles

	// it on the way up. It shouldn't matter, because you're not supposed to

	// overstore the result you find already in IoStatus.Information.



	return DefaultPnpHandler(pdx, Irp);

	}							// HandleQueryState



///////////////////////////////////////////////////////////////////////////////



NTSTATUS HandleQueryStop(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleQueryStop

	ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_QUERY_STOP_DEVICE);

	Irp->IoStatus.Status = STATUS_SUCCESS;	// flag that we handled this IRP

	

	// Boot devices may get this query before they even start, so check to see

	// if we're in the WORKING state before doing anything.



	if (pdx->state != WORKING)

		return DefaultPnpHandler(pdx, Irp);



	// See if it will be okay to stop the device right now. This test includes

	// asking the client driver via a callback routine.



	if (!OkayToStop(pdx))

		return CompleteRequest(Irp, STATUS_UNSUCCESSFUL);



	// Stall the request queue and wait for the current IRP (if any) to finish

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -