NtQueryInformationFile/NtSetInformationFile:
- Check for information class specific access rights.
- Clean-up some indentation mess.
Modified: trunk/reactos/ntoskrnl/io/file.c

Modified: trunk/reactos/ntoskrnl/io/file.c
--- trunk/reactos/ntoskrnl/io/file.c	2005-04-30 21:11:39 UTC (rev 14892)
+++ trunk/reactos/ntoskrnl/io/file.c	2005-04-30 22:00:26 UTC (rev 14893)
@@ -2150,99 +2150,132 @@
                        ULONG Length,
                        FILE_INFORMATION_CLASS FileInformationClass)
 {
-   PFILE_OBJECT FileObject;
-   NTSTATUS Status;
-   PIRP Irp;
-   PDEVICE_OBJECT DeviceObject;
-   PIO_STACK_LOCATION StackPtr;
-   PVOID SystemBuffer;
-   KPROCESSOR_MODE PreviousMode;
-   
-   ASSERT(IoStatusBlock != NULL);
-   ASSERT(FileInformation != NULL);
-   
-   DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
-   "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
-   Length, FileInformationClass);
+  OBJECT_HANDLE_INFORMATION HandleInformation;
+  PFILE_OBJECT FileObject;
+  NTSTATUS Status;
+  PIRP Irp;
+  PDEVICE_OBJECT DeviceObject;
+  PIO_STACK_LOCATION StackPtr;
+  PVOID SystemBuffer;
+  KPROCESSOR_MODE PreviousMode;
+  BOOLEAN Failed = FALSE;
 
-   PreviousMode = ExGetPreviousMode();
+  ASSERT(IoStatusBlock != NULL);
+  ASSERT(FileInformation != NULL);
 
-   Status = ObReferenceObjectByHandle(FileHandle,
-          0, /* FIXME - access depends on the information class! */
-          IoFileObjectType,
-          PreviousMode,
-          (PVOID *)&FileObject,
-          NULL);
-   if (!NT_SUCCESS(Status))
-     {
- return(Status);
-     }
-   DPRINT("FileObject %x\n", FileObject);
-   
-   DeviceObject = FileObject->DeviceObject;
-   
-   Irp = IoAllocateIrp(DeviceObject->StackSize,
-         TRUE);
-   if (Irp == NULL)
-     {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
-     }
-   
-   SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
-     Length,
-     TAG_SYSB);
-   if (SystemBuffer == NULL)
-     {
- IoFreeIrp(Irp);
- ObDereferenceObject(FileObject);
- return(STATUS_INSUFFICIENT_RESOURCES);
-     }
-   
-   /* Trigger FileObject/Event dereferencing */
-   Irp->Tail.Overlay.OriginalFileObject = FileObject;
-   Irp->RequestorMode = PreviousMode;
-   Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
-   Irp->UserIosb = IoStatusBlock;
-   Irp->UserEvent = &FileObject->Event;
-   Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   KeResetEvent( &FileObject->Event );
-   
-   StackPtr = IoGetNextIrpStackLocation(Irp);
-   StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
-   StackPtr->MinorFunction = 0;
-   StackPtr->Flags = 0;
-   StackPtr->Control = 0;
-   StackPtr->DeviceObject = DeviceObject;
-   StackPtr->FileObject = FileObject;
-   
-   StackPtr->Parameters.QueryFile.FileInformationClass =
-     FileInformationClass;
-   StackPtr->Parameters.QueryFile.Length = Length;
-   
-   Status = IoCallDriver(FileObject->DeviceObject,
-    Irp);
-   if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
-     {
- KeWaitForSingleObject(&FileObject->Event,
-         Executive,
-         PreviousMode,
-         FileObject->Flags & FO_ALERTABLE_IO,
-         NULL);
- Status = IoStatusBlock->Status;
-     }
+  DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+         "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
+         Length, FileInformationClass);
 
+  PreviousMode = ExGetPreviousMode();
+
+  Status = ObReferenceObjectByHandle(FileHandle,
+                                     0,
+                                     IoFileObjectType,
+                                     PreviousMode,
+                                     (PVOID *)&FileObject,
+                                     &HandleInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    return Status;
+  }
+
+  /* Check information class specific access rights */
+  switch (FileInformationClass)
+  {
+    case FileBasicInformation:
+      if (!(HandleInformation.GrantedAccess & FILE_READ_ATTRIBUTES))
+        Failed = TRUE;
+      break;
+
+    case FilePositionInformation:
+      if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
+          !(FileObject->Flags & FO_SYNCHRONOUS_IO))
+        Failed = TRUE;
+      break;
+
+    case FileAlignmentInformation:
+      if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
+        Failed = TRUE;
+      break;
+
+    default:
+      break;
+  }
+
+  if (Failed)
+  {
+    DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
+    ObDereferenceObject(FileObject);
+    return STATUS_ACCESS_DENIED;
+  }
+
+  DPRINT("FileObject %x\n", FileObject);
+
+  DeviceObject = FileObject->DeviceObject;
+
+  Irp = IoAllocateIrp(DeviceObject->StackSize,
+                      TRUE);
+  if (Irp == NULL)
+  {
+    ObDereferenceObject(FileObject);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                       Length,
+                                       TAG_SYSB);
+  if (SystemBuffer == NULL)
+  {
+    IoFreeIrp(Irp);
+    ObDereferenceObject(FileObject);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  /* Trigger FileObject/Event dereferencing */
+  Irp->Tail.Overlay.OriginalFileObject = FileObject;
+  Irp->RequestorMode = PreviousMode;
+  Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+  Irp->UserIosb = IoStatusBlock;
+  Irp->UserEvent = &FileObject->Event;
+  Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+  KeResetEvent(&FileObject->Event);
+
+  StackPtr = IoGetNextIrpStackLocation(Irp);
+  StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
+  StackPtr->MinorFunction = 0;
+  StackPtr->Flags = 0;
+  StackPtr->Control = 0;
+  StackPtr->DeviceObject = DeviceObject;
+  StackPtr->FileObject = FileObject;
+
+  StackPtr->Parameters.QueryFile.FileInformationClass =
+    FileInformationClass;
+  StackPtr->Parameters.QueryFile.Length = Length;
+
+  Status = IoCallDriver(FileObject->DeviceObject,
+                        Irp);
+  if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
+  {
+    KeWaitForSingleObject(&FileObject->Event,
+                          Executive,
+                          PreviousMode,
+                          FileObject->Flags & FO_ALERTABLE_IO,
+                          NULL);
+    Status = IoStatusBlock->Status;
+  }
+
   if (NT_SUCCESS(Status))
-    {
-      DPRINT("Information %lu\n", IoStatusBlock->Information);
-      MmSafeCopyToUser(FileInformation,
-         SystemBuffer,
-         IoStatusBlock->Information);
-    }
+  {
+    DPRINT("Information %lu\n", IoStatusBlock->Information);
+    MmSafeCopyToUser(FileInformation,
+                     SystemBuffer,
+                     IoStatusBlock->Information);
+  }
 
-   ExFreePool(SystemBuffer);
+  ExFreePool(SystemBuffer);
 
-   return Status;
+  return Status;
 }
 
 /*
@@ -2465,134 +2498,171 @@
                      ULONG Length,
                      FILE_INFORMATION_CLASS FileInformationClass)
 {
-   PIO_STACK_LOCATION StackPtr;
-   PFILE_OBJECT FileObject;
-   PDEVICE_OBJECT DeviceObject;
-   PIRP Irp;
-   NTSTATUS Status;
-   PVOID SystemBuffer;
-   KPROCESSOR_MODE PreviousMode;
-   
-   ASSERT(IoStatusBlock != NULL);
-   ASSERT(FileInformation != NULL);
-   
-   DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
-   "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
-   Length, FileInformationClass);
+  OBJECT_HANDLE_INFORMATION HandleInformation;
+  PIO_STACK_LOCATION StackPtr;
+  PFILE_OBJECT FileObject;
+  PDEVICE_OBJECT DeviceObject;
+  PIRP Irp;
+  NTSTATUS Status;
+  PVOID SystemBuffer;
+  KPROCESSOR_MODE PreviousMode;
+  BOOLEAN Failed = FALSE;
 
-   PreviousMode = ExGetPreviousMode();
+  ASSERT(IoStatusBlock != NULL);
+  ASSERT(FileInformation != NULL);
 
-   /*  Get the file object from the file handle  */
-   Status = ObReferenceObjectByHandle(FileHandle,
-          0, /* FIXME - depends on the information class */
-          IoFileObjectType,
-          PreviousMode,
-          (PVOID *)&FileObject,
-          NULL);
-   if (!NT_SUCCESS(Status))
-     {
- return Status;
-     }
-   
-   DPRINT("FileObject %x\n", FileObject);
+  DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+         "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
+         Length, FileInformationClass);
 
