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

📄 plugplay.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 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 + -