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

📄 plugplaypdo.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		{							// query for PDO address
		ASSERT(!oldrel);			// no-one has any business with this but us!
		newrel = (PDEVICE_RELATIONS) ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
		if (newrel)
			{
			newrel->Count = 1;
			newrel->Objects[0] = pdo;
			ObReferenceObject(pdo);
			status = STATUS_SUCCESS;
			}
		else
			status = STATUS_INSUFFICIENT_RESOURCES;
		}							// query for PDO address

	if (newrel)
		{							// install new relation list
		if (oldrel)
			ExFreePool(oldrel);
		Irp->IoStatus.Information = (ULONG_PTR) newrel;
		}							// install new relation list

	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return status;
	}							// HandleQueryRelations

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

#pragma PAGEDCODE

static NTSTATUS IgnoreRequest(PDEVICE_OBJECT pdo, PIRP Irp)
	{							// IgnoreRequest
	NTSTATUS status = Irp->IoStatus.Status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return status;
	}							// IgnoreRequest

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

#pragma LOCKEDCODE

static NTSTATUS OnRepeaterComplete(PDEVICE_OBJECT tdo, PIRP subirp, PVOID needsvote)
	{							// OnRepeaterComplete
	ObDereferenceObject(tdo);
	PIO_STACK_LOCATION substack = IoGetCurrentIrpStackLocation(subirp);
	PIRP Irp = (PIRP) substack->Parameters.Others.Argument1;

	// Complete the main IRP. We need to copy IoStatus.Information from the
	// now-complete repeater IRP, inasmuch as it contains the "return value"
	// from the IRP. If the repeater IRP still holds STATUS_NOT_SUPPORTED as
	// its status, the parent device stack didn't actually process the IRP.
	// The status we then set depends on the "needsvote" value developed by
	// RepeatRequest.

	if (subirp->IoStatus.Status == STATUS_NOT_SUPPORTED)
		{						// parent stack ignored this IRP
		if (needsvote)
			Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
		}						// parent stack ignored this IRP
	else
		Irp->IoStatus = subirp->IoStatus; // propagate status from parent stack

	Irp->IoStatus.Information = subirp->IoStatus.Information;

	IoFreeIrp(subirp);
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return STATUS_MORE_PROCESSING_REQUIRED;
	}							// OnRepeaterComplete

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

#pragma PAGEDCODE

static NTSTATUS RepeatRequest(PDEVICE_OBJECT pdo, PIRP Irp)
	{							// RepeatRequest
	PPDO_EXTENSION pdx = (PPDO_EXTENSION) pdo->DeviceExtension;
	PDEVICE_OBJECT fdo = pdx->Fdo;
	PDEVICE_EXTENSION pfx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	PDEVICE_OBJECT tdo = IoGetAttachedDeviceReference(fdo);
	PIRP subirp = IoAllocateIrp(tdo->StackSize + 1, FALSE);

	if (!subirp)
		return CompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, Irp->IoStatus.Information);

	// Setup extra stack location at the top so we can cleanup and complete
	// the main IRP

	PIO_STACK_LOCATION substack = IoGetNextIrpStackLocation(subirp);
	substack->DeviceObject = tdo;
	substack->Parameters.Others.Argument1 = (PVOID) Irp;

	// Setup next stack location for the FDO stack to process the repeater IRP

	IoSetNextIrpStackLocation(subirp);
	substack = IoGetNextIrpStackLocation(subirp);
	RtlCopyMemory(substack, stack, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine));
	substack->Control = 0;

	// Our completion routine needs a way to know what to do if the parent driver stack
	// completes the subsidiary IRP with STATUS_NOT_SUPPORTED. For some IRPs (ones that
	// require a parental "vote" on their status), we want to fail the IRPs if no-one
	// in the parent stack handles it. For others, we don't want to change the status
	// passed down to us from the child stack. Since we're not using the context
	// argument for any other purpose in our completion routine, we pass a simple
	// boolean value to distinguish the two cases.

	UCHAR subfunc = stack->MinorFunction;
	static BOOLEAN voteflag[] = {
		FALSE,			// IRP_MN_START_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_REMOVE_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_REMOVE_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_CANCEL_REMOVE_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_STOP_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_STOP_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_CANCEL_STOP_DEVICE [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_DEVICE_RELATIONS [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_INTERFACE
		FALSE,			// IRP_MN_QUERY_CAPABILITIES
		FALSE,			// IRP_MN_QUERY_RESOURCES [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_RESOURCE_REQUIREMENTS [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_DEVICE_TEXT [don't care since not repeated]
		FALSE,			// IRP_MN_FILTER_RESOURCE_REQUIREMENTS [don't care since not repeated]
		FALSE,			//  [don't care since not repeated]
		TRUE,			// IRP_MN_READ_CONFIG
		TRUE,			// IRP_MN_WRITE_CONFIG
		TRUE,			// IRP_MN_EJECT [no-one above us should have changed status anyway]
		TRUE,			// IRP_MN_SET_LOCK [no-one above us should have changed status anyway]
		FALSE,			// IRP_MN_QUERY_ID [don't care since not repeated]
		FALSE,			// IRP_MN_QUERY_PNP_DEVICE_STATE
		TRUE,			// IRP_MN_QUERY_BUS_INFORMATION
		FALSE,			// IRP_MN_DEVICE_USAGE_NOTIFICATION
		FALSE,			// IRP_MN_SURPRISE_REMOVAL [don't care since not repeated]
		TRUE,			// IRP_MN_QUERY_LEGACY_BUS_INFORMATION
		};

	BOOLEAN needsvote = subfunc < arraysize(voteflag) ? voteflag[subfunc] : TRUE;

	IoSetCompletionRoutine(subirp, (PIO_COMPLETION_ROUTINE) OnRepeaterComplete, (PVOID) needsvote, TRUE, TRUE, TRUE);

	// Initialize completion status for the repeater IRP to STATUS_NOT_SUPPORTED.
	// This is required to avoid a bug check in the driver verifier. The underlying
	// reason is that some drivers in some parent stacks (not MULFUNC's, because it's
	// not a real device, but in general) need a way to know when someone truly handles
	// this IRP.

	subirp->IoStatus.Status = STATUS_NOT_SUPPORTED;

	// Return STATUS_PENDING because we won't know until completion time what the
	// right status is (and it may not be what the parent stack returns here).

	IoMarkIrpPending(Irp);
	IoCallDriver(tdo, subirp);
	return STATUS_PENDING;
	}							// RepeatRequest

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

#pragma PAGEDCODE

static NTSTATUS SucceedRequest(PDEVICE_OBJECT pdo, PIRP Irp)
	{							// SucceedRequest
	Irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
	}							// SucceedRequest

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

VOID SuballocInterfaceReference(PDEVICE_EXTENSION fdx)
	{							// SuballocInterfaceReference
	InterlockedIncrement(&fdx->sarefcnt);
	}							// SuballocInterfaceReference

VOID SuballocInterfaceDereference(PDEVICE_EXTENSION fdx)
	{							// SuballocInterfaceDereference
	LONG count = InterlockedDecrement(&fdx->sarefcnt);
	ASSERT(count >= 0);
	}							// SuballocInterfaceDereference

NTSTATUS GetChildResources(PDEVICE_EXTENSION fdx, PDEVICE_OBJECT pdo, PCM_RESOURCE_LIST* praw, PCM_RESOURCE_LIST* ptranslated)
	{							// GetChildResources
	ASSERT(fdx->sarefcnt > 0);	// someone needs to still have a reference

	if (pdo != fdx->ChildA && pdo != fdx->ChildB)
		return STATUS_DEVICE_CONFIGURATION_ERROR; // who's that asking??

	ULONG size = sizeof(CM_RESOURCE_LIST);
	
	PCM_RESOURCE_LIST raw, translated;
	raw = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool, size);
	if (!raw)
		return STATUS_INSUFFICIENT_RESOURCES;
	translated = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool, size);
	if (!translated)
		{
		ExFreePool(raw);
		return STATUS_INSUFFICIENT_RESOURCES;
		}

	RtlZeroMemory(raw, size);
	RtlZeroMemory(translated, size);

	raw->Count = 1;
	raw->List[0].PartialResourceList.Version = 1;
	raw->List[0].PartialResourceList.Revision = 1;
	raw->List[0].PartialResourceList.Count = 1;
	raw->List[0].PartialResourceList.PartialDescriptors[0] = (pdo == fdx->ChildA) ? fdx->PortARaw : fdx->PortBRaw;

	translated->Count = 1;
	translated->List[0].PartialResourceList.Version = 1;
	translated->List[0].PartialResourceList.Revision = 1;
	translated->List[0].PartialResourceList.Count = 1;
	translated->List[0].PartialResourceList.PartialDescriptors[0] = (pdo == fdx->ChildA) ? fdx->PortATranslated : fdx->PortBTranslated;

	*praw = raw;
	*ptranslated = translated;
	return STATUS_SUCCESS;
	}							// GetChildResources

⌨️ 快捷键说明

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