-   /* io completion port? */
-   if (FileInformationClass == FileCompletionInformation)
-   {
-      PKQUEUE Queue;
+  PreviousMode = ExGetPreviousMode();
 
-      if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+  /* Get the file object from the file handle */
+  Status = ObReferenceObjectByHandle(FileHandle,
+                                     0,
+                                     IoFileObjectType,
+                                     PreviousMode,
+                                     (PVOID *)&FileObject,
+                                     &HandleInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    return Status;
+  }
+
+  /* Check information class specific access rights */
+  switch (FileInformationClass)
+  {
+    case FileBasicInformation:
+      if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
+        Failed = TRUE;
+      break;
+
+    case FileDispositionInformation:
+      if (!(HandleInformation.GrantedAccess & DELETE))
+        Failed = TRUE;
+      break;
+
+    case FilePositionInformation:
+      if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
+          !(FileObject->Flags & FO_SYNCHRONOUS_IO))
+        Failed = TRUE;
+      break;
+
+    case FileEndOfFileInformation:
+      if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
+        Failed = TRUE;
+      break;
+
+    default:
+      break;
+  }
+
+  if (Failed)
+  {
+    DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
+    ObDereferenceObject(FileObject);
+    return STATUS_ACCESS_DENIED;
+  }
+
+  DPRINT("FileObject %x\n", FileObject);
+
+  /* io completion port? */
+  if (FileInformationClass == FileCompletionInformation)
+  {
+    PKQUEUE Queue;
+
+    if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+    {
+      Status = STATUS_INFO_LENGTH_MISMATCH;
+    }
+    else
+    {
+      Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
+                                         IO_COMPLETION_MODIFY_STATE,//???
+                                         ExIoCompletionType,
+                                         PreviousMode,
+                                         (PVOID*)&Queue,
+                                         NULL);
+      if (NT_SUCCESS(Status))
       {
-         Status = STATUS_INFO_LENGTH_MISMATCH;
-      }
-      else
-      {
-         Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
-                                            IO_COMPLETION_MODIFY_STATE,//???
-                                            ExIoCompletionType,
-                                            PreviousMode,
-                                            (PVOID*)&Queue,
-                                            NULL);
-         if (NT_SUCCESS(Status))
-         {   
-            /* FIXME: maybe use lookaside list */
-            FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
-            FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
-            FileObject->CompletionContext->Port = Queue;
+        /* FIXME: maybe use lookaside list */
+        FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
+        FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
+        FileObject->CompletionContext->Port = Queue;
 
-            ObDereferenceObject(Queue);
-         }
+        ObDereferenceObject(Queue);
       }
+    }
 
-      ObDereferenceObject(FileObject);
-      return Status;
-   }
+    ObDereferenceObject(FileObject);
+    return Status;
+  }
 
