windows-nt/Source/XPSP1/NT/base/ntos/io/pnpmgr/pphandle.c
2020-09-26 16:20:57 +08:00

308 lines
6.7 KiB
C

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
PpHandle.c
Abstract:
This module implements handle location code for the Plug and Play subsystem.
Author:
Adrian J. Oney - April 4, 2001
Revision History:
--*/
#include "pnpmgrp.h"
#include "pihandle.h"
#pragma hdrstop
//
// This code is current used only in the checked build for debugging purposes.
//
#if DBG
#ifdef ALLOC_PRAGMA
//#pragma alloc_text(NONPAGE, PpHandleEnumerateHandlesAgainstPdoStack)
#pragma alloc_text(PAGE, PiHandleEnumerateHandlesAgainstDeviceObject)
#pragma alloc_text(PAGE, PiHandleProcessWalkWorker)
#endif
BOOLEAN
PpHandleEnumerateHandlesAgainstPdoStack(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PHANDLE_ENUMERATION_CALLBACK HandleEnumCallBack,
IN PVOID Context
)
/*++
Routine Description:
This routine walks every device object in the WDM device stack along with
all filesystem device objects on the other side of a VPB. If any handles
are opened against such device objects, the specified callback is invoked.
Arguments:
PhysicalDeviceObject - Supplies a pointer to the device object at the
bottom of the WDM device stack.
HandleEnumCallBack - Pointer the callback function.
Context - Pointer to information to be passed into the callback function.
Return Value:
TRUE if the enumeration was halted, FALSE otherwise.
--*/
{
PDEVICE_OBJECT currentDevObj, nextDevObj, vpbObj, vpbBottomObj;
BOOLEAN stopEnum;
KIRQL oldIrql;
PVPB vpb;
//
// Preinit
//
stopEnum = FALSE;
//
// Start with the device object at the bottom of the stack
//
currentDevObj = PhysicalDeviceObject;
ObReferenceObject(currentDevObj);
do {
//
// Dump any handles opened directly against the specified device object
//
stopEnum = PiHandleEnumerateHandlesAgainstDeviceObject(
currentDevObj,
HandleEnumCallBack,
Context
);
if (stopEnum) {
ObDereferenceObject(currentDevObj);
break;
}
//
// Look for a VPB
//
IoAcquireVpbSpinLock(&oldIrql);
vpb = currentDevObj->Vpb;
vpbObj = NULL;
if (vpb) {
vpbObj = vpb->DeviceObject;
if (vpbObj) {
ObReferenceObject(vpbObj);
}
}
IoReleaseVpbSpinLock(oldIrql);
//
// If we have a vpb object, dump any handles queued against it.
//
if (vpbObj) {
vpbBottomObj = IoGetDeviceAttachmentBaseRef(vpbObj);
stopEnum = PiHandleEnumerateHandlesAgainstDeviceObject(
vpbBottomObj,
HandleEnumCallBack,
Context
);
ObDereferenceObject(vpbBottomObj);
ObDereferenceObject(vpbObj);
if (stopEnum) {
ObDereferenceObject(currentDevObj);
break;
}
}
//
// Advance to the next DO.
//
oldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
nextDevObj = currentDevObj->AttachedDevice;
if (nextDevObj) {
ObReferenceObject(nextDevObj);
}
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, oldIrql);
//
// Drop ref on old DO.
//
ObDereferenceObject(currentDevObj);
//
// Loop.
//
currentDevObj = nextDevObj;
} while (currentDevObj);
return stopEnum;
}
BOOLEAN
PiHandleEnumerateHandlesAgainstDeviceObject(
IN PDEVICE_OBJECT DeviceObject,
IN PHANDLE_ENUMERATION_CALLBACK HandleEnumCallBack,
IN PVOID Context
)
/*++
Routine Description:
This routine walks the handle table for each process in the system looking
for handles opened against the passed in device object.
Arguments:
PhysicalDeviceObject - Supplies a pointer to the device object at the
bottom of the WDM device stack.
HandleEnumCallBack - Pointer the callback function.
Context - Pointer to information to be passed into the callback function.
Return Value:
TRUE if the enumeration was halted, FALSE otherwise.
--*/
{
PEPROCESS process;
PHANDLE_TABLE objectTable;
HANDLE_ENUM_CONTEXT handleEnumContext;
BOOLEAN stopEnum;
stopEnum = FALSE;
for(process = PsGetNextProcess(NULL);
process != NULL;
process = PsGetNextProcess(process)) {
objectTable = ObReferenceProcessHandleTable(process);
if (objectTable) {
handleEnumContext.DeviceObject = DeviceObject;
handleEnumContext.Process = process;
handleEnumContext.CallBack = HandleEnumCallBack;
handleEnumContext.Context = Context;
stopEnum = ExEnumHandleTable(
objectTable,
PiHandleProcessWalkWorker,
(PVOID) &handleEnumContext,
NULL
);
ObDereferenceProcessHandleTable(process);
if (stopEnum) {
PsQuitNextProcess(process);
break;
}
}
}
return stopEnum;
}
BOOLEAN
PiHandleProcessWalkWorker(
IN PHANDLE_TABLE_ENTRY ObjectTableEntry,
IN HANDLE HandleId,
IN PHANDLE_ENUM_CONTEXT EnumContext
)
/*++
Routine Description:
This routine gets called back for each handle in a given process. It
examines each handle to see if it is a file object opened against the
device object we are looking for.
Arguments:
ObjectTableEntry - Points to the handle table entry of interest.
HandleId - Supplies the handle.
EnumContext - Context passed in for the enumeration.
Return Value:
TRUE if the enumeration should be stopped, FALSE otherwise.
--*/
{
PDEVICE_OBJECT deviceObject;
POBJECT_HEADER objectHeader;
PFILE_OBJECT fileObject;
objectHeader = OBJECT_FROM_EX_TABLE_ENTRY(ObjectTableEntry);
if (objectHeader->Type != IoFileObjectType) {
//
// Not a file object
//
return FALSE;
}
fileObject = (PFILE_OBJECT) &objectHeader->Body;
deviceObject = IoGetBaseFileSystemDeviceObject( fileObject );
if (deviceObject != EnumContext->DeviceObject) {
//
// Not our device object
//
return FALSE;
}
//
// Found one, invoke the callback!
//
return EnumContext->CallBack(
EnumContext->DeviceObject,
EnumContext->Process,
fileObject,
HandleId,
EnumContext->Context
);
}
#endif // DBG