mirror of
https://github.com/reactos/reactos.git
synced 2025-07-26 22:43:52 +00:00
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
svn path=/trunk/; revision=15158
This commit is contained in:
parent
dd19f592a2
commit
2ba13f06b1
1 changed files with 160 additions and 116 deletions
|
@ -2058,7 +2058,7 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
|
||||||
PIO_STACK_LOCATION StackPtr;
|
PIO_STACK_LOCATION StackPtr;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
BOOLEAN LocalEvent;
|
BOOLEAN LocalEvent = FALSE;
|
||||||
PKEVENT Event = NULL;
|
PKEVENT Event = NULL;
|
||||||
|
|
||||||
DPRINT("NtQueryDirectoryFile()\n");
|
DPRINT("NtQueryDirectoryFile()\n");
|
||||||
|
@ -2435,127 +2435,171 @@ NtReadFile(IN HANDLE FileHandle,
|
||||||
IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
|
IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
|
||||||
IN PULONG Key OPTIONAL)
|
IN PULONG Key OPTIONAL)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION StackPtr;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
PIO_STACK_LOCATION StackPtr;
|
||||||
PKEVENT EventObject = NULL;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
|
BOOLEAN LocalEvent = FALSE;
|
||||||
|
PKEVENT EventObject = NULL;
|
||||||
|
|
||||||
DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
|
DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
|
||||||
"IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
|
"IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
|
||||||
IoStatusBlock);
|
|
||||||
|
|
||||||
if (IoStatusBlock == NULL)
|
|
||||||
return STATUS_ACCESS_VIOLATION;
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(FileHandle,
|
|
||||||
FILE_READ_DATA,
|
|
||||||
IoFileObjectType,
|
|
||||||
PreviousMode,
|
|
||||||
(PVOID*)&FileObject,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
|
|
||||||
ObDereferenceObject(FileObject);
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteOffset = &FileObject->CurrentByteOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Event != NULL)
|
|
||||||
{
|
|
||||||
Status = ObReferenceObjectByHandle(Event,
|
|
||||||
SYNCHRONIZE,
|
|
||||||
ExEventObjectType,
|
|
||||||
PreviousMode,
|
|
||||||
(PVOID*)&EventObject,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(FileObject);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeClearEvent(EventObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
|
||||||
FileObject->DeviceObject,
|
|
||||||
Buffer,
|
|
||||||
Length,
|
|
||||||
ByteOffset,
|
|
||||||
EventObject,
|
|
||||||
IoStatusBlock);
|
IoStatusBlock);
|
||||||
}
|
PAGED_CODE();
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
#if 0
|
||||||
Status = _SEH_GetExceptionCode();
|
/* Validate User-Mode Buffers */
|
||||||
}
|
if(PreviousMode != KernelMode)
|
||||||
_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)
|
|
||||||
{
|
{
|
||||||
/* Wait failed. */
|
_SEH_TRY
|
||||||
return Status;
|
{
|
||||||
|
ProbeForWrite(IoStatusBlock,
|
||||||
|
sizeof(IO_STATUS_BLOCK),
|
||||||
|
sizeof(ULONG));
|
||||||
|
ProbeForWrite(Buffer,
|
||||||
|
Length,
|
||||||
|
sizeof(ULONG));
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the Current Byte OFfset */
|
||||||
|
ByteOffset = &FileObject->CurrentByteOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = IoStatusBlock->Status;
|
/* Check for event */
|
||||||
}
|
if (Event)
|
||||||
|
{
|
||||||
|
/* Reference it */
|
||||||
|
Status = ObReferenceObjectByHandle(Event,
|
||||||
|
EVENT_MODIFY_STATE,
|
||||||
|
ExEventObjectType,
|
||||||
|
PreviousMode,
|
||||||
|
(PVOID*)&EventObject,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
KeClearEvent(EventObject);
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
/* 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;
|
||||||
|
|
||||||
|
/* Cleanup if IRP Allocation Failed */
|
||||||
|
if (!NT_SUCCESS(Status) || !Irp)
|
||||||
|
{
|
||||||
|
if (Event) ObDereferenceObject(EventObject);
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
if (Irp)
|
||||||
|
{
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
}
|
||||||
|
return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Call the Driver */
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
if (!LocalEvent)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&FileObject->Event,
|
||||||
|
Executive,
|
||||||
|
PreviousMode,
|
||||||
|
FileObject->Flags & FO_ALERTABLE_IO,
|
||||||
|
NULL);
|
||||||
|
Status = FileObject->FinalStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the Status */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue