1. IoAttachDevice
NTSTATUS IoAttachDevice( IN PDEVICE_OBJECT SourceDevice, IN PUNICODE_STRING TargetDevice, OUT PDEVICE_OBJECT *AttachedDevice );
将【指定指针】的设备对象附加到【指定名称】的设备对象所在的【设备对象栈】顶层,并返回【附加之前的栈顶设备对象指针】。
PDEVICE_OBJECT IoAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice );
NTSTATUS IoGetDeviceObjectPointer( IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject );
它的源代码:
NTSTATUS IoGetDeviceObjectPointer( IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject ) { PFILE_OBJECT fileObject; OBJECT_ATTRIBUTES objectAttributes; HANDLE fileHandle; IO_STATUS_BLOCK ioStatus; NTSTATUS status; PAGED_CODE(); // // Initialize the object attributes to open the device. // InitializeObjectAttributes( &objectAttributes, ObjectName, OBJ_KERNEL_HANDLE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); status = ZwOpenFile( &fileHandle, DesiredAccess, &objectAttributes, &ioStatus, 0, FILE_NON_DIRECTORY_FILE ); if (NT_SUCCESS( status )) { // // The open operation was successful. Dereference the file handle // and obtain a pointer to the device object for the handle. // status = ObReferenceObjectByHandle( fileHandle, 0, IoFileObjectType, KernelMode, (PVOID *) &fileObject, NULL ); if (NT_SUCCESS( status )) { *FileObject = fileObject; // // Get a pointer to the device object for this file. // *DeviceObject = IoGetRelatedDeviceObject( fileObject ); } (VOID) ZwClose( fileHandle ); } return status; }
(a) 在DEVICE_OBJECT和FILE_OBJECT结构中都存在Vpb字段,它是文件对象与相应磁盘卷设备直接的桥梁,一般Vpb中的RealDevice就指向了该对象的相应磁盘卷(块)设备,而vpb中的DeviceObject指向的是文件系统卷设备。比如将C盘下一个文件的FileObject传递给IoGetBaseFileSystemDeviceObject,那么若c盘是ntfs分区的,得到的文件系统卷设备DEVICE_OBJECT所属的驱动对象DRIVER_OBJECT就是\FileSystem\Ntfs;如果把该FileOjbect传递给 IoGetRelatedDeviceObject,那么得到的deviceobject是附加在这个文件系统卷设备所在设备栈的顶层设备。
(b) 如果文件系统没有挂接,返回的是【磁盘系统卷设备】,否则返回的是【文件系统卷设备】.
(c) 如果文件系统已经挂接,返回的是【文件系统卷设备】
PDEVICE_OBJECT IoGetRelatedDeviceObject( IN PFILE_OBJECT FileObject );
它的实现如下:
PDEVICE_OBJECT IoGetRelatedDeviceObject( IN PFILE_OBJECT FileObject ) { PDEVICE_OBJECT deviceObject; // // If the file object was taken out against the mounted file system, it // will have a Vpb. Traverse it to get to the DeviceObject. Note that in // this case we should never follow FileObject->DeviceObject, as that // mapping may be invalid after a forced dismount. // if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) { ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); deviceObject = FileObject->Vpb->DeviceObject; // // If a driver opened a disk device using direct device open and // later on it uses IoGetRelatedTargetDeviceObject to find the // device object it wants to send an IRP then it should not get the // filesystem device object. This is so that if the device object is in the // process of being mounted then vpb is not stable. // } else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && FileObject->DeviceObject->Vpb != NULL && FileObject->DeviceObject->Vpb->DeviceObject != NULL) { deviceObject = FileObject->DeviceObject->Vpb->DeviceObject; // // This is a direct open against the device stack (and there is no mounted // file system to strain the IRPs through). // } else { deviceObject = FileObject->DeviceObject; } ASSERT( deviceObject != NULL ); // // Check to see whether or not the device has any associated devices. // If so, return the highest level device; otherwise, return a pointer // to the device object itself. // if (deviceObject->AttachedDevice != NULL) { if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) { PIOP_FILE_OBJECT_EXTENSION fileObjectExtension = (PIOP_FILE_OBJECT_EXTENSION)(FileObject + 1); ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); if (fileObjectExtension->TopDeviceObjectHint != NULL && IopVerifyDeviceObjectOnStack(deviceObject, fileObjectExtension->TopDeviceObjectHint)) { return fileObjectExtension->TopDeviceObjectHint; } } deviceObject = IoGetAttachedDevice( deviceObject ); } return deviceObject; }
PDEVICE_OBJECT IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject) { PDEVICE_OBJECT deviceObject; // If the file object has a mounted Vpb, use its DeviceObject. if(FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) { deviceObject = FileObject->Vpb->DeviceObject; // Otherwise, if the real device has a VPB that indicates that it is mounted, // then use the file system device object associated with the VPB. } else if(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && FileObject->DeviceObject->Vpb != NULL && FileObject->DeviceObject->Vpb->DeviceObject != NULL ) { deviceObject = FileObject->DeviceObject->Vpb->DeviceObject; // Otherwise, just return the real device object. } else { deviceObject = FileObject->DeviceObject; } ASSERT(deviceObject != NULL); // Simply return the resultant file object. return deviceObject; }