📄 pnp.c
字号:
Irp->IoStatus.Status = status;
PptCompleteRequest(Irp, IO_NO_INCREMENT);
PptReleaseRemoveLock(&extension->RemoveLock, Irp);
return status;
}
BOOLEAN
PptPnpFilterExistsNonIrqResourceList(
IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
)
/*++dvdf8
Routine Description:
This function is a helper function called by
PptPnpFilterResourceRequirements().
This function scans the IO_RESOURCE_REQUIREMENTS_LIST to determine
whether there exists any resource alternatives that do NOT contain
an IRQ resource descriptor. The method used to filter out IRQ
resources may differ based on whether or not there exists a
resource alternative that does not contain an IRQ resource
descriptor.
Arguments:
ResourceRequirementsList - The list to scan.
Return Value:
TRUE - There exists at least one resource alternative in the list that
does not contain an IRQ resource descriptor.
FALSE - Otherwise.
--*/
{
ULONG listCount = ResourceRequirementsList->AlternativeLists;
PIO_RESOURCE_LIST curList;
ULONG i;
PptDump2(PARRESOURCE,("Enter PptPnpFilterExistsNonIrqResourceList() - AlternativeLists= %d\n", listCount));
i=0;
curList = ResourceRequirementsList->List;
while( i < listCount ) {
PptDump2(PARRESOURCE,("Searching List i=%d for an IRQ, curList= %x\n", i,curList));
{
ULONG remain = curList->Count;
PIO_RESOURCE_DESCRIPTOR curDesc = curList->Descriptors;
BOOLEAN foundIrq = FALSE;
while( remain ) {
PptDump2(PARRESOURCE,(" curDesc= %x , remain=%d\n", curDesc, remain));
if(curDesc->Type == CmResourceTypeInterrupt) {
PptDump2(PARRESOURCE,(" Found IRQ - skip to next list\n"));
foundIrq = TRUE;
break;
}
++curDesc;
--remain;
}
if( foundIrq == FALSE ) {
//
// We found a resource list that does not contain an IRQ resource.
// Our search is over.
//
PptDump2(PARRESOURCE,(" Found a list with NO IRQ - return TRUE from PptPnpFilterExistsNonIrqResourceList\n"));
return TRUE;
}
}
//
// The next list starts immediately after the last descriptor of the current list.
//
curList = (PIO_RESOURCE_LIST)(curList->Descriptors + curList->Count);
++i;
}
//
// All resource alternatives contain at least one IRQ resource descriptor.
//
PptDump2(PARRESOURCE,("all lists contain IRQs - return FALSE from PptPnpFilterExistsNonIrqResourceList\n"));
return FALSE;
}
VOID
PptPnpFilterRemoveIrqResourceLists(
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
)
/*++dvdf8
Routine Description:
This function is a helper function called by
PptPnpFilterResourceRequirements().
This function removes all resource alternatives (IO_RESOURCE_LISTs)
that contain IRQ resources from the IO_RESOURCE_REQUIREMENTS_LIST
Arguments:
ResourceRequirementsList - The list to process.
Return Value:
none.
--*/
{
ULONG listCount = ResourceRequirementsList->AlternativeLists;
PIO_RESOURCE_LIST curList;
PIO_RESOURCE_LIST nextList;
ULONG i;
PCHAR currentEndOfResourceRequirementsList;
LONG bytesToMove;
PptDump2(PARRESOURCE,("Enter PptPnpFilterRemoveIrqResourceLists() - AlternativeLists= %d\n", listCount));
//
// We use the end of the list to compute the size of the memory
// block to move when we remove a resource alternative from the
// list of lists.
//
currentEndOfResourceRequirementsList = PptPnpFilterGetEndOfResourceRequirementsList(ResourceRequirementsList);
i=0;
curList = ResourceRequirementsList->List;
//
// Walk through the IO_RESOURCE_LISTs.
//
while( i < listCount ) {
PptDump2(PARRESOURCE,("\n"));
PptDump2(PARRESOURCE,("TopOfLoop: i=%d listCount=%d curList= %#x , curEndOfRRL= %#x\n",
i,listCount,curList,currentEndOfResourceRequirementsList));
if( PptPnpListContainsIrqResourceDescriptor(curList) ) {
//
// The current list contains IRQ, remove it by shifting the
// remaining lists into its place and decrementing the list count.
//
PptDump2(PARRESOURCE,("list contains an IRQ - Removing List\n"));
//
// Get a pointer to the start of the next list.
//
nextList = (PIO_RESOURCE_LIST)(curList->Descriptors + curList->Count);
//
// compute the number of bytes to move
//
bytesToMove = (LONG)(currentEndOfResourceRequirementsList - (PCHAR)nextList);
//
// if (currentEndOfResourceRequirementsList == next list),
// then this is the last list so there is nothing to move.
//
if( bytesToMove > 0 ) {
//
// More lists remain - shift them into the hole.
//
RtlMoveMemory(curList, nextList, bytesToMove);
//
// Adjust the pointer to the end of of the
// IO_RESOURCE_REQUIREMENTS_LIST (list of lists) due to the shift.
//
currentEndOfResourceRequirementsList -= ( (PCHAR)nextList - (PCHAR)curList );
}
//
// Note that we removed an IO_RESOURCE_LIST from the IO_RESOURCE_REQUIREMENTS_LIST.
//
--listCount;
} else {
//
// The current list does not contain an IRQ resource, advance to next list.
//
PptDump2(PARRESOURCE,("list does not contain an IRQ - i=%d listCount=%d curList= %#x\n", i,listCount,curList));
curList = (PIO_RESOURCE_LIST)(curList->Descriptors + curList->Count);
++i;
}
}
//
// Note the post filtered list count in the ResourceRequirementsList.
//
ResourceRequirementsList->AlternativeLists = listCount;
PptDump2(PARRESOURCE,("Leave PptPnpFilterRemoveIrqResourceLists() - AlternativeLists= %d\n", listCount));
return;
}
PVOID
PptPnpFilterGetEndOfResourceRequirementsList(
IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
)
/*++dvdf8
Routine Description:
This function is a helper function called by PptPnpFilterRemoveIrqResourceLists()
This function finds the end of an IO_RESOURCE_REQUIREMENTS_LIST
(list of IO_RESOURCE_LISTs).
Arguments:
ResourceRequirementsList - The list to scan.
Return Value:
Pointer to the next address past the end of the IO_RESOURCE_REQUIREMENTS_LIST.
--*/
{
ULONG listCount = ResourceRequirementsList->AlternativeLists;
PIO_RESOURCE_LIST curList;
ULONG i;
i=0;
curList = ResourceRequirementsList->List;
while( i < listCount ) {
//
// Pointer arithmetic based on the size of an IO_RESOURCE_DESCRIPTOR.
//
curList = (PIO_RESOURCE_LIST)(curList->Descriptors + curList->Count);
++i;
}
return (PVOID)curList;
}
VOID
PptPnpFilterNukeIrqResourceDescriptorsFromAllLists(
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
)
/*++dvdf8
Routine Description:
This function is a helper function called by
PptPnpFilterResourceRequirements().
This function "nukes" all IRQ resources descriptors
in the IO_RESOURCE_REQUIREMENTS_LIST by changing the descriptor
types from CmResourceTypeInterrupt to CmResourceTypeNull.
Arguments:
ResourceRequirementsList - The list to process.
Return Value:
none.
--*/
{
ULONG listCount = ResourceRequirementsList->AlternativeLists;
ULONG i = 0;
PIO_RESOURCE_LIST curList = ResourceRequirementsList->List;
PptDump2(PARRESOURCE,("Enter PptPnpFilterNukeIrqResourceDescriptorsFromAllLists()"
" - AlternativeLists= %d\n", listCount));
//
// Walk through the list of IO_RESOURCE_LISTs in the IO_RESOURCE_REQUIREMENTS list.
//
while( i < listCount ) {
PptDump2(PARRESOURCE,("Nuking IRQs from List i=%d, curList= %x\n", i,curList));
//
// Nuke all IRQ resources from the current IO_RESOURCE_LIST.
//
PptPnpFilterNukeIrqResourceDescriptors( curList );
curList = (PIO_RESOURCE_LIST)(curList->Descriptors + curList->Count);
++i;
}
}
VOID
PptPnpFilterNukeIrqResourceDescriptors(
PIO_RESOURCE_LIST IoResourceList
)
/*++dvdf8
Routine Description:
This function is a helper function called by
PptPnpFilterNukeIrqResourceDescriptorsFromAllLists().
This function "nukes" all IRQ resources descriptors
in the IO_RESOURCE_LIST by changing the descriptor
types from CmResourceTypeInterrupt to CmResourceTypeNull.
Arguments:
IoResourceList - The list to process.
Return Value:
none.
--*/
{
PIO_RESOURCE_DESCRIPTOR pIoResourceDescriptorIn = IoResourceList->Descriptors;
ULONG i;
//
// Scan the descriptor list for Interrupt descriptors.
//
for (i = 0; i < IoResourceList->Count; ++i) {
if (pIoResourceDescriptorIn->Type == CmResourceTypeInterrupt) {
//
// Found one - change resource type from Interrupt to Null.
//
pIoResourceDescriptorIn->Type = CmResourceTypeNull;
PptDump2(PARRESOURCE,(" - giving up IRQ resource - MinimumVector: %d MaximumVector: %d\n",
pIoResourceDescriptorIn->u.Interrupt.MinimumVector,
pIoResourceDescriptorIn->u.Interrupt.MaximumVector) );
}
++pIoResourceDescriptorIn;
}
}
NTSTATUS
PptPnpQueryDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This function handles PnP IRP_MN_QUERY_DEVICE_RELATIONS.
Arguments:
DeviceObject - The target device for the IRP
Irp - The IRP
Return Value:
STATUS_SUCCESS - on success,
an appropriate error status - otherwise
--*/
{
PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
DEVICE_RELATION_TYPE type = irpSp->Parameters.QueryDeviceRelations.Type;
PDEVICE_RELATIONS removalRelations;
switch( type ) {
case RemovalRelations:
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - RemovalRelations\n") );
PptDumpRemovalRelationsList( extension );
if( Irp->IoStatus.Information ) {
// someone above us has already handled this - dvdf RMT
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - RemovalRelations - handled above us\n"));
} else {
removalRelations = PptPnpBuildRemovalRelations( extension );
if( removalRelations ) {
// report devices
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - RemovalRelations - reporting relations\n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = (ULONG_PTR)removalRelations;
} else {
// no devices to report
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - RemovalRelations - empty list - nothing to report\n"));
}
}
break;
case BusRelations:
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - BusRelations\n") );
break;
case EjectionRelations:
PptDump2(PARPNP1, ("pnp::PptPnpQueryDeviceRelations - EjectionRelations\n") );
break;
case PowerRelations:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -