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

📄 powerfdo.cpp

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



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

		// SubPowerUpComplete is the action for a AsyncNotify event in the

		// SubPowerUpPending state. This should be called from PoCompletionRoutine.

		// We can also get here from SendDeviceIrp to avoid the Win98 no-D-IRP bug,

		// in which case we don't want to alter "status" from its current value.



		case SubPowerUpComplete:

			{					// SubPowerUpComplete

			if (status == -1)

				status = STATUS_SUCCESS; // don't actually care, since called from PoCompletionRoutine

			action = CompleteMainIrp;

			continue;

			}					// SubPowerUpComplete



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

		// SubPowerDownComplete is the action for a AsyncNotify event in the

		// SubPowerDownPending state. This should be called from PoCompletionRoutine.

		// We can also get here from SendDeviceIrp to avoid the Win98 no-D-IRP bug,

		// in which case we don't want to alter "status" from its current value.



		case SubPowerDownComplete:

			{					// SubPowerDownComplete

			if (status == -1)

				status = STATUS_SUCCESS; // don't actually care, since called from PoCompletionRoutine



			if (NT_SUCCESS(ctx->status))

				{

				SETSTATE(SysPowerDownPending);

				action = ForwardMainIrp;

				}

			else

				action = CompleteMainIrp; // D-state IRP failed, so fail S-state IRP too

			

			continue;

			}					// SubPowerDownComplete



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

		// DevPowerUpComplete is the action for a MainIrpComplete event in the

		// DevPowerUpPending state. This should be called from MainCompletionRoutine

		// when a device power-up IRP finishes in the lower layers.



		case DevPowerUpComplete:

			{					// DevPowerUpComplete



			// If this IRP failed, or if we're just dealing with a query, we're done.



			if (!NT_SUCCESS(ctx->status) || stack->MinorFunction != IRP_MN_SET_POWER)

				{

				action = CompleteMainIrp;

				continue;

				}



			status = STATUS_MORE_PROCESSING_REQUIRED; // defer completion of the main IRP while we restore context



			ctx->oldpower = pdx->devpower;

			pdx->devpower = stack->Parameters.Power.State.DeviceState;



			KdPrint((DRIVERNAME " - Now in %s\n", devstate[pdx->devpower]));



			action = ContextRestoreComplete;

			continue;

			}					// DevPowerUpComplete



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

		// ContextRestoreComplete is the last action for a device set power up

		// operation. It's ordinarily reached when GenericSaveRestoreComplete

		// signals a MainIrpComplete event from the ContextRestorePending state.

		// It can also be reached directly from DevPowerUpComplete when there is

		// no context restore function.



		case ContextRestoreComplete:

			{					// ContextRestoreComplete

			if (event == AsyncNotify)

				status = STATUS_SUCCESS; // doesn't actually matter

			action = CompleteMainIrp;



			// If the device IRP failed, just go ahead and let it complete. If we've

			// successfully resumed to a sleeping state (> D0), skip restarting the

			// substantive IRP queue and complete the IRP as well.



			if (!NT_SUCCESS(ctx->status) || pdx->devpower != PowerDeviceD0)

				continue;



			ASSERT(stack->MinorFunction == IRP_MN_SET_POWER); // query should have gone directly to CompleteMainIrp from DevPowerUpComplete



			continue;

			}					// ContextRestoreComplete



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

		// SaveContext initiates a context save operation if necessary. This will

		// be the second action for a new device set-power IRP.



		case SaveContext:

			{					// SaveContext

			ASSERT(stack->MinorFunction == IRP_MN_SET_POWER);

			DEVICE_POWER_STATE devpower = stack->Parameters.Power.State.DeviceState;



			action = ContextSaveComplete;

			continue;

			}					// SaveContext



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

		// ContextSaveComplete is the action for an AsyncNotify event in the

		// ContextSavePending state. It should be entered from GenericSaveRestoreComplete,

		// which in turn should have been called by the client driver when its

		// context save operation finished. It can also be entered directly from

		// SaveContext when there is no context save routine.



		case ContextSaveComplete:

			{					// ContextSaveComplete

			if (event == AsyncNotify)

				status = STATUS_SUCCESS;	// doesn't actually matter in this case



			SETSTATE(DevPowerDownPending);

			action = ForwardMainIrp;



			ASSERT(stack);

			DEVICE_POWER_STATE devpower = stack->Parameters.Power.State.DeviceState;

			if (devpower <= pdx->devpower)

				continue;		// no actual change in device power



			ASSERT(stack->MinorFunction == IRP_MN_SET_POWER);



			pdx->devpower = devpower;



			KdPrint((DRIVERNAME " - Now in %s\n", devstate[pdx->devpower]));



			continue;

			}					// ContextSaveComplete



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

		// DevQueryUpComplete is the action for a MainIrpComplete event in the

		// DevQueryUpPending state. This should be called by MainCompletionRoutine

		// when a device query-power-up IRP completes. We don't expect to ever get this

		// kind of a query, by the way, but we should handle it nontheless.



		case DevQueryUpComplete:

			{					// DevQueryUpComplete

			if (NT_SUCCESS(ctx->status))

				{				// ask client if change okay



				// TODO replace the FALSE immediately below with some non-blocking test

				// to see if it's okay to restore power. It would be very unusual to

				// say "no". In making the test, pdx->devpower is the current power

				// state and stack->Parameters.Power.State.DeviceState is the

				// proposed new state.



				if (FALSE)

					ctx->status = STATUS_UNSUCCESSFUL; // fail the query

				}				// ask client if change okay



			action = CompleteMainIrp;

			continue;

			}					// DevQueryUpComplete



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

		// DevQueryDown is the second action (after TriageNewIrp) for a device

		// query-power that specifies less than or equal to the current device

		// power state.



		case DevQueryDown:

			{					// DevQueryDown

			DEVICE_POWER_STATE devpower = stack->Parameters.Power.State.DeviceState;



			// TODO replace the FALSE immediately below with some non-blocking test

			// to see if it's okay to remove power. In making the test, pdx->devpower

			// is the current power state and devpower is the proposed new state.



			if (devpower > pdx->devpower && FALSE)

				{				// fail the query

				ctx->status = STATUS_UNSUCCESSFUL;

				action = DevQueryDownComplete;

				continue;

				}				// fail the query



			SETSTATE(DevQueryDownPending);

			action = ForwardMainIrp;

			continue;

			}					// DevQueryDown



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

		// DevQueryDownComplete is the action for a MainIrpComplete event in the

		// DevQueryDownPending state. It can be reached from MainCompletionRoutine

		// or directly from DevQueryDown.



		case DevQueryDownComplete:

			{					// DevQueryDownComplete



			action = CompleteMainIrp;

			continue;

			}					// DevQueryDownComplete



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

		// InvalidAction is the action for any unexpected event. It should never occur.



		case InvalidAction:

		default:

			ASSERT(FALSE);

			status = STATUS_UNSUCCESSFUL;

			break;

			}					// perform next action



		break;					// for cases that "break" from the switch

		}						// handle this event



	// Check to make sure the state got changed before we exit

		

	ASSERT(nextstate != originalstate);



	// Check to make sure a valid status will be returned



	ASSERT(status != -1);



	return status;

	}							// HandlePowerEvent



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



