感觉IoCreateFile应该算是系统调用,它会调用ObCreateObject函数。
IoCreateFile和IoCreateDevice都会调用ObCreateObject函数。
在中IoCreateFile中,
Status = ObCreateObject(FileHandle, |
在中IoCreateDevice中
if (DeviceName != NULL) |
ObCreateObject的过程大概如下:
1.调用ObFindObject能返回Parent对象、RemainingPath。其中ObFindObject会反复parse对象名,分析出RemainingPath。
2.ObCreateObject会根据传进来的Type,即IoFileObjectType或者IoDeviceObjectType 然后调用Create函数。
如果是IoFileObjectType则调用IopCreateFile
3.调用ObCreateHandle去创建handle,handle是与进程相关的。
下面对IopCreateFile进行注解.
NTSTATUS STDCALL IopCreateFile(PVOID ObjectBody, PVOID Parent, PWSTR RemainingPath, POBJECT_ATTRIBUTES ObjectAttributes) { PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Parent;//Parent肯定是设备对象。 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody; NTSTATUS Status; DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n", ObjectBody, Parent, RemainingPath); if (NULL == DeviceObject) { /* This is probably an attempt to create a meta fileobject (eg. for FAT) for the cache manager, so return STATUS_SUCCESS */ DPRINT("DeviceObject was NULL\n"); return(STATUS_SUCCESS); } if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType)//Parent肯定是设备对象。 { CPRINT("Parent is a %S which is not a device type\n", BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer); return(STATUS_UNSUCCESSFUL); }
//对设备对象进行reference Status = ObReferenceObjectByPointer(DeviceObject, STANDARD_RIGHTS_REQUIRED, IoDeviceObjectType, UserMode); if (!NT_SUCCESS(Status)) { CPRINT("Failed to reference device object %x\n", DeviceObject); return(Status); } //得到下层的设备对象 DeviceObject = IoGetAttachedDevice(DeviceObject); DPRINT("DeviceObject %x\n", DeviceObject); if (NULL == RemainingPath) { FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN; FileObject->FileName.Buffer = 0; FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0; } else {
//设备对象类型一定是下列类型之一。 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM) && (DeviceObject->DeviceType != FILE_DEVICE_DISK) && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) && (DeviceObject->DeviceType != FILE_DEVICE_TAPE) && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK) && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE) && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT)) { CPRINT("Device was wrong type\n"); return(STATUS_UNSUCCESSFUL); } if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE) && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT)) {
//如果是上述类型,并且没有被mount,则进行mount if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED)) { DPRINT("Mount the logical volume\n"); Status = IoMountVolume(DeviceObject, FALSE); DPRINT("Status %x\n", Status); if (!NT_SUCCESS(Status)) { CPRINT("Failed to mount logical volume (Status %x)\n", Status); return(Status); } } DeviceObject = DeviceObject->Vpb->DeviceObject; DPRINT("FsDeviceObject %lx\n", DeviceObject); } RtlCreateUnicodeString(&(FileObject->FileName), RemainingPath); } DPRINT("FileObject->FileName %wZ\n", &FileObject->FileName); FileObject->DeviceObject = DeviceObject; DPRINT("FileObject %x DeviceObject %x\n", FileObject, DeviceObject); FileObject->Vpb = DeviceObject->Vpb; FileObject->Type = InternalFileType; return(STATUS_SUCCESS); }