NTSTATUS IopForAllDeviceNodesCallback( IN PDEVICE_NODE DeviceNode, IN PVOID Context ) /*++ Routine Description: This function is the worker routine for IopForAllChildDeviceNodes routine. Arguments: DeviceNode - Supplies a pointer to the device node whose subtree is to be walked. Context - Supplies a context which contains the caller specified call back function and parameter. Return Value: NTSTATUS value. --*/ { PENUM_CONTEXT enumContext; NTSTATUS status; PAGED_CODE(); enumContext = (PENUM_CONTEXT)Context; // // First call the caller's callback for this devnode // status = enumContext->CallersCallback(DeviceNode, enumContext->CallersContext); if (NT_SUCCESS(status)) { // // Now enumerate the children, if any. // IopAcquireEnumerationLock(DeviceNode); if( DeviceNode->Child) { status = IopForAllChildDeviceNodes( DeviceNode, IopForAllDeviceNodesCallback, Context); } IopReleaseEnumerationLock(DeviceNode); } return status; }
NTSTATUS IopForAllDeviceNodes( IN PENUM_CALLBACK Callback, IN PVOID Context ) /*++ Routine Description: This function walks the device node tree and perform caller specified 'Callback' function for each device node. Note, this routine (or its worker routine) traverses the tree in a top down manner. Arguments: Callback - Supplies the call back routine for each device node. Context - Supplies a parameter/context for the callback function. Return Value: Status returned from Callback, if not successfull then the tree walking stops. --*/ { ENUM_CONTEXT enumContext; NTSTATUS status; PAGED_CODE(); enumContext.CallersCallback = Callback; enumContext.CallersContext = Context; // // Start with a pointer to the root device node, recursively examine all the // children until we the callback function says stop or we've looked at all // of them. // IopAcquireEnumerationLock(IopRootDeviceNode); status = IopForAllChildDeviceNodes(IopRootDeviceNode, IopForAllDeviceNodesCallback, (PVOID)&enumContext ); IopReleaseEnumerationLock(IopRootDeviceNode); return status; }
PDEVICE_OBJECT IopGetDevicePDO( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: Call this routine to obtain the Base PDO for a device object Arguments: DeviceObject - pointer to device object to get PDO for ReturnValue: PDO if DeviceObject is attached to a PDO, otherwise NULL The returned PDO is reference-counted --*/ { PDEVICE_OBJECT deviceBaseObject; KIRQL irql; ASSERT(DeviceObject); IopAcquireEnumerationLock(NULL); // ensure we have acquired P&P locks ExAcquireSpinLock(&IopDatabaseLock,&irql); deviceBaseObject = IopGetDeviceAttachmentBase(DeviceObject); if ((deviceBaseObject->Flags & DO_BUS_ENUMERATED_DEVICE) != 0) { // // we have determined that this is attached to a PDO // ObReferenceObject( deviceBaseObject ); } else { // // not a PDO // deviceBaseObject = NULL; } ExReleaseSpinLock(&IopDatabaseLock,irql); IopReleaseEnumerationLock(NULL); return deviceBaseObject; }
NTSTATUS IopSetDeviceSecurityDescriptors( IN PDEVICE_OBJECT DeviceObject, IN PSECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN DoAttachedDevices ) /*++ Routine Description: Call this routine to set device security descriptor Arguments: DeviceObject - pointer to base device object (first one to set) SecurityInformation )_ passed directly from IopGetSetSecurityObject SecurityDescriptor ) PoolType ) GenericMapping ) DoAttachedDevices - if true, iterate the AttachedDevice list ReturnValue: success, or error from first failure --*/ { PDEVICE_OBJECT NewDeviceObject = NULL; PSECURITY_DESCRIPTOR OldSecurityDescriptor; KIRQL irql; NTSTATUS status; NTSTATUS firsterr = STATUS_SUCCESS; BOOLEAN first = TRUE; ASSERT(DeviceObject); IopAcquireEnumerationLock(NULL); // ensure we have acquired P&P locks // // pre-reference this object to match the dereference later // ObReferenceObject( DeviceObject ); do { KeEnterCriticalRegion(); ExAcquireResourceExclusive( &IopSecurityResource, TRUE ); OldSecurityDescriptor = DeviceObject->SecurityDescriptor; if (OldSecurityDescriptor || first) { // // always call this on the first object, only do it for others that have a security descriptor // status = SeSetSecurityDescriptorInfo( NULL, SecurityInformation, SecurityDescriptor, &DeviceObject->SecurityDescriptor, PoolType, GenericMapping ); if (NT_SUCCESS(firsterr)) { firsterr = status; } if (NT_SUCCESS( status )) { ASSERT(OldSecurityDescriptor); ExFreePool( OldSecurityDescriptor ); } first = FALSE; } ExReleaseResource( &IopSecurityResource ); KeLeaveCriticalRegion(); // // get next device on attachment chain // ExAcquireSpinLock(&IopDatabaseLock,&irql); NewDeviceObject = DeviceObject->AttachedDevice; if ( NewDeviceObject != NULL ) { ObReferenceObject( NewDeviceObject ); } else { DoAttachedDevices = FALSE; } ExReleaseSpinLock(&IopDatabaseLock,irql); ObDereferenceObject( DeviceObject ); DeviceObject = NewDeviceObject; } while(DoAttachedDevices); IopReleaseEnumerationLock(NULL); return firsterr; // of the PDO / single object }