|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
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
#ifdef ALLOC_PRAGMA
//#pragma alloc_text(NONPAGE, PpHandleEnumerateHandlesAgainstPdoStack)
#pragma alloc_text(PAGE, PiHandleEnumerateHandlesAgainstDeviceObject)
#pragma alloc_text(PAGE, PiHandleProcessWalkWorker)
#endif
LOGICAL 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; LOGICAL 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; }
LOGICAL 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; LOGICAL 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 = (LOGICAL) 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 (BOOLEAN) EnumContext->CallBack( EnumContext->DeviceObject, EnumContext->Process, fileObject, HandleId, EnumContext->Context ); }
|