Fix a previous bug and fix NtReadFile: Read FileObject Status, Set Read
Operation, support IRP_NOCACHE (ReactOS doesn't like this because of
some other bug i'm investigating), use right event reqeuested access,
add SEH
Modified: trunk/reactos/ntoskrnl/io/file.c
_____
Modified: trunk/reactos/ntoskrnl/io/file.c
--- trunk/reactos/ntoskrnl/io/file.c 2005-05-09 00:05:15 UTC (rev
15157)
+++ trunk/reactos/ntoskrnl/io/file.c 2005-05-09 00:33:23 UTC (rev
15158)
@@ -2058,7 +2058,7 @@
PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
- BOOLEAN LocalEvent;
+ BOOLEAN LocalEvent = FALSE;
PKEVENT Event = NULL;
DPRINT("NtQueryDirectoryFile()\n");
@@ -2435,127 +2435,171 @@
IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for
asynch. operations! */
IN PULONG Key OPTIONAL)
{
- NTSTATUS Status;
- PFILE_OBJECT FileObject;
- PIRP Irp = NULL;
- PIO_STACK_LOCATION StackPtr;
- KPROCESSOR_MODE PreviousMode;
- PKEVENT EventObject = NULL;
+ NTSTATUS Status;
+ PFILE_OBJECT FileObject;
+ PIRP Irp = NULL;
+ PDEVICE_OBJECT DeviceObject;
+ PIO_STACK_LOCATION StackPtr;
+ KPROCESSOR_MODE PreviousMode;
+ BOOLEAN LocalEvent = FALSE;
+ PKEVENT EventObject = NULL;
- DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
- "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
- IoStatusBlock);
+ DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x,
"
+ "IoStatusBlock %x)\n", FileHandle, Buffer, Length,
ByteOffset,
+ IoStatusBlock);
+ PAGED_CODE();
+
+ #if 0
+ /* Validate User-Mode Buffers */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(IoStatusBlock,
+ sizeof(IO_STATUS_BLOCK),
+ sizeof(ULONG));
+ ProbeForWrite(Buffer,
+ Length,
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- if (IoStatusBlock == NULL)
- return STATUS_ACCESS_VIOLATION;
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+ #endif
- PreviousMode = ExGetPreviousMode();
+ /* Get File Object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_READ_DATA,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check the Byte Offset */
+ if (!ByteOffset ||
+ (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+ ByteOffset->u.HighPart == 0xffffffff))
+ {
+ /* a valid ByteOffset is required if asynch. op. */
+ if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ {
+ DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_PARAMETER;
+ }
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_READ_DATA,
- IoFileObjectType,
- PreviousMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ /* Use the Current Byte OFfset */
+ ByteOffset = &FileObject->CurrentByteOffset;
+ }
- if (ByteOffset == NULL ||
- (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
- ByteOffset->u.HighPart == 0xffffffff))
- {
- /* a valid ByteOffset is required if asynch. op. */
- if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+ /* Check for event */
+ if (Event)
{
- DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(Event,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID*)&EventObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(FileObject);
+ return Status;
+ }
+ KeClearEvent(EventObject);
}
- ByteOffset = &FileObject->CurrentByteOffset;
- }
+ /* Check if this is a direct open or not */
+ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+ {
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if we should use Sync IO or not */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ {
+ /* Use File Object event */
+ KeClearEvent(&FileObject->Event);
+ }
+ else
+ {
+ LocalEvent = TRUE;
+ }
+
+ /* Create the IRP */
+ _SEH_TRY
+ {
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+ DeviceObject,
+ Buffer,
+ Length,
+ ByteOffset,
+ EventObject,
+ IoStatusBlock);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- if (Event != NULL)
- {
- Status = ObReferenceObjectByHandle(Event,
- SYNCHRONIZE,
- ExEventObjectType,
- PreviousMode,
- (PVOID*)&EventObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
+ /* Cleanup if IRP Allocation Failed */
+ if (!NT_SUCCESS(Status) || !Irp)
+ {
+ if (Event) ObDereferenceObject(EventObject);
ObDereferenceObject(FileObject);
- return Status;
- }
+ if (Irp)
+ {
+ IoFreeIrp(Irp);
+ }
+ return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES :
Status;
+ }
- KeClearEvent(EventObject);
- }
+ /* Set up IRP Data */
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = PreviousMode;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+ Irp->Flags |= IRP_READ_OPERATION;
+
+ /* FIXME: Somethign weird is going on when I enable this. */
+ //if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags
|= IRP_NOCACHE;
+
+ /* Setup Stack Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->FileObject = FileObject;
+ StackPtr->Parameters.Read.Key = Key ? *Key : 0;
+ StackPtr->Parameters.Read.Length = Length;
+ StackPtr->Parameters.Read.ByteOffset = *ByteOffset;
- _SEH_TRY
- {
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
- FileObject->DeviceObject,
- Buffer,
- Length,
- ByteOffset,
- EventObject,
- IoStatusBlock);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if (!NT_SUCCESS(Status) || Irp == NULL)
- {
- if (Event)
- {
- ObDereferenceObject(&EventObject);
- }
- ObDereferenceObject(FileObject);
- if (Irp)
- {
- IoFreeIrp(Irp);
- }
- return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES :
Status;
- }
-
- KeClearEvent(&FileObject->Event);
-
- /* Trigger FileObject/Event dereferencing */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
- Irp->RequestorMode = PreviousMode;
-
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
- Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
- StackPtr->Parameters.Read.Key = Key ? *Key : 0;
-
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING && (FileObject->Flags &
FO_SYNCHRONOUS_IO))
- {
- Status = KeWaitForSingleObject(&FileObject->Event,
- Executive,
- PreviousMode,
- FileObject->Flags & FO_ALERTABLE_IO,
- NULL);
- if (Status != STATUS_WAIT_0)
+ /* Call the Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- /* Wait failed. */
- return Status;
+ if (!LocalEvent)
+ {
+ KeWaitForSingleObject(&FileObject->Event,
+ Executive,
+ PreviousMode,
+ FileObject->Flags & FO_ALERTABLE_IO,
+ NULL);
+ Status = FileObject->FinalStatus;
+ }
}
- Status = IoStatusBlock->Status;
- }
-
- return Status;
+ /* Return the Status */
+ return Status;
}
/*