-   DeviceObject = FileObject->DeviceObject;
-   
-   Irp = IoAllocateIrp(DeviceObject->StackSize,
-         TRUE);
-   if (Irp == NULL)
-     {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
-     }
-   
-   SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
-     Length,
-     TAG_SYSB);
-   if (SystemBuffer == NULL)
-     {
- IoFreeIrp(Irp);
- ObDereferenceObject(FileObject);
- return(STATUS_INSUFFICIENT_RESOURCES);
-     }
-   
-   MmSafeCopyFromUser(SystemBuffer,
-        FileInformation,
-        Length);
-   
-   /* Trigger FileObject/Event dereferencing */
-   Irp->Tail.Overlay.OriginalFileObject = FileObject;
-   Irp->RequestorMode = PreviousMode;
-   Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
-   Irp->UserIosb = IoStatusBlock;
-   Irp->UserEvent = &FileObject->Event;
-   KeResetEvent( &FileObject->Event );
-   Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   
-   StackPtr = IoGetNextIrpStackLocation(Irp);
-   StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
-   StackPtr->MinorFunction = 0;
-   StackPtr->Flags = 0;
-   StackPtr->Control = 0;
-   StackPtr->DeviceObject = DeviceObject;
-   StackPtr->FileObject = FileObject;
-   
-   StackPtr->Parameters.SetFile.FileInformationClass =
-     FileInformationClass;
-   StackPtr->Parameters.SetFile.Length = Length;
-   
-   /*
-    * Pass the IRP to the FSD (and wait for
-    * it if required)
-    */
-   DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
-   Status = IoCallDriver(FileObject->DeviceObject,
-    Irp);
-   if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
-     {
- KeWaitForSingleObject(&FileObject->Event,
-         Executive,
-         PreviousMode,
-         FileObject->Flags & FO_ALERTABLE_IO,
-         NULL);
- Status = IoStatusBlock->Status;
-     }
+  DeviceObject = FileObject->DeviceObject;
 
-   ExFreePool(SystemBuffer);
+  Irp = IoAllocateIrp(DeviceObject->StackSize,
+                      TRUE);
+  if (Irp == NULL)
+  {
+    ObDereferenceObject(FileObject);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
 
-   return Status;
+  SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                       Length,
+                                       TAG_SYSB);
+  if (SystemBuffer == NULL)
+  {
+    IoFreeIrp(Irp);
+    ObDereferenceObject(FileObject);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  MmSafeCopyFromUser(SystemBuffer,
+                     FileInformation,
+                     Length);
+
+  /* Trigger FileObject/Event dereferencing */
+  Irp->Tail.Overlay.OriginalFileObject = FileObject;
+  Irp->RequestorMode = PreviousMode;
+  Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+  Irp->UserIosb = IoStatusBlock;
+  Irp->UserEvent = &FileObject->Event;
+  KeResetEvent(&FileObject->Event);
+  Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+
+  StackPtr = IoGetNextIrpStackLocation(Irp);
+  StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
+  StackPtr->MinorFunction = 0;
+  StackPtr->Flags = 0;
+  StackPtr->Control = 0;
+  StackPtr->DeviceObject = DeviceObject;
+  StackPtr->FileObject = FileObject;
+
+  StackPtr->Parameters.SetFile.FileInformationClass =
+    FileInformationClass;
+  StackPtr->Parameters.SetFile.Length = Length;
+
+  /*
+   * Pass the IRP to the FSD (and wait for
+   * it if required)
+   */
+  DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
+  Status = IoCallDriver(FileObject->DeviceObject,
+                        Irp);
+  if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
+  {
+    KeWaitForSingleObject(&FileObject->Event,
+                          Executive,
+                          PreviousMode,
+                          FileObject->Flags & FO_ALERTABLE_IO,
+                          NULL);
+    Status = IoStatusBlock->Status;
+  }
+
+  ExFreePool(SystemBuffer);
+
+  return Status;
 }
 
 /*