NTSTATUS MainCompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp, PPOWCONTEXT ctx)

	{							// MainCompletionRoutine

	ctx->status = Irp->IoStatus.Status;

	return HandlePowerEvent(ctx, MainIrpComplete);

	}							// MainCompletionRoutine



VOID PoCompletionRoutine(PDEVICE_OBJECT junk, UCHAR fcn, POWER_STATE state, PPOWCONTEXT ctx, PIO_STATUS_BLOCK pstatus)

	{							// PoCompletionRoutine

	ctx->status = pstatus->Status;

	HandlePowerEvent(ctx, AsyncNotify);

	}							// PoCompletionRoutine



VOID PassivePowerCall(PIRP Irp)

	{							// PassivePowerCall

	PoCallDriver(IoGetNextIrpStackLocation(Irp)->DeviceObject, Irp);

	}							// PassivePowerCall



NTSTATUS SafePoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp)

	{							// SafePoCallDriver



	// If running in Win2K, or if Win98 and already at PASSIVE_LEVEL, just call

	// PoCallDriver.



	if (!win98 || KeGetCurrentIrql() == PASSIVE_LEVEL)

		return PoCallDriver(DeviceObject, Irp);

	

	// Win98's PoCallDriver is the same as IoCallDriver, and it won't do anything to

	// present the IRP at passive level if we're currently above. Build a work queue

	// item in the DriverContext field of the IRP and queue the work item so we

	// can present the IRP properly. Boy, is this something we shouldn't have to

	// worry about!



	IoMarkIrpPending(Irp);		// be sure it's marked pending

	IoGetNextIrpStackLocation(Irp)->DeviceObject = DeviceObject; // so PassivePowerCall can find it



	// Note: The ExXxxWorkItem functions are deprecated for Win2K and WinXp but

	// okay for win98. This code only executes in Win98, so these should be okay



	#pragma warning(disable:4995)

	#pragma warning(disable:4996)



	PWORK_QUEUE_ITEM item = (PWORK_QUEUE_ITEM) Irp->Tail.Overlay.DriverContext;

	ExInitializeWorkItem(item, (PWORKER_THREAD_ROUTINE) PassivePowerCall, (PVOID) Irp);

	ExQueueWorkItem(item, DelayedWorkQueue);



	return STATUS_PENDING;

	}							// SafePoCallDriver



⌨️ 快捷键说明

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