Fix NtQueryInformationFile. Use right device object in case of FO_DIRECT_DEVICE_OPEN, use local event, set proper flags so that the I/O manager does the copying and freeing of the buffers, respect syyncronous I/O. Same kind of fixes for IoQueryFileInformation
Modified: trunk/reactos/ntoskrnl/io/file.c

Modified: trunk/reactos/ntoskrnl/io/file.c
--- trunk/reactos/ntoskrnl/io/file.c	2005-05-01 23:19:48 UTC (rev 14940)
+++ trunk/reactos/ntoskrnl/io/file.c	2005-05-02 05:15:20 UTC (rev 14941)
@@ -1131,75 +1131,90 @@
                        OUT PVOID FileInformation,
                        OUT PULONG ReturnedLength)
 {
-   IO_STATUS_BLOCK IoStatusBlock;
-   PIRP Irp;
-   PDEVICE_OBJECT DeviceObject;
-   PIO_STACK_LOCATION StackPtr;
-   NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PIRP Irp;
+    PDEVICE_OBJECT DeviceObject;
+    PIO_STACK_LOCATION StackPtr;
+    BOOLEAN LocalEvent = FALSE;
+    KEVENT Event;
+    NTSTATUS Status;
    
-   ASSERT(FileInformation != NULL);
+    ASSERT(FileInformation != NULL);
    
-   Status = ObReferenceObjectByPointer(FileObject,
-           FILE_READ_ATTRIBUTES,
-           IoFileObjectType,
-           KernelMode);
-   if (!NT_SUCCESS(Status))
-     {
- return(Status);
-     }
+    Status = ObReferenceObjectByPointer(FileObject,
+                                        FILE_READ_ATTRIBUTES,
+                                        IoFileObjectType,
+                                        KernelMode);
+    if (!NT_SUCCESS(Status)) return(Status);
    
-   DPRINT("FileObject %x\n", FileObject);
+    DPRINT("FileObject %x\n", FileObject);
    
-   DeviceObject = FileObject->DeviceObject;
+    /* Get the Device Object */
+    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
+    {
+        /* Use local event */
+        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+        LocalEvent = TRUE;
+    }
    
-   Irp = IoAllocateIrp(DeviceObject->StackSize,
-         TRUE);
-   if (Irp == NULL)
-     {
- ObDereferenceObject(FileObject);
- return STATUS_INSUFFICIENT_RESOURCES;
-     }
-
-   /* Trigger FileObject/Event dereferencing */
-   Irp->Tail.Overlay.OriginalFileObject = FileObject;
-   Irp->RequestorMode = KernelMode;
-   Irp->AssociatedIrp.SystemBuffer = FileInformation;
-   Irp->UserIosb = &IoStatusBlock;
-   Irp->UserEvent = &FileObject->Event;
-   Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   KeResetEvent( &FileObject->Event );
+    /* Allocate the IRP */
+    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+     
+    /* Set the IRP */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = KernelMode;
+    Irp->AssociatedIrp.SystemBuffer = FileInformation;
+    Irp->UserIosb = &IoStatusBlock;
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+    Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    
-   StackPtr = IoGetNextIrpStackLocation(Irp);
-   StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
-   StackPtr->MinorFunction = 0;
-   StackPtr->Flags = 0;
-   StackPtr->Control = 0;
-   StackPtr->DeviceObject = DeviceObject;
-   StackPtr->FileObject = FileObject;
+    /* Set the Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;    
+    StackPtr->FileObject = FileObject;
    
-   StackPtr->Parameters.QueryFile.FileInformationClass =
-     FileInformationClass;
-   StackPtr->Parameters.QueryFile.Length = Length;
+    /* Set Parameters */
+    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,
-         KernelMode,
-         FileObject->Flags & FO_ALERTABLE_IO,
-         NULL);
- Status = IoStatusBlock.Status;
-     }
+    /* Call the Driver */
+    Status = IoCallDriver(FileObject->DeviceObject, Irp);
+    
+    if (Status == STATUS_PENDING)
+    {
+        if (LocalEvent)
+        {
+            KeWaitForSingleObject(&Event, 
+                                  Executive, 
+                                  KernelMode, 
+                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  NULL);
+            Status = IoStatusBlock.Status;
+        }
+        else
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive, 
+                                  KernelMode, 
+                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
+        
    
-   if (ReturnedLength != NULL)
-     {
- *ReturnedLength = IoStatusBlock.Information;
-     }
-   
-   
-   return Status;
+    /* Return the Length and Status. ReturnedLength is NOT optional */
+    *ReturnedLength = IoStatusBlock.Information;
+    return Status;
 }
 
 /*
@@ -2170,132 +2185,150 @@
                        ULONG Length,
                        FILE_INFORMATION_CLASS 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;
+    OBJECT_HANDLE_INFORMATION HandleInformation;
+    PFILE_OBJECT FileObject;
+    NTSTATUS Status;
+    PIRP Irp;
+    PDEVICE_OBJECT DeviceObject;
+    PIO_STACK_LOCATION StackPtr;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KEVENT Event;
+    BOOLEAN LocalEvent = FALSE;
+    BOOLEAN Failed = FALSE;
 
-  ASSERT(IoStatusBlock != NULL);
-  ASSERT(FileInformation != NULL);
+    ASSERT(IoStatusBlock != NULL);
+    ASSERT(FileInformation != NULL);
 
-  DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
-         "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
-         Length, FileInformationClass);
+    DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
+            Length, FileInformationClass);
 
-  PreviousMode = ExGetPreviousMode();
+    /* Reference the Handle */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       0,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID *)&FileObject,
+                                       &HandleInformation);
+    if (!NT_SUCCESS(Status)) return Status;
 
