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

📄 plugplay.cpp

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


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

	if (pdx->FlushPendingIo)

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

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

	GenericWakeupControl(pdx, DisableWakeup);

 	

	pdx->state = PENDINGSTOP;

	return DefaultPnpHandler(pdx, Irp);

	}							// HandleQueryStop



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



NTSTATUS HandleRemoveDevice(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleRemoveDevice

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

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



	// Cancel any queued requests and start rejecting new ones



	AbortAllRequests(pdx->queues, pdx->nqueues, STATUS_DELETE_PENDING);

	AbortPendingIoctls(pdx, STATUS_DELETE_PENDING);

	GenericWakeupControl(pdx, DisableWakeup);



	// Disable all device interfaces that were registered through us. This

	// triggers PnP notifications that will allow apps to close their handles.



	DeregisterAllInterfaces(pdx);



	// Release I/O resources



	CallStopDevice(pdx);



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

	pdx->state = REMOVED;



	// Let lower-level drivers handle this request. Ignore whatever

	// result eventuates.



	NTSTATUS status = DefaultPnpHandler(pdx, Irp);



	// Wait for all claims against this device to vanish before removing

	// the device object

	

	if (pdx->RemoveLock)

		IoReleaseRemoveLockAndWait(pdx->RemoveLock, Irp);



	// Remove the device object



	CallRemoveDevice(pdx);



	// Cleanup our device extension



	CleanupGenericExtension(pdx);



	return status;				// lower-level completed IoStatus already

	}							// HandleRemoveDevice



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



NTSTATUS HandleStartDevice(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleStartDevice

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

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



	NTSTATUS status = ForwardAndWait(pdx, Irp);

	if (!NT_SUCCESS(status))

		return CompleteRequest(Irp, status);



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);



	PCM_PARTIAL_RESOURCE_LIST raw;

	if (stack->Parameters.StartDevice.AllocatedResources)

		raw = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;

	else

		raw = NULL;



	PCM_PARTIAL_RESOURCE_LIST translated;

	if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)

		translated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;

	else

		translated = NULL;



#if DBG

	if (raw)

		{

		KdPrint(("%s - Resources:\n", pdx->DebugName));

		ShowResources(raw);

		}

	if (translated)

		{

		KdPrint(("%s - Translated Resources:\n", pdx->DebugName));

		ShowResources(translated);

		}

#endif // DBG



	// Assume we are initially in the D0 state



	pdx->devpower = PowerDeviceD0;

	pdx->syspower = PowerSystemWorking;

	POWER_STATE foo;

	foo.DeviceState = PowerDeviceD0;

	PoSetPowerState(pdx->Pdo, DevicePowerState, foo);



	// Call client driver's StartDevice function to initialize the device for I/O



	status = (*pdx->StartDevice)(pdx->DeviceObject, raw, translated); 



	if (NT_SUCCESS(status))

		{						// started okay

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



		pdx->HardwareWorking = TRUE;



		// If idle detection constants were saved in the registry, register

		// this device for idle detection



		POWERINFO pi;

		if (NT_SUCCESS(GetPowerInfoFromRegistry(pdx, &pi)))

			ImplementPowerPolicy(pdx, &pi);



		// Enable all registered device interfaces



		EnableAllInterfaces(pdx, TRUE);



		// Release any stalled IRPs



		pdx->state = WORKING;

		AllowAllRequests(pdx->queues, pdx->nqueues); // in case we got a bogus STOP

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



		// If system wakeup is enabled, start a wait-wake IRP



		GenericWakeupControl(pdx, ManageWaitWake);

		}						// started okay



	return CompleteRequest(Irp, status);

	}							// HandleStartDevice



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



