- if a file object is a named pipe don't allow the FILE_APPEND_DATA access right as it equals FILE_CREATE_PIPE_INSTANCE (NtFlushBuffersFile and NtWriteFile)

- add more parameters probing and capturing code

svn path=/trunk/; revision=18932
This commit is contained in:
Thomas Bluemel 2005-11-01 16:17:25 +00:00
parent 6e138c7f47
commit 0ecd041efc

View file

@ -755,7 +755,6 @@ IoCreateFile(OUT PHANDLE FileHandle,
IO_SECURITY_CONTEXT SecurityContext; IO_SECURITY_CONTEXT SecurityContext;
KPROCESSOR_MODE AccessMode; KPROCESSOR_MODE AccessMode;
HANDLE LocalHandle; HANDLE LocalHandle;
IO_STATUS_BLOCK LocalIoStatusBlock;
LARGE_INTEGER SafeAllocationSize; LARGE_INTEGER SafeAllocationSize;
PVOID SystemEaBuffer = NULL; PVOID SystemEaBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -988,7 +987,7 @@ IoCreateFile(OUT PHANDLE FileHandle,
//trigger FileObject/Event dereferencing //trigger FileObject/Event dereferencing
Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->RequestorMode = AccessMode; Irp->RequestorMode = AccessMode;
Irp->UserIosb = &LocalIoStatusBlock; Irp->UserIosb = IoStatusBlock;
Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer; Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL; Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.Thread = PsGetCurrentThread();
@ -1054,7 +1053,7 @@ IoCreateFile(OUT PHANDLE FileHandle,
AccessMode, AccessMode,
FALSE, FALSE,
NULL); NULL);
Status = LocalIoStatusBlock.Status; Status = IoStatusBlock->Status;
} }
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1069,7 +1068,6 @@ IoCreateFile(OUT PHANDLE FileHandle,
_SEH_TRY _SEH_TRY
{ {
*FileHandle = LocalHandle; *FileHandle = LocalHandle;
*IoStatusBlock = LocalIoStatusBlock;
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -1380,20 +1378,41 @@ STDCALL
NtCancelIoFile(IN HANDLE FileHandle, NtCancelIoFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock) OUT PIO_STATUS_BLOCK IoStatusBlock)
{ {
NTSTATUS Status;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PETHREAD Thread; PETHREAD Thread;
PIRP Irp; PIRP Irp;
KIRQL OldIrql; KIRQL OldIrql;
BOOLEAN OurIrpsInList = FALSE; BOOLEAN OurIrpsInList = FALSE;
LARGE_INTEGER Interval; LARGE_INTEGER Interval;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
if ((ULONG_PTR)IoStatusBlock >= (ULONG_PTR)MmUserProbeAddress && PAGED_CODE();
KeGetPreviousMode() != KernelMode)
return STATUS_ACCESS_VIOLATION;
Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType, PreviousMode = KeGetPreviousMode();
KeGetPreviousMode(), (PVOID*)&FileObject,
if (PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}
Status = ObReferenceObjectByHandle(FileHandle,
0,
IoFileObjectType,
PreviousMode,
(PVOID*)&FileObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return Status; return Status;
@ -1531,23 +1550,39 @@ NtCreateMailslotFile(OUT PHANDLE FileHandle,
MAILSLOT_CREATE_PARAMETERS Buffer; MAILSLOT_CREATE_PARAMETERS Buffer;
DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, " DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
"ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n", "ObjectAttributes 0x%p)\n",
FileHandle,DesiredAccess,ObjectAttributes, FileHandle,DesiredAccess,ObjectAttributes);
ObjectAttributes->ObjectName->Buffer);
PAGED_CODE(); PAGED_CODE();
/* Check for Timeout */ /* Check for Timeout */
if (TimeOut) if (TimeOut != NULL)
{ {
/* Enable it */ if (KeGetPreviousMode() != KernelMode)
Buffer.TimeoutSpecified = TRUE; {
NTSTATUS Status = STATUS_SUCCESS;
/* FIXME: Add SEH */ _SEH_TRY
Buffer.ReadTimeout = *TimeOut; {
Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}
else
{
Buffer.ReadTimeout = *TimeOut;
}
Buffer.TimeoutSpecified = TRUE;
} }
else else
{ {
/* No timeout */
Buffer.TimeoutSpecified = FALSE; Buffer.TimeoutSpecified = FALSE;
} }
@ -1592,25 +1627,39 @@ NtCreateNamedPipeFile(PHANDLE FileHandle,
NAMED_PIPE_CREATE_PARAMETERS Buffer; NAMED_PIPE_CREATE_PARAMETERS Buffer;
DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, " DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
"ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n", "ObjectAttributes 0x%p)\n",
FileHandle,DesiredAccess,ObjectAttributes, FileHandle,DesiredAccess,ObjectAttributes);
ObjectAttributes->ObjectName->Buffer);
PAGED_CODE(); PAGED_CODE();
/* Check for Timeout */ /* Check for Timeout */
if (DefaultTimeout) if (DefaultTimeout != NULL)
{ {
/* Enable it */ if (KeGetPreviousMode() != KernelMode)
Buffer.TimeoutSpecified = TRUE; {
NTSTATUS Status = STATUS_SUCCESS;
/* FIXME: Add SEH */ _SEH_TRY
Buffer.DefaultTimeout = *DefaultTimeout; {
Buffer.DefaultTimeout = ProbeForReadLargeInteger(DefaultTimeout);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}
else
{
Buffer.DefaultTimeout = *DefaultTimeout;
}
Buffer.TimeoutSpecified = TRUE;
} }
else else
{
/* No timeout */
Buffer.TimeoutSpecified = FALSE; Buffer.TimeoutSpecified = FALSE;
}
/* Set Settings */ /* Set Settings */
Buffer.NamedPipeType = NamedPipeType; Buffer.NamedPipeType = NamedPipeType;
@ -1724,6 +1773,8 @@ NTSTATUS
STDCALL STDCALL
NtFlushWriteBuffer(VOID) NtFlushWriteBuffer(VOID)
{ {
PAGED_CODE();
KeFlushWriteBuffer(); KeFlushWriteBuffer();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1746,20 +1797,56 @@ NtFlushBuffersFile(IN HANDLE FileHandle,
PFILE_OBJECT FileObject = NULL; PFILE_OBJECT FileObject = NULL;
PIRP Irp; PIRP Irp;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
NTSTATUS Status; NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
KEVENT Event; KEVENT Event;
BOOLEAN LocalEvent = FALSE; BOOLEAN LocalEvent = FALSE;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
KPROCESSOR_MODE PreviousMode;
PAGED_CODE();
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}
/* Get the File Object */ /* Get the File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
FILE_WRITE_DATA, 0,
NULL, IoFileObjectType,
PreviousMode, PreviousMode,
(PVOID*)&FileObject, (PVOID*)&FileObject,
NULL); &ObjectHandleInfo);
if (Status != STATUS_SUCCESS) return(Status); if (!NT_SUCCESS(Status)) return(Status);
/* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
granted. However, if this is a named pipe, make sure we don't ask for
FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
access right! */
if (!(FileObject->Flags & FO_NAMED_PIPE))
DesiredAccess |= FILE_APPEND_DATA;
if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
DesiredAccess))
{
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
/* Check if this is a direct open or not */ /* Check if this is a direct open or not */
if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
@ -1968,12 +2055,17 @@ NtLockFile(IN HANDLE FileHandle,
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
PKEVENT Event = NULL; PKEVENT Event = NULL;
BOOLEAN LocalEvent = FALSE; BOOLEAN LocalEvent = FALSE;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER CapturedByteOffset, CapturedLength;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
OBJECT_HANDLE_INFORMATION HandleInformation; OBJECT_HANDLE_INFORMATION HandleInformation;
/* FIXME: instead of this, use SEH */ PAGED_CODE();
if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
PreviousMode = KeGetPreviousMode();
CapturedByteOffset.QuadPart = 0;
CapturedLength.QuadPart = 0;
/* Get File Object */ /* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
@ -1984,12 +2076,41 @@ NtLockFile(IN HANDLE FileHandle,
&HandleInformation); &HandleInformation);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Must have FILE_READ_DATA | FILE_WRITE_DATA access */ if (PreviousMode != KernelMode)
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
{ {
DPRINT1("Invalid access rights\n"); /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless
ObDereferenceObject(FileObject); we're in KernelMode! */
return STATUS_ACCESS_DENIED; if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
{
DPRINT1("Invalid access rights\n");
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
_SEH_TRY
{
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
CapturedLength = ProbeForReadLargeInteger(Length);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(FileObject);
return Status;
}
}
else
{
CapturedByteOffset = *ByteOffset;
CapturedLength = *Length;
} }
/* Get Event Object */ /* Get Event Object */
@ -2043,7 +2164,7 @@ NtLockFile(IN HANDLE FileHandle,
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
*LocalLength = *Length; *LocalLength = CapturedLength;
/* Set up the IRP */ /* Set up the IRP */
Irp->RequestorMode = PreviousMode; Irp->RequestorMode = PreviousMode;
@ -2060,8 +2181,8 @@ NtLockFile(IN HANDLE FileHandle,
/* Set Parameters */ /* Set Parameters */
StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.Length = LocalLength;
StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset; StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
StackPtr->Parameters.LockControl.Key = Key ? Key : 0; StackPtr->Parameters.LockControl.Key = Key;
/* Set Flags */ /* Set Flags */
if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY; if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
@ -2709,7 +2830,7 @@ NtReadFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer, OUT PVOID Buffer,
IN ULONG Length, IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */ IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL) IN PULONG Key OPTIONAL)
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -2717,14 +2838,19 @@ NtReadFile(IN HANDLE FileHandle,
PIRP Irp = NULL; PIRP Irp = NULL;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
BOOLEAN LocalEvent = FALSE; BOOLEAN LocalEvent = FALSE;
PKEVENT EventObject = NULL; PKEVENT EventObject = NULL;
LARGE_INTEGER CapturedByteOffset;
DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, " DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
"IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset, "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
IoStatusBlock); IoStatusBlock);
PAGED_CODE(); PAGED_CODE();
PreviousMode = KeGetPreviousMode();
CapturedByteOffset.QuadPart = 0;
/* Validate User-Mode Buffers */ /* Validate User-Mode Buffers */
if(PreviousMode != KernelMode) if(PreviousMode != KernelMode)
@ -2734,11 +2860,14 @@ NtReadFile(IN HANDLE FileHandle,
ProbeForWrite(IoStatusBlock, ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK), sizeof(IO_STATUS_BLOCK),
sizeof(ULONG)); sizeof(ULONG));
#if 0
ProbeForWrite(Buffer, ProbeForWrite(Buffer,
Length, Length,
sizeof(ULONG)); 1);
#endif if (ByteOffset != NULL)
{
CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
}
/* FIXME - probe other pointers and capture information */
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -2748,6 +2877,13 @@ NtReadFile(IN HANDLE FileHandle,
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
else
{
if (ByteOffset != NULL)
{
CapturedByteOffset = *ByteOffset;
}
}
/* Get File Object */ /* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
@ -2759,9 +2895,9 @@ NtReadFile(IN HANDLE FileHandle,
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Check the Byte Offset */ /* Check the Byte Offset */
if (!ByteOffset || if (ByteOffset == NULL ||
(ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION && (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
ByteOffset->u.HighPart == -1)) CapturedByteOffset.u.HighPart == -1))
{ {
/* 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))
@ -2772,7 +2908,7 @@ NtReadFile(IN HANDLE FileHandle,
} }
/* Use the Current Byte OFfset */ /* Use the Current Byte OFfset */
ByteOffset = &FileObject->CurrentByteOffset; CapturedByteOffset = FileObject->CurrentByteOffset;
} }
/* Check for event */ /* Check for event */
@ -2821,7 +2957,7 @@ NtReadFile(IN HANDLE FileHandle,
DeviceObject, DeviceObject,
Buffer, Buffer,
Length, Length,
ByteOffset, &CapturedByteOffset,
EventObject, EventObject,
IoStatusBlock); IoStatusBlock);
if (Irp == NULL) if (Irp == NULL)
@ -3276,7 +3412,7 @@ NtUnlockFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER ByteOffset,
IN PLARGE_INTEGER Length, IN PLARGE_INTEGER Length,
OUT ULONG Key OPTIONAL) IN ULONG Key OPTIONAL)
{ {
PFILE_OBJECT FileObject = NULL; PFILE_OBJECT FileObject = NULL;
PLARGE_INTEGER LocalLength = NULL; PLARGE_INTEGER LocalLength = NULL;
@ -3285,12 +3421,17 @@ NtUnlockFile(IN HANDLE FileHandle,
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
KEVENT Event; KEVENT Event;
BOOLEAN LocalEvent = FALSE; BOOLEAN LocalEvent = FALSE;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
LARGE_INTEGER CapturedByteOffset, CapturedLength;
OBJECT_HANDLE_INFORMATION HandleInformation; OBJECT_HANDLE_INFORMATION HandleInformation;
/* FIXME: instead of this, use SEH */ PAGED_CODE();
if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
PreviousMode = KeGetPreviousMode();
CapturedByteOffset.QuadPart = 0;
CapturedLength.QuadPart = 0;
/* Get File Object */ /* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
@ -3301,12 +3442,41 @@ NtUnlockFile(IN HANDLE FileHandle,
&HandleInformation); &HandleInformation);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Must have FILE_READ_DATA | FILE_WRITE_DATA access */ if (PreviousMode != KernelMode)
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
{ {
DPRINT1("Invalid access rights\n"); /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
ObDereferenceObject(FileObject); in KernelMode! */
return STATUS_ACCESS_DENIED; if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
{
DPRINT1("Invalid access rights\n");
ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED;
}
_SEH_TRY
{
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
CapturedLength = ProbeForReadLargeInteger(Length);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(FileObject);
return Status;
}
}
else
{
CapturedByteOffset = *ByteOffset;
CapturedLength = *Length;
} }
/* Check if this is a direct open or not */ /* Check if this is a direct open or not */
@ -3349,7 +3519,7 @@ NtUnlockFile(IN HANDLE FileHandle,
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
*LocalLength = *Length; *LocalLength = CapturedLength;
/* Set up the IRP */ /* Set up the IRP */
Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
@ -3367,8 +3537,8 @@ NtUnlockFile(IN HANDLE FileHandle,
/* Set Parameters */ /* Set Parameters */
StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.Length = LocalLength;
StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset; StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
StackPtr->Parameters.LockControl.Key = Key ? Key : 0; StackPtr->Parameters.LockControl.Key = Key;
/* Call the Driver */ /* Call the Driver */
Status = IoCallDriver(DeviceObject, Irp); Status = IoCallDriver(DeviceObject, Irp);
@ -3424,34 +3594,49 @@ 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; OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PIRP Irp = NULL; PIRP Irp = NULL;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
BOOLEAN LocalEvent = FALSE; BOOLEAN LocalEvent = FALSE;
PKEVENT EventObject = NULL; PKEVENT EventObject = NULL;
LARGE_INTEGER CapturedByteOffset;
ULONG CapturedKey = 0;
ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, " DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
"IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset, "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
IoStatusBlock); IoStatusBlock);
PAGED_CODE();
PreviousMode = KeGetPreviousMode();
CapturedByteOffset.QuadPart = 0;
/* Validate User-Mode Buffers */ /* Validate User-Mode Buffers */
if(PreviousMode != KernelMode) if(PreviousMode != KernelMode)
{ {
_SEH_TRY _SEH_TRY
{ {
#if 0
ProbeForWrite(IoStatusBlock, ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK), sizeof(IO_STATUS_BLOCK),
sizeof(ULONG)); sizeof(ULONG));
ProbeForRead(Buffer, ProbeForRead(Buffer,
Length, Length,
sizeof(ULONG)); 1);
#endif if (ByteOffset != NULL)
{
CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
}
if (Key != NULL)
{
CapturedKey = ProbeForReadUlong(Key);
}
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -3461,6 +3646,17 @@ NtWriteFile (IN HANDLE FileHandle,
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
else
{
if (ByteOffset != NULL)
{
CapturedByteOffset = *ByteOffset;
}
if (Key != NULL)
{
CapturedKey = *Key;
}
}
/* Get File Object */ /* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
@ -3468,24 +3664,29 @@ NtWriteFile (IN HANDLE FileHandle,
IoFileObjectType, IoFileObjectType,
PreviousMode, PreviousMode,
(PVOID*)&FileObject, (PVOID*)&FileObject,
&HandleInformation); &ObjectHandleInfo);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */ /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA))) granted. However, if this is a named pipe, make sure we don't ask for
FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
access right! */
if (!(FileObject->Flags & FO_NAMED_PIPE))
DesiredAccess |= FILE_APPEND_DATA;
if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
DesiredAccess))
{ {
DPRINT1("Invalid access rights\n");
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
} }
/* Check if we got write Access */ /* Check if we got write Access */
if (HandleInformation.GrantedAccess & FILE_WRITE_DATA) if (ObjectHandleInfo.GrantedAccess & FILE_WRITE_DATA)
{ {
/* Check the Byte Offset */ /* Check the Byte Offset */
if (!ByteOffset || if (ByteOffset == NULL ||
(ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION && (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
ByteOffset->u.HighPart == -1)) CapturedByteOffset.u.HighPart == -1))
{ {
/* 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))
@ -3496,10 +3697,11 @@ NtWriteFile (IN HANDLE FileHandle,
} }
/* Use the Current Byte OFfset */ /* Use the Current Byte OFfset */
ByteOffset = &FileObject->CurrentByteOffset; CapturedByteOffset = FileObject->CurrentByteOffset;
} }
} }
else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA) else if ((ObjectHandleInfo.GrantedAccess & FILE_APPEND_DATA) &&
!(FileObject->Flags & FO_NAMED_PIPE))
{ {
/* 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))
@ -3510,8 +3712,8 @@ NtWriteFile (IN HANDLE FileHandle,
} }
/* Give the drivers somethign to understand */ /* Give the drivers somethign to understand */
ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE; CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
ByteOffset->u.HighPart = 0xffffffff; CapturedByteOffset.u.HighPart = 0xffffffff;
} }
/* Check if we got an event */ /* Check if we got an event */
@ -3560,7 +3762,7 @@ NtWriteFile (IN HANDLE FileHandle,
DeviceObject, DeviceObject,
Buffer, Buffer,
Length, Length,
ByteOffset, &CapturedByteOffset,
EventObject, EventObject,
IoStatusBlock); IoStatusBlock);
if (Irp == NULL) if (Irp == NULL)
@ -3601,7 +3803,7 @@ NtWriteFile (IN HANDLE FileHandle,
/* Setup Stack Data */ /* 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 = CapturedKey;
if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH; if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
/* Call the Driver */ /* Call the Driver */