-  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;
 
-  /* 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 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;
 
-    case FileAlignmentInformation:
-      if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
-        Failed = TRUE;
-      break;
+        default:
+            break;
+    }
 
-    default:
-      break;
-  }
+    if (Failed)
+    {
+        DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
+        ObDereferenceObject(FileObject);
+        return STATUS_ACCESS_DENIED;
+    }
 
-  if (Failed)
-  {
-    DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
-    ObDereferenceObject(FileObject);
-    return STATUS_ACCESS_DENIED;
-  }
+    DPRINT("FileObject %x\n", FileObject);
+        
+    /* 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
+    {
+        /* Use local event */
+        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+        LocalEvent = TRUE;
+    }
 
-  DPRINT("FileObject %x\n", FileObject);
+    /* Allocate the IRP */
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    
+    /* Allocate the System Buffer */
+    if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, 
+                                                                  Length, 
+                                                                  TAG_SYSB)))
+    {
+        IoFreeIrp(Irp);
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
-  DeviceObject = FileObject->DeviceObject;
+    /* Set up the IRP */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = PreviousMode;
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+    Irp->UserBuffer = FileInformation;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
+    Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+    
+    /* Set up Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
+    StackPtr->FileObject = FileObject;
 
-  Irp = IoAllocateIrp(DeviceObject->StackSize,
-                      TRUE);
-  if (Irp == NULL)
-  {
-    ObDereferenceObject(FileObject);
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
+    /* Set the Parameters */
+    StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
+    StackPtr->Parameters.QueryFile.Length = Length;
+    
+    /* Call the Driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (LocalEvent)
+        {
+            KeWaitForSingleObject(&Event, 
+                                  Executive, 
+                                  PreviousMode, 
+                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  NULL);
+            Status = IoStatusBlock->Status;
+        }
+        else
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive, 
+                                  PreviousMode, 
+                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
 
-  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);
-  }
-
-  ExFreePool(SystemBuffer);
-
-  return Status;
+    /* Return the Status */
+    return Status;
 }
 
 /*