NTSTATUS HandleStopDevice(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleStopDevice

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

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



	// We're supposed to always get a query before we're stopped, so

	// we should already be in the PENDINGSTOP state. There's a Win98 bug that

	// can sometimes cause us to get a STOP instead of a REMOVE, in which case

	// we should start rejecting IRPs



	if (pdx->state != PENDINGSTOP)

		{						// no previous query

		KdPrint(("%s - STOP with no previous QUERY_STOP!\n", pdx->DebugName));

		AbortAllRequests(pdx->queues, pdx->nqueues, STATUS_DELETE_PENDING);

		AbortPendingIoctls(pdx, STATUS_DELETE_PENDING);

		}						// no previous query



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

	CallStopDevice(pdx);

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

	pdx->state = STOPPED;

	return DefaultPnpHandler(pdx, Irp);

	}							// HandleStopDevice



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



NTSTATUS HandleSurpriseRemoval(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleSurpriseRemoval

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

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



	AbortAllRequests(pdx->queues, pdx->nqueues, STATUS_DELETE_PENDING);

	AbortPendingIoctls(pdx, STATUS_DELETE_PENDING);

	GenericWakeupControl(pdx, DisableWakeup);



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

	pdx->state = SURPRISEREMOVED;



	EnableAllInterfaces(pdx, FALSE);	// this triggers notifications so apps can close their handles

	CallStopDevice(pdx);

	return DefaultPnpHandler(pdx, Irp);

	}							// HandleSurpriseRemoval



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



NTSTATUS HandleUsageNotification(PGENERIC_EXTENSION pdx, PIRP Irp)

	{							// HandleUsageNotification

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



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	DEVICE_USAGE_NOTIFICATION_TYPE type = stack->Parameters.UsageNotification.Type;

	BOOLEAN inpath = stack->Parameters.UsageNotification.InPath;



	switch (type)

		{						// switch on usage type



	case DeviceUsageTypeHibernation:

		if (!(pdx->Flags & GENERIC_USAGE_HIBERNATE))

			return CompleteRequest(Irp, STATUS_UNSUCCESSFUL);



		AdjustSpecialFileCounter(pdx, inpath, &pdx->nhibernatefiles);

		Irp->IoStatus.Status = STATUS_SUCCESS;

		break;



	case DeviceUsageTypePaging:

		{						// DeviceUsageTypePaging

		if (!(pdx->Flags & GENERIC_USAGE_PAGING))

			return CompleteRequest(Irp, STATUS_UNSUCCESSFUL);



		if (inpath && pdx->state != WORKING)

			return CompleteRequest(Irp, STATUS_DEVICE_NOT_READY); // SP-7, per DDK doc



		// Guard against reentrance by waiting on evPagingPath, which is a

		// synchronization event that was initialized to the signalled state.

		// Therefore, it will be reset once we get past the wait (SP-7, ver 1.6)



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



		// Add or substract one from the paging path counter. AdjustSpecialFileCounter

		// will also take care of enabling or disabling idle detection.



		AdjustSpecialFileCounter(pdx, inpath, &pdx->npagefiles);



		// Adjust the power-pagable flag too. (Per AdrianO) we must be careful not to

		// have a non-paged power handler sitting on top of a paged handler, so we

		// only clear DO_POWER_PAGABLE in our completion routine.

		

		PDEVICE_OBJECT fdo = pdx->DeviceObject;

		if (pdx->npagefiles == 0)

			{					// resume paging

			if (!(fdo->Flags & DO_POWER_INRUSH))

				fdo->Flags |= DO_POWER_PAGABLE;

			}					// resume paging



		// TODO Deal with paging of Read, Write, Control requests in minidriver



		Irp->IoStatus.Status = STATUS_SUCCESS;

		break;

		}						// DeviceUsageTypePaging



	case DeviceUsageTypeDumpFile:

		if (!(pdx->Flags & GENERIC_USAGE_DUMP))

			return CompleteRequest(Irp, STATUS_UNSUCCESSFUL);



		AdjustSpecialFileCounter(pdx, inpath, &pdx->ndumpfiles);

		Irp->IoStatus.Status = STATUS_SUCCESS;

		break;

		}						// switch on usage type



	// Install completion routine so we can recover from a failure and so we can

	// clear DO_POWER_PAGABLE at the right time.

	

	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnNotificationComplete, pdx, TRUE, TRUE, TRUE);

	IoCopyCurrentIrpStackLocationToNext(Irp);

	return IoCallDriver(pdx->LowerDeviceObject, Irp);

	}							// HandleUsageNotification



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



NTSTATUS OnNotificationComplete(PDEVICE_OBJECT fdo, PIRP Irp, PGENERIC_EXTENSION pdx)

	{							// OnNotificationComplete



	if (Irp->PendingReturned)

		IoMarkIrpPending(Irp);



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	DEVICE_USAGE_NOTIFICATION_TYPE type = stack->Parameters.UsageNotification.Type;

	BOOLEAN inpath = stack->Parameters.UsageNotification.InPath;



	// If the notification succeeded, and if we're on the path for paging files,

	// be sure we start getting power IRPs at DISPATCH_LEVEL.



	if (NT_SUCCESS(Irp->IoStatus.Status))

		{						// notification succeeded

		if (pdx->npagefiles)

			fdo->Flags &= ~DO_POWER_PAGABLE;

		if (type == DeviceUsageTypePaging)

			KeSetEvent(&pdx->evPagingPath, IO_NO_INCREMENT, FALSE); // SP-7

		return STATUS_SUCCESS;

		}						// notification succeeded



	// Somebody underneath us failed this usage notification, so undo the steps we

	// took in the dispatch routine. Notice how we reverse the sense of "inpath" in

	// the following calls to AdjustSpecialFileCounter.



	switch (type)

		{						// switch on usage type



	case DeviceUsageTypeHibernation:

		AdjustSpecialFileCounter(pdx, !inpath, &pdx->nhibernatefiles);

		break;



	case DeviceUsageTypePaging:

		{						// DeviceUsageTypePaging

		AdjustSpecialFileCounter(pdx, !inpath, &pdx->npagefiles);

		if (pdx->npagefiles == 0)

			{					// resume paging

			if (!(fdo->Flags & DO_POWER_INRUSH))

				fdo->Flags |= DO_POWER_PAGABLE;

			}					// resume paging

		else

			fdo->Flags &= ~DO_POWER_PAGABLE;



		KeSetEvent(&pdx->evPagingPath, IO_NO_INCREMENT, FALSE); // SP-7

		break;

		}						// DeviceUsageTypePaging



	case DeviceUsageTypeDumpFile:

		AdjustSpecialFileCounter(pdx, !inpath, &pdx->ndumpfiles);

		break;

		}						// switch on usage type



	return STATUS_SUCCESS;

	}							// OnNotificationComplete



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



#if DBG



VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list)

	{							// ShowResources

	PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = list->PartialDescriptors;

	ULONG nres = list->Count;

	ULONG i;



	for (i = 0; i < nres; ++i, ++resource)

		{						// for each resource

		ULONG type = resource->Type;



		static char* name[] = {

			"CmResourceTypeNull",

			"CmResourceTypePort",

			"CmResourceTypeInterrupt",

			"CmResourceTypeMemory",

			"CmResourceTypeDma",

			"CmResourceTypeDeviceSpecific",

			"CmResourceTypeBusNumber",

			"CmResourceTypeDevicePrivate",

			"CmResourceTypeAssignedResource",

			"CmResourceTypeSubAllocateFrom",

			};



		KdPrint(("    type %s", type < arraysize(name) ? name[type] : "unknown"));



		switch (type)

			{					// select on resource type

		case CmResourceTypePort:

		case CmResourceTypeMemory:

			KdPrint((" start %8X%8.8lX length %X\n",

				resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,

				resource->u.Port.Length));

			break;

		

		case CmResourceTypeInterrupt:

			KdPrint(("  level %X, vector %X, affinity %X\n",

				resource->u.Interrupt.Level, resource->u.Interrupt.Vector,

				resource->u.Interrupt.Affinity));

			break;

	

		case CmResourceTypeDma:

			KdPrint(("  channel %d, port %X\n",

				resource->u.Dma.Channel, resource->u.Dma.Port));

			}					// select on resource type

		}						// for each resource

	}							// ShowResources



#endif // DBG



⌨️ 快捷键说明

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