2.1.ReactOS系统NtReadFile函数的实现。

NTSTATUS NTAPI NtReadFile(IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject; PIRP Irp; PDEVICE_OBJECT DeviceObject; PIO_STACK_LOCATION StackPtr; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PKEVENT EventObject = NULL; LARGE_INTEGER CapturedByteOffset; ULONG CapturedKey = 0; BOOLEAN Synchronous = FALSE; PMDL Mdl; PAGED_CODE(); CapturedByteOffset.QuadPart = 0; IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Validate User-Mode Buffers */ if(PreviousMode != KernelMode) { _SEH_TRY { /* Probe the status block */ ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe the read buffer */ ProbeForWrite(Buffer, Length, 1); /* Check if we got a byte offset */ if (ByteOffset) { /* Capture and probe it */ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); } /* Capture and probe the key */ if (Key) CapturedKey = ProbeForReadUlong(Key); } _SEH_HANDLE { /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; /* Check for probe failure */ if (!NT_SUCCESS(Status)) return Status; } else { /* Kernel mode: capture directly */ if (ByteOffset) CapturedByteOffset = *ByteOffset; if (Key) CapturedKey = *Key; } /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, FILE_READ_DATA, IoFileObjectType, PreviousMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) return Status; /* Check for event */ if (Event) { /* Reference it */ Status = ObReferenceObjectByHandle(Event, EVENT_MODIFY_STATE, ExEventObjectType, PreviousMode, (PVOID*)&EventObject, NULL); if (!NT_SUCCESS(Status)) { /* Fail */ ObDereferenceObject(FileObject); return Status; } /* Otherwise reset the event */ KeClearEvent(EventObject); } /* Check if we should use Sync IO or not */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { /* Lock the file object */ IopLockFileObject(FileObject); /* Check if we don't have a byte offset avilable */ if (!(ByteOffset) || ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) && (CapturedByteOffset.u.HighPart == -1))) { /* Use the Current Byte Offset instead */ CapturedByteOffset = FileObject->CurrentByteOffset; } /* Rememer we are sync */ Synchronous = TRUE; } else if (!(ByteOffset) && !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) { /* Otherwise, this was async I/O without a byte offset, so fail */ if (EventObject) ObDereferenceObject(EventObject); ObDereferenceObject(FileObject); return STATUS_INVALID_PARAMETER; } /* Get the device object */ DeviceObject = IoGetRelatedDeviceObject(FileObject); /* Clear the File Object's event */ KeClearEvent(&FileObject->Event); /* Allocate the IRP */ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); /* Set the IRP */ Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->RequestorMode = KernelMode; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; Irp->UserIosb = IoStatusBlock; Irp->UserEvent = EventObject; Irp->PendingReturned = FALSE; Irp->Cancel = FALSE; Irp->CancelRoutine = NULL; Irp->AssociatedIrp.SystemBuffer = NULL; Irp->MdlAddress = NULL; /* Set the Stack Data */ StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_READ; StackPtr->FileObject = FileObject; StackPtr->Parameters.Read.Key = CapturedKey; StackPtr->Parameters.Read.Length = Length; StackPtr->Parameters.Read.ByteOffset = CapturedByteOffset; /* Check if this is buffered I/O */ if (DeviceObject->Flags & DO_BUFFERED_IO) { /* Check if we have a buffer length */ if (Length) { /* Enter SEH */ _SEH_TRY { /* Allocate a buffer */ Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB); } _SEH_HANDLE { /* Allocating failed, clean up */ IopCleanupAfterException(FileObject, Irp, NULL, Event); Status = _SEH_GetExceptionCode(); } _SEH_END; if (!NT_SUCCESS(Status)) return Status; /* Set the buffer and flags */ Irp->UserBuffer = Buffer; Irp->Flags = (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION); } else { /* Not reading anything */ Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; } } else if (DeviceObject->Flags & DO_DIRECT_IO) { /* Check if we have a buffer length */ if (Length) { /* Allocate an MDL */ Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); } /* No allocation flags */ Irp->Flags = 0; } else { /* No allocation flags, and use the buffer directly */ Irp->Flags = 0; Irp->UserBuffer = Buffer; } /* Now set the deferred read flags */ Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION); #if 0 /* FIXME: VFAT SUCKS */ if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; #endif /* Perform the call */ return IopPerformSynchronousRequest(DeviceObject, Irp, FileObject, TRUE, PreviousMode, Synchronous, IopReadTransfer); }
上一篇:unity学习-全局光照(GI)


下一篇:Windows 安装Redis(图文详解)