NtWriteFile must append to file if it was opened with the FILE_APPEND_DATA access.

FILE_WRITE_DATA take precedence over FILE_APPEND_DATA.

svn path=/trunk/; revision=11101
This commit is contained in:
Eric Kohl 2004-09-28 10:51:05 +00:00
parent 3d82d976d3
commit d394870def

View file

@ -1,4 +1,4 @@
/* $Id: rw.c,v 1.54 2004/08/15 16:39:03 chorns Exp $ /* $Id: rw.c,v 1.55 2004/09/28 10:51:05 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -66,10 +66,10 @@ NtReadFile (IN HANDLE FileHandle,
(PVOID*)&FileObject, (PVOID*)&FileObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return Status;
} }
if (ByteOffset == NULL) if (ByteOffset == NULL)
{ {
/* a valid ByteOffset is required if asynch. op. */ /* a valid ByteOffset is required if asynch. op. */
@ -85,17 +85,18 @@ NtReadFile (IN HANDLE FileHandle,
if (Event != NULL) if (Event != NULL)
{ {
Status = ObReferenceObjectByHandle(Event, Status = ObReferenceObjectByHandle(Event,
SYNCHRONIZE, SYNCHRONIZE,
ExEventObjectType, ExEventObjectType,
PreviousMode, PreviousMode,
(PVOID*)&EventObject, (PVOID*)&EventObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return(Status); return Status;
} }
KeClearEvent(EventObject); KeClearEvent(EventObject);
} }
@ -124,16 +125,15 @@ NtReadFile (IN HANDLE FileHandle,
Status = IoCallDriver(FileObject->DeviceObject, Irp); Status = IoCallDriver(FileObject->DeviceObject, Irp);
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO)) if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
{ {
Status = KeWaitForSingleObject (&FileObject->Event, Status = KeWaitForSingleObject(&FileObject->Event,
Executive, Executive,
PreviousMode, PreviousMode,
FileObject->Flags & FO_ALERTABLE_IO, FileObject->Flags & FO_ALERTABLE_IO,
NULL); NULL);
if (Status != STATUS_WAIT_0) if (Status != STATUS_WAIT_0)
{ {
/* Wait failed. */ /* Wait failed. */
return(Status); return Status;
} }
Status = IoStatusBlock->Status; Status = IoStatusBlock->Status;
@ -168,12 +168,14 @@ NtWriteFile (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)
{ {
OBJECT_HANDLE_INFORMATION HandleInformation;
NTSTATUS Status; NTSTATUS Status;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PIRP Irp; PIRP Irp;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode;
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,
@ -185,17 +187,40 @@ NtWriteFile (IN HANDLE FileHandle,
PreviousMode = ExGetPreviousMode(); PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
FILE_WRITE_DATA, 0,
IoFileObjectType, IoFileObjectType,
PreviousMode, PreviousMode,
(PVOID*)&FileObject, (PVOID*)&FileObject,
NULL); &HandleInformation);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return Status;
} }
if (ByteOffset == NULL) /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
{
DPRINT1("Invalid access rights\n");
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
{
if (ByteOffset == NULL)
{
/* a valid ByteOffset is required if asynch. op. */
if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
{
DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
ObDereferenceObject(FileObject);
return STATUS_INVALID_PARAMETER;
}
ByteOffset = &FileObject->CurrentByteOffset;
}
}
else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
{ {
/* 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))
@ -205,27 +230,28 @@ NtWriteFile (IN HANDLE FileHandle,
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
ByteOffset = &FileObject->CurrentByteOffset; Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
Offset.u.HighPart = 0xffffffff;
ByteOffset = &Offset;
} }
if (Event != NULL) if (Event != NULL)
{ {
Status = ObReferenceObjectByHandle(Event, Status = ObReferenceObjectByHandle(Event,
SYNCHRONIZE, SYNCHRONIZE,
ExEventObjectType, ExEventObjectType,
PreviousMode, PreviousMode,
(PVOID*)&EventObject, (PVOID*)&EventObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return(Status); return Status;
} }
KeClearEvent(EventObject); KeClearEvent(EventObject);
} }
KeClearEvent(&FileObject->Event); KeClearEvent(&FileObject->Event);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
@ -250,21 +276,21 @@ NtWriteFile (IN HANDLE FileHandle,
Status = IoCallDriver(FileObject->DeviceObject, Irp); Status = IoCallDriver(FileObject->DeviceObject, Irp);
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO)) 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)
{ {
Status = KeWaitForSingleObject (&FileObject->Event, /* Wait failed. */
Executive, return Status;
PreviousMode,
FileObject->Flags & FO_ALERTABLE_IO,
NULL);
if (Status != STATUS_WAIT_0)
{
/* Wait failed. */
return(Status);
}
Status = IoStatusBlock->Status;
} }
Status = IoStatusBlock->Status;
}
return Status; return Status;
} }