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

📄 plugplaypdo.cpp

📁 Programming the Microsoft Windows Driver Model(2nd)
💻 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 + -