Fix NtWriteFile: Get right Deviceobject, Use FileObject->FinalStatus, use FileObject-.CurrentByteOffset if ByteOffset == FILE_USER_FILE_POINTER_POSITION, add SEH, use right event requested access, set IRP_WRITE_OPERATION flag, add support for IRP_NOCACHE and add support for SL_WRITE_THROUGH if FO_WRITE_THROUGH is enabled.

svn path=/trunk/; revision=15175
This commit is contained in:
Alex Ionescu 2005-05-09 02:15:03 +00:00
parent 71b6d3cb0f
commit 02a4600eb8

View file

@ -2958,33 +2958,50 @@ NtWriteFile (IN HANDLE FileHandle,
IN PULONG Key OPTIONAL) IN PULONG Key OPTIONAL)
{ {
OBJECT_HANDLE_INFORMATION HandleInformation; OBJECT_HANDLE_INFORMATION HandleInformation;
NTSTATUS Status; NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PIRP Irp = NULL; PIRP Irp = NULL;
PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
BOOLEAN LocalEvent = FALSE;
PKEVENT EventObject = NULL; PKEVENT EventObject = NULL;
LARGE_INTEGER Offset;
DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, " DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
"IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset, "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
IoStatusBlock); IoStatusBlock);
if (IoStatusBlock == NULL) /* Validate User-Mode Buffers */
return STATUS_ACCESS_VIOLATION; if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
#if 0
ProbeForRead(Buffer,
Length,
sizeof(ULONG));
#endif
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
PreviousMode = ExGetPreviousMode(); if(!NT_SUCCESS(Status)) return Status;
}
/* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
0, 0,
IoFileObjectType, IoFileObjectType,
PreviousMode, PreviousMode,
(PVOID*)&FileObject, (PVOID*)&FileObject,
&HandleInformation); &HandleInformation);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
return Status;
}
/* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */ /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA))) if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
@ -2994,18 +3011,23 @@ NtWriteFile (IN HANDLE FileHandle,
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
} }
/* Check if we got write Access */
if (HandleInformation.GrantedAccess & FILE_WRITE_DATA) if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
{ {
if (ByteOffset == NULL) /* 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. */ /* a valid ByteOffset is required if asynch. op. */
if (!(FileObject->Flags & FO_SYNCHRONOUS_IO)) if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
{ {
DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n"); DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
/* Use the Current Byte OFfset */
ByteOffset = &FileObject->CurrentByteOffset; ByteOffset = &FileObject->CurrentByteOffset;
} }
} }
@ -3019,15 +3041,17 @@ NtWriteFile (IN HANDLE FileHandle,
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE; /* Give the drivers somethign to understand */
Offset.u.HighPart = 0xffffffff; ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
ByteOffset = &Offset; ByteOffset->u.HighPart = 0xffffffff;
} }
if (Event != NULL) /* Check if we got an event */
if (Event)
{ {
/* Reference it */
Status = ObReferenceObjectByHandle(Event, Status = ObReferenceObjectByHandle(Event,
SYNCHRONIZE, EVENT_MODIFY_STATE,
ExEventObjectType, ExEventObjectType,
PreviousMode, PreviousMode,
(PVOID*)&EventObject, (PVOID*)&EventObject,
@ -3037,10 +3061,31 @@ NtWriteFile (IN HANDLE FileHandle,
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return Status; return Status;
} }
KeClearEvent(EventObject); KeClearEvent(EventObject);
} }
/* 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;
}
/* Build the IRP */
_SEH_TRY _SEH_TRY
{ {
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
@ -3057,51 +3102,48 @@ NtWriteFile (IN HANDLE FileHandle,
} }
_SEH_END; _SEH_END;
if (!NT_SUCCESS(Status) || Irp == NULL) /* Cleanup on failure */
if (!NT_SUCCESS(Status) || !Irp)
{ {
if (Event) if (Event)
{ {
ObDereferenceObject(&EventObject); ObDereferenceObject(&EventObject);
} }
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
if (Irp) if (Irp) IoFreeIrp(Irp);
{
IoFreeIrp(Irp);
}
return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status; return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
} }
KeClearEvent(&FileObject->Event); /* Set up IRP Data */
/* Trigger FileObject/Event dereferencing */
Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->RequestorMode = PreviousMode; Irp->RequestorMode = PreviousMode;
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
Irp->Flags |= IRP_WRITE_OPERATION;
if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
/* Setup Stack Data */
StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->FileObject = FileObject; StackPtr->FileObject = FileObject;
StackPtr->Parameters.Write.Key = Key ? *Key : 0; StackPtr->Parameters.Write.Key = Key ? *Key : 0;
if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
Status = IoCallDriver(FileObject->DeviceObject, Irp); /* Call the Driver */
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO)) Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{ {
Status = KeWaitForSingleObject(&FileObject->Event, if (!LocalEvent)
{
KeWaitForSingleObject(&FileObject->Event,
Executive, Executive,
PreviousMode, PreviousMode,
FileObject->Flags & FO_ALERTABLE_IO, FileObject->Flags & FO_ALERTABLE_IO,
NULL); NULL);
if (Status != STATUS_WAIT_0) Status = FileObject->FinalStatus;
{ }
/* Wait failed. */
return Status;
}
Status = IoStatusBlock->Status;
} }
/* Return the Status */
return Status; return Status;
} }