Properly setup the I/O stack location in IopSecurityFile.
[reactos.git] / reactos / ntoskrnl / io / file.c
index bc82401..0c21f63 100644 (file)
@@ -3,8 +3,9 @@
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/file.c
  * PURPOSE:         I/O File Object & NT File Handle Access/Managment of Files.
- * 
- * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ *
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 
 /* GLOBALS *******************************************************************/
 
-#define TAG_SYSB        TAG('S', 'Y', 'S', 'B')
-#define TAG_LOCK        TAG('F','l','c','k')
-#define TAG_FILE_NAME   TAG('F', 'N', 'A', 'M')
-
 extern GENERIC_MAPPING IopFileMapping;
 
-/* INTERNAL FUNCTIONS ********************************************************/
-
-static 
-NTSTATUS 
+NTSTATUS
 STDCALL
-IopLockFileCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
-                             IN PIRP Irp,
-                             IN PVOID Context)
-{
-  ExFreePool(Context);
-  return STATUS_SUCCESS;
-  // FIXME: Should I call IoFreeIrp and return STATUS_MORE_PROCESSING_REQUIRED?
-}
+SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
+                             PSECURITY_DESCRIPTOR SecurityDescriptor,
+                             PULONG BufferLength);
+
+/* INTERNAL FUNCTIONS ********************************************************/
 
 /*
  * NAME       INTERNAL
  *  IopCreateFile
- *  
+ *
  * DESCRIPTION
- *  
+ *
  * ARGUMENTS
- *  
+ *
  * RETURN VALUE
  *
  * REVISIONS
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 IopCreateFile(PVOID ObjectBody,
               PVOID Parent,
               PWSTR RemainingPath,
-              POBJECT_ATTRIBUTES ObjectAttributes)
+              POBJECT_CREATE_INFORMATION ObjectCreateInfo)
 {
   PDEVICE_OBJECT DeviceObject;
   PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
   POBJECT_TYPE ParentObjectType;
   NTSTATUS Status;
 
-  DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-  ObjectBody,
-  Parent,
-  RemainingPath);
+  DPRINT("IopCreateFile(ObjectBody 0x%p, Parent 0x%p, RemainingPath %S)\n",
+         ObjectBody,
+         Parent,
+         RemainingPath);
 
   if (NULL == Parent)
     {
@@ -72,25 +63,25 @@ IopCreateFile(PVOID ObjectBody,
       return(STATUS_SUCCESS);
     }
 
-  ParentObjectType = BODY_TO_HEADER(Parent)->ObjectType;
+  ParentObjectType = BODY_TO_HEADER(Parent)->Type;
 
   if (ParentObjectType != IoDeviceObjectType &&
       ParentObjectType != IoFileObjectType)
     {
       DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
-        &BODY_TO_HEADER(Parent)->Name,
-        BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer,
-        RemainingPath);
+             &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name,
+             BODY_TO_HEADER(Parent)->Type->Name.Buffer,
+             RemainingPath);
       return(STATUS_UNSUCCESSFUL);
     }
 
   Status = ObReferenceObjectByPointer(Parent,
-          STANDARD_RIGHTS_REQUIRED,
-          ParentObjectType,
-          UserMode);
+                                      STANDARD_RIGHTS_REQUIRED,
+                                      ParentObjectType,
+                                      UserMode);
   if (!NT_SUCCESS(Status))
     {
-      CPRINT("Failed to reference parent object %x\n", Parent);
+      CPRINT("Failed to reference parent object 0x%p\n", Parent);
       return(Status);
     }
 
@@ -98,82 +89,81 @@ IopCreateFile(PVOID ObjectBody,
     {
       /* Parent is a devce object */
       DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)Parent);
-      DPRINT("DeviceObject %x\n", DeviceObject);
+      DPRINT("DeviceObject 0x%p\n", DeviceObject);
 
       if (RemainingPath == NULL)
- {
-   FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
-   FileObject->FileName.Buffer = 0;
-   FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
- }
       {
+          FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
+          FileObject->FileName.Buffer = 0;
+          FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
       }
       else
- {
-   if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
-       && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
-       && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
-       && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
-       && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
-       && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
-       && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
-     {
-       CPRINT("Device was wrong type\n");
-       return(STATUS_UNSUCCESSFUL);
-     }
-
-   if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
-       && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
-       && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
-     {
-       if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
-  {
-    DPRINT("Mount the logical volume\n");
-    Status = IoMountVolume(DeviceObject, FALSE);
-    DPRINT("Status %x\n", Status);
-    if (!NT_SUCCESS(Status))
-      {
-        CPRINT("Failed to mount logical volume (Status %x)\n",
-        Status);
-        return(Status);
-      }
-  }
-       DeviceObject = DeviceObject->Vpb->DeviceObject;
-       DPRINT("FsDeviceObject %lx\n", DeviceObject);
-     }
-   RtlpCreateUnicodeString(&(FileObject->FileName),
-             RemainingPath, NonPagedPool);
- }
+        {
+          if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
+              && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
+              && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
+              && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
+              && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
+              && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
+              && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
+            {
+              CPRINT("Device was wrong type\n");
+              return(STATUS_UNSUCCESSFUL);
+            }
+
+          if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
+              && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
+              && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
+            {
+              if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
+                {
+                  DPRINT("Mount the logical volume\n");
+                  Status = IoMountVolume(DeviceObject, FALSE);
+                  DPRINT("Status %x\n", Status);
+                  if (!NT_SUCCESS(Status))
+                    {
+                      CPRINT("Failed to mount logical volume (Status %x)\n", Status);
+                      return(Status);
+                    }
+                }
+              DeviceObject = DeviceObject->Vpb->DeviceObject;
+              DPRINT("FsDeviceObject %lx\n", DeviceObject);
+            }
+          RtlpCreateUnicodeString(&(FileObject->FileName),
+                                  RemainingPath, NonPagedPool);
+        }
     }
   else
     {
       /* Parent is a file object */
       if (RemainingPath == NULL)
- {
-   CPRINT("Device is unnamed\n");
-   return STATUS_UNSUCCESSFUL;
- }
       {
+          CPRINT("Device is unnamed\n");
+          return STATUS_UNSUCCESSFUL;
       }
 
       DeviceObject = ((PFILE_OBJECT)Parent)->DeviceObject;
-      DPRINT("DeviceObject %x\n", DeviceObject);
+      DPRINT("DeviceObject 0x%p\n", DeviceObject);
 
       FileObject->RelatedFileObject = (PFILE_OBJECT)Parent;
 
       RtlpCreateUnicodeString(&(FileObject->FileName),
-              RemainingPath, NonPagedPool);
+                              RemainingPath, NonPagedPool);
     }
 
   DPRINT("FileObject->FileName %wZ\n",
-  &FileObject->FileName);
+         &FileObject->FileName);
   FileObject->DeviceObject = DeviceObject;
-  DPRINT("FileObject %x DeviceObject %x\n",
-  FileObject,
-  DeviceObject);
+  DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
+         FileObject,
+         DeviceObject);
   FileObject->Vpb = DeviceObject->Vpb;
   FileObject->Type = IO_TYPE_FILE;
 
   return(STATUS_SUCCESS);
 }
 
-VOID 
+VOID
 STDCALL
 IopDeleteFile(PVOID ObjectBody)
 {
@@ -183,11 +173,11 @@ IopDeleteFile(PVOID ObjectBody)
     NTSTATUS Status;
     KEVENT Event;
     PDEVICE_OBJECT DeviceObject;
-   
+
     DPRINT("IopDeleteFile()\n");
 
     if (FileObject->DeviceObject)
-    {    
+    {
         /* Check if this is a direct open or not */
         if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
         {
@@ -197,46 +187,46 @@ IopDeleteFile(PVOID ObjectBody)
         {
             DeviceObject = IoGetRelatedDeviceObject(FileObject);
         }
-        
+
         /* Clear and set up Events */
         KeClearEvent(&FileObject->Event);
         KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-         
+
         /* Allocate an IRP */
-        Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-        
+        Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
         /* Set it up */
         Irp->UserEvent = &Event;
         Irp->UserIosb = &Irp->IoStatus;
         Irp->Tail.Overlay.Thread = PsGetCurrentThread();
         Irp->Tail.Overlay.OriginalFileObject = FileObject;
         Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
-        
+
         /* Set up Stack Pointer Data */
         StackPtr = IoGetNextIrpStackLocation(Irp);
         StackPtr->MajorFunction = IRP_MJ_CLOSE;
         StackPtr->DeviceObject = DeviceObject;
         StackPtr->FileObject = FileObject;
-   
+
         /* Call the FS Driver */
         Status = IoCallDriver(DeviceObject, Irp);
-        
+
         /* Wait for completion */
         if (Status == STATUS_PENDING)
         {
             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
         }
-       IoFreeIrp(Irp);
-      
+        IoFreeIrp(Irp);
+
     }
 
-    /* Clear the file name */  
+    /* Clear the file name */
     if (FileObject->FileName.Buffer)
     {
        ExFreePool(FileObject->FileName.Buffer);
        FileObject->FileName.Buffer = NULL;
     }
-        
+
     /* Free the completion context */
     if (FileObject->CompletionContext)
     {
@@ -245,183 +235,162 @@ IopDeleteFile(PVOID ObjectBody)
     }
 }
 
-static 
 NTSTATUS
-IopSetDefaultSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
-                                PSECURITY_DESCRIPTOR SecurityDescriptor,
-                                PULONG BufferLength)
+STDCALL
+IopSecurityFile(PVOID ObjectBody,
+                SECURITY_OPERATION_CODE OperationCode,
+                SECURITY_INFORMATION SecurityInformation,
+                PSECURITY_DESCRIPTOR SecurityDescriptor,
+                PULONG BufferLength)
 {
-  ULONG_PTR Current;
-  ULONG SidSize;
-  ULONG SdSize;
-  NTSTATUS Status;
-
-  DPRINT("IopSetDefaultSecurityDescriptor() called\n");
+    IO_STATUS_BLOCK IoStatusBlock;
+    PIO_STACK_LOCATION StackPtr;
+    PFILE_OBJECT FileObject;
+    PDEVICE_OBJECT DeviceObject;
+    ULONG MajorFunction;
+    PIRP Irp;
+    BOOLEAN LocalEvent = FALSE;
+    KEVENT Event;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-  if (SecurityInformation == 0)
-    {
-      return STATUS_ACCESS_DENIED;
-    }
+    DPRINT("IopSecurityFile() called\n");
 
-  SidSize = RtlLengthSid(SeWorldSid);
-  SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
+    FileObject = (PFILE_OBJECT)ObjectBody;
 
-  if (*BufferLength < SdSize)
+    if (OperationCode == QuerySecurityDescriptor)
     {
-      *BufferLength = SdSize;
-      return STATUS_BUFFER_TOO_SMALL;
+        MajorFunction = IRP_MJ_QUERY_SECURITY;
+        DPRINT("Query security descriptor\n");
     }
-
-  *BufferLength = SdSize;
-
-  Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
-           SECURITY_DESCRIPTOR_REVISION);
-  if (!NT_SUCCESS(Status))
+    else if (OperationCode == DeleteSecurityDescriptor)
     {
-      return Status;
+        DPRINT("Delete\n");
+        return STATUS_SUCCESS;
     }
-
-  SecurityDescriptor->Control |= SE_SELF_RELATIVE;
-  Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
-
-  if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+    else if (OperationCode == AssignSecurityDescriptor)
     {
-      RtlCopyMemory((PVOID)Current,
-      SeWorldSid,
-      SidSize);
-      SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
-      Current += SidSize;
-    }
+        /* If this is a direct open, we can assign it */
+        if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+        {
+            /* Get the Device Object */
+            DPRINT("here\n");
+            DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
 
-  if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+            /* Assign the Security Descriptor */
+            DeviceObject->SecurityDescriptor = SecurityDescriptor;
+        }
+        return STATUS_SUCCESS;
+    }
+    else
     {
-      RtlCopyMemory((PVOID)Current,
-      SeWorldSid,
-      SidSize);
-      SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
-      Current += SidSize;
+        MajorFunction = IRP_MJ_SET_SECURITY;
+        DPRINT("Set security descriptor\n");
+
+        /* If this is a direct open, we can set it */
+        if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+        {
+            DPRINT1("Set SD unimplemented for Devices\n");
+            return STATUS_SUCCESS;
+        }
     }
 
-  if (SecurityInformation & DACL_SECURITY_INFORMATION)
+    /* Get the Device Object */
+    DPRINT1("FileObject: %p\n", FileObject);
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
+
+    /* Check if we should use Sync IO or not */
+    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
     {
-      SecurityDescriptor->Control |= SE_DACL_PRESENT;
+        /* Use File Object event */
+        KeClearEvent(&FileObject->Event);
     }
-
-  if (SecurityInformation & SACL_SECURITY_INFORMATION)
+    else
     {
-      SecurityDescriptor->Control |= SE_SACL_PRESENT;
+        /* Use local event */
+        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+        LocalEvent = TRUE;
     }
 
-  return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDCALL
-IopSecurityFile(PVOID ObjectBody,
-                SECURITY_OPERATION_CODE OperationCode,
-                SECURITY_INFORMATION SecurityInformation,
-                PSECURITY_DESCRIPTOR SecurityDescriptor,
-                PULONG BufferLength)
-{
-  IO_STATUS_BLOCK IoStatusBlock;
-  PIO_STACK_LOCATION StackPtr;
-  PFILE_OBJECT FileObject;
-  PIRP Irp;
-  NTSTATUS Status;
+    /* Allocate the IRP */
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
 
-  DPRINT("IopSecurityFile() called\n");
+    /* Set the IRP */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = ExGetPreviousMode();
+    Irp->UserIosb = &IoStatusBlock;
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+    Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
 
-  FileObject = (PFILE_OBJECT)ObjectBody;
+    /* Set Stack Parameters */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = MajorFunction;
+    StackPtr->FileObject = FileObject;
 
-  switch (OperationCode)
+    /* Set Parameters */
+    if (OperationCode == QuerySecurityDescriptor)
     {
-      case SetSecurityDescriptor:
- DPRINT("Set security descriptor\n");
- KeResetEvent(&FileObject->Event);
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_SECURITY,
-        FileObject->DeviceObject,
-        NULL,
-        0,
-        NULL,
-        &FileObject->Event,
-        &IoStatusBlock);
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
-
- StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
- StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
-
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING)
-   {
-     KeWaitForSingleObject(&FileObject->Event,
-      Executive,
-      KernelMode,
-      FALSE,
-      NULL);
-     Status = IoStatusBlock.Status;
-   }
-
- if (Status == STATUS_INVALID_DEVICE_REQUEST)
-   {
-     Status = STATUS_SUCCESS;
-   }
- return Status;
-
-      case QuerySecurityDescriptor:
- DPRINT("Query security descriptor\n");
- KeResetEvent(&FileObject->Event);
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_SECURITY,
-        FileObject->DeviceObject,
-        NULL,
-        0,
-        NULL,
-        &FileObject->Event,
-        &IoStatusBlock);
-
- Irp->UserBuffer = SecurityDescriptor;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
-
- StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
- StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
+        StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
+        StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
+        Irp->UserBuffer = SecurityDescriptor;
+    }
+    else
+    {
+        StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
+        StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
+    }
 
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING)
-   {
-     KeWaitForSingleObject(&FileObject->Event,
-      Executive,
-      KernelMode,
-      FALSE,
-      NULL);
-     Status = IoStatusBlock.Status;
-   }
+    ObReferenceObject(FileObject);
 
- if (Status == STATUS_INVALID_DEVICE_REQUEST)
-   {
-     Status = IopSetDefaultSecurityDescriptor(SecurityInformation,
-           SecurityDescriptor,
-           BufferLength);
-   }
- else
-   {
-     /* FIXME: Is this correct?? */
-     *BufferLength = IoStatusBlock.Information;
-   }
- return Status;
+    /* Call the Driver */
+    Status = IoCallDriver(FileObject->DeviceObject, Irp);
 
-      case DeleteSecurityDescriptor:
- DPRINT("Delete security descriptor\n");
- return STATUS_SUCCESS;
+    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;
+        }
+    }
 
-      case AssignSecurityDescriptor:
- DPRINT("Assign security descriptor\n");
- return STATUS_SUCCESS;
+    /* This Driver doesn't implement Security, so try to give it a default */
+    if (Status == STATUS_INVALID_DEVICE_REQUEST)
+    {
+        if (OperationCode == QuerySecurityDescriptor)
+        {
+            /* Set a World Security Descriptor */
+            Status = SeSetWorldSecurityDescriptor(SecurityInformation,
+                                                  SecurityDescriptor,
+                                                  BufferLength);
+        }
+        else
+        {
+            /* It wasn't a query, so just fake success */
+            Status = STATUS_SUCCESS;
+        }
+    }
+    else if (OperationCode == QuerySecurityDescriptor)
+    {
+        /* Return length */
+        *BufferLength = IoStatusBlock.Information;
     }
 
-  return STATUS_UNSUCCESSFUL;
+    /* Return Status */
+    return Status;
 }
 
 NTSTATUS
@@ -431,65 +400,60 @@ IopQueryNameFile(PVOID ObjectBody,
                  ULONG Length,
                  PULONG ReturnLength)
 {
-  POBJECT_NAME_INFORMATION LocalInfo;
-  PFILE_NAME_INFORMATION FileNameInfo;
-  PFILE_OBJECT FileObject;
-  ULONG LocalReturnLength;
-  NTSTATUS Status;
+    POBJECT_NAME_INFORMATION LocalInfo;
+    PFILE_OBJECT FileObject;
+    ULONG LocalReturnLength;
+    NTSTATUS Status;
 
-  DPRINT ("IopQueryNameFile() called\n");
+    DPRINT1("IopQueryNameFile() called\n");
 
-  FileObject = (PFILE_OBJECT)ObjectBody;
+    FileObject = (PFILE_OBJECT)ObjectBody;
 
-  LocalInfo = ExAllocatePool (NonPagedPool,
-         sizeof(OBJECT_NAME_INFORMATION) +
-    MAX_PATH * sizeof(WCHAR));
-  if (LocalInfo == NULL)
-    return STATUS_INSUFFICIENT_RESOURCES;
+    /* Allocate Buffer */
+    LocalInfo = ExAllocatePool(PagedPool,
+                               sizeof(OBJECT_NAME_INFORMATION) +
+                               MAX_PATH * sizeof(WCHAR));
+    if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
 
-  Status = ObQueryNameString (FileObject->DeviceObject->Vpb->RealDevice,
-         LocalInfo,
-         MAX_PATH * sizeof(WCHAR),
-         &LocalReturnLength);
-  if (!NT_SUCCESS (Status))
+    /* Query the name */
+    Status = ObQueryNameString(FileObject->DeviceObject,
+                               LocalInfo,
+                               MAX_PATH * sizeof(WCHAR),
+                               &LocalReturnLength);
+    if (!NT_SUCCESS (Status))
     {
-      ExFreePool (LocalInfo);
-      return Status;
+        ExFreePool (LocalInfo);
+        return Status;
     }
-  DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
-
-  Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-        &LocalInfo->Name);
-
-  ExFreePool (LocalInfo);
-
-  FileNameInfo = ExAllocatePool (NonPagedPool,
-     MAX_PATH * sizeof(WCHAR) + sizeof(ULONG));
-  if (FileNameInfo == NULL)
-    return STATUS_INSUFFICIENT_RESOURCES;
-
-  Status = IoQueryFileInformation (FileObject,
-       FileNameInformation,
-       MAX_PATH * sizeof(WCHAR) + sizeof(ULONG),
-       FileNameInfo,
-       NULL);
-  if (Status != STATUS_SUCCESS)
+    DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
+    
+    /* Write Device Path */
+    Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
+                                            &(LocalInfo)->Name);
+
+    /* Query the File name */
+    Status = IoQueryFileInformation(FileObject,
+                                    FileNameInformation,
+                                    LocalReturnLength,
+                                    LocalInfo,
+                                    NULL);
+    if (Status != STATUS_SUCCESS)
     {
-      ExFreePool (FileNameInfo);
-      return Status;
+        ExFreePool(LocalInfo);
+        return Status;
     }
 
-  Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
-         FileNameInfo->FileName);
-
-  DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
+    /* Write the Name */
+    Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
+                                      ((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
+    DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
 
-  ExFreePool (FileNameInfo);
-
-  return Status;
+    /* Free buffer and return */
+    ExFreePool(LocalInfo);
+    return Status;
 }
 
-VOID 
+VOID
 STDCALL
 IopCloseFile(PVOID ObjectBody,
              ULONG HandleCount)
@@ -500,9 +464,9 @@ IopCloseFile(PVOID ObjectBody,
     PIO_STACK_LOCATION StackPtr;
     NTSTATUS Status;
     PDEVICE_OBJECT DeviceObject;
-   
+
     DPRINT("IopCloseFile()\n");
-   
+
     if (HandleCount > 1 || FileObject->DeviceObject == NULL) return;
 
     /* Check if this is a direct open or not */
@@ -514,36 +478,161 @@ IopCloseFile(PVOID ObjectBody,
     {
         DeviceObject = IoGetRelatedDeviceObject(FileObject);
     }
-    
+
     /* Clear and set up Events */
     KeClearEvent(&FileObject->Event);
     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-  
+
     /* Allocate an IRP */
-    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-        
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
     /* Set it up */
     Irp->UserEvent = &Event;
     Irp->UserIosb = &Irp->IoStatus;
     Irp->Tail.Overlay.Thread = PsGetCurrentThread();
     Irp->Tail.Overlay.OriginalFileObject = FileObject;
     Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
-        
+
     /* Set up Stack Pointer Data */
     StackPtr = IoGetNextIrpStackLocation(Irp);
     StackPtr->MajorFunction = IRP_MJ_CLEANUP;
     StackPtr->FileObject = FileObject;
-   
+
     /* Call the FS Driver */
     Status = IoCallDriver(DeviceObject, Irp);
-        
+
     /* Wait for completion */
     if (Status == STATUS_PENDING)
     {
         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
     }
+    IoFreeIrp(Irp);
 }
 
+NTSTATUS 
+STDCALL
+IopDeviceFsIoControl(IN HANDLE DeviceHandle,
+                     IN HANDLE Event OPTIONAL,
+                     IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+                     IN PVOID UserApcContext OPTIONAL,
+                     OUT PIO_STATUS_BLOCK IoStatusBlock,
+                     IN ULONG IoControlCode,
+                     IN PVOID InputBuffer,
+                     IN ULONG InputBufferLength OPTIONAL,
+                     OUT PVOID OutputBuffer,
+                     IN ULONG OutputBufferLength OPTIONAL,
+                     BOOLEAN IsDevIoCtl)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PFILE_OBJECT FileObject;
+    PDEVICE_OBJECT DeviceObject;
+    PIRP Irp;
+    PIO_STACK_LOCATION StackPtr;
+    PKEVENT EventObject = NULL;
+    BOOLEAN LocalEvent = FALSE;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+
+    DPRINT("IopDeviceFsIoControl(DeviceHandle 0x%p Event 0x%p UserApcRoutine 0x%p "
+           "UserApcContext 0x%p IoStatusBlock 0x%p IoControlCode %x "
+           "InputBuffer 0x%p InputBufferLength %x OutputBuffer 0x%p "
+           "OutputBufferLength 0x%p)\n",
+           DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
+           IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,
+           OutputBufferLength);
+
+    if (IoStatusBlock == NULL) return STATUS_ACCESS_VIOLATION;
+
+    /* Check granted access against the access rights from IoContolCode */
+    Status = ObReferenceObjectByHandle(DeviceHandle,
+                                       (IoControlCode >> 14) & 0x3,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID *) &FileObject,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check for an event */
+    if (Event)
+    {
+        /* Reference it */
+        Status = ObReferenceObjectByHandle(Event,
+                                           EVENT_MODIFY_STATE,
+                                           ExEventObjectType,
+                                           PreviousMode,
+                                           (PVOID*)&EventObject,
+                                           NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject (FileObject);
+            return Status;
+        }
+        
+        /* Clear it */
+        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
+    {
+        /* Use local event */
+        LocalEvent = TRUE;
+    }
+
+    /* Build the IRP */
+    Irp = IoBuildDeviceIoControlRequest(IoControlCode,
+                                        DeviceObject,
+                                        InputBuffer,
+                                        InputBufferLength,
+                                        OutputBuffer,
+                                        OutputBufferLength,
+                                        FALSE,
+                                        EventObject,
+                                        IoStatusBlock);
+
+    /* Set some extra settings */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = PreviousMode;
+    Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
+    Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->FileObject = FileObject;
+    StackPtr->MajorFunction = IsDevIoCtl ? 
+                              IRP_MJ_DEVICE_CONTROL : IRP_MJ_FILE_SYSTEM_CONTROL;
+    
+    /* Call the Driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (!LocalEvent)
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
+
+    /* Return the Status */
+    return Status;
+}
+                      
 /* FUNCTIONS *****************************************************************/
 
 /*
@@ -575,60 +664,60 @@ IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
 /*
  * NAME       EXPORTED
  *  IoCreateFile@56
- *  
+ *
  * DESCRIPTION
  *  Either causes a new file or directory to be created, or it
  *  opens an existing file, device, directory or volume, giving
  *  the caller a handle for the file object. This handle can be
  *  used by subsequent calls to manipulate data within the file
  *  or the file object's state of attributes.
- *  
+ *
  * ARGUMENTS
  * FileHandle (OUT)
  *  Points to a variable which receives the file handle
  *  on return;
- *  
+ *
  * DesiredAccess
  *  Desired access to the file;
- *  
+ *
  * ObjectAttributes
  *  Structure describing the file;
- *  
+ *
  * IoStatusBlock (OUT)
  *  Receives information about the operation on return;
- *  
+ *
  * AllocationSize [OPTIONAL]
  *  Initial size of the file in bytes;
- *  
+ *
  * FileAttributes
  *  Attributes to create the file with;
- *  
+ *
  * ShareAccess
  *  Type of shared access the caller would like to the
  *  file;
- *  
+ *
  * CreateDisposition
  *  Specifies what to do, depending on whether the
  *  file already exists;
- *  
+ *
  * CreateOptions
  *  Options for creating a new file;
- *  
+ *
  * EaBuffer [OPTIONAL]
  *  Undocumented;
- *  
+ *
  * EaLength
  *  Undocumented;
- *  
+ *
  * CreateFileType
  *  Type of file (normal, named pipe, mailslot) to create;
- *  
+ *
  * ExtraCreateParameters [OPTIONAL]
  *  Additional creation data for named pipe and mailsots;
- *  
+ *
  * Options
  *  Undocumented.
- *  
+ *
  * RETURN VALUE
  *  Status
  *
@@ -636,12 +725,12 @@ IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
  *  Prototype taken from Bo Branten's ntifs.h v15.
  *  Description taken from old NtCreateFile's which is
  *  now a wrapper of this call.
- *  
+ *
  * REVISIONS
- * 
+ *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 IoCreateFile(OUT PHANDLE  FileHandle,
              IN ACCESS_MASK  DesiredAccess,
@@ -669,12 +758,12 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    LARGE_INTEGER        SafeAllocationSize;
    PVOID                SystemEaBuffer = NULL;
    NTSTATUS  Status = STATUS_SUCCESS;
-   
-   DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
-   "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
-   FileHandle,DesiredAccess,ObjectAttributes,
-   ObjectAttributes->ObjectName->Buffer);
-   
+
+   DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
+          "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
+          FileHandle,DesiredAccess,ObjectAttributes,
+          ObjectAttributes->ObjectName->Buffer);
+
    ASSERT_IRQL(PASSIVE_LEVEL);
 
    if (IoStatusBlock == NULL || FileHandle == NULL)
@@ -686,7 +775,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
      AccessMode = KernelMode;
    else
      AccessMode = ExGetPreviousMode();
-   
+
    if(AccessMode != KernelMode)
    {
      _SEH_TRY
@@ -732,7 +821,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
        Status = _SEH_GetExceptionCode();
      }
      _SEH_END;
-     
+
      if(!NT_SUCCESS(Status))
      {
        return Status;
@@ -756,80 +845,82 @@ IoCreateFile(OUT PHANDLE  FileHandle,
      DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
    }
 
-   if (CreateDisposition == FILE_OPEN ||
-       CreateDisposition == FILE_OPEN_IF)
+   Status = ObOpenObjectByName(ObjectAttributes,
+                               NULL,
+                               NULL,
+                               AccessMode,
+                               DesiredAccess,
+                               NULL,
+                               &LocalHandle);
+
+   if (NT_SUCCESS(Status))
    {
-      Status = ObOpenObjectByName(ObjectAttributes,
-                           NULL,
-      NULL,
-      AccessMode,
-      DesiredAccess,
-      NULL,
-      &LocalHandle);
-      if (NT_SUCCESS(Status))
+      Status = ObReferenceObjectByHandle(LocalHandle,
+                                         DesiredAccess,
+                                         NULL,
+                                         AccessMode,
+                                         (PVOID*)&DeviceObject,
+                                         NULL);
+      ZwClose(LocalHandle);
+      if (!NT_SUCCESS(Status))
       {
-         Status = ObReferenceObjectByHandle(LocalHandle,
-                                     DesiredAccess,
-         NULL,
-         AccessMode,
-         (PVOID*)&DeviceObject,
-         NULL);
-         ZwClose(LocalHandle); 
-  if (!NT_SUCCESS(Status))
-  {
-     return Status;
-  }
-         if (BODY_TO_HEADER(DeviceObject)->ObjectType != IoDeviceObjectType)
-  {
-     ObDereferenceObject (DeviceObject);
-     return STATUS_OBJECT_NAME_COLLISION;
-  }
-         FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
-  ObDereferenceObject (DeviceObject);
+         return Status;
       }
+      if (BODY_TO_HEADER(DeviceObject)->Type != IoDeviceObjectType)
+      {
+         ObDereferenceObject (DeviceObject);
+         return STATUS_OBJECT_NAME_COLLISION;
+      }
+      /* FIXME: wt... */
+      FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
+      /* HACK */
+      FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
+      DPRINT("%wZ\n", ObjectAttributes->ObjectName);
+
+      ObDereferenceObject (DeviceObject);
    }
 
 
    if (FileObject == NULL)
    {
       Status = ObCreateObject(AccessMode,
-         IoFileObjectType,
-         ObjectAttributes,
-         AccessMode,
-         NULL,
-         sizeof(FILE_OBJECT),
-         0,
-         0,
-         (PVOID*)&FileObject);
+                              IoFileObjectType,
+                              ObjectAttributes,
+                              AccessMode,
+                              NULL,
+                              sizeof(FILE_OBJECT),
+                              0,
+                              0,
+                              (PVOID*)&FileObject);
       if (!NT_SUCCESS(Status))
       {
- DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
- return Status;
        DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
        return Status;
       }
    }
-   RtlMapGenericMask(&DesiredAccess,    
-                      BODY_TO_HEADER(FileObject)->ObjectType->Mapping);
-                      
+   RtlMapGenericMask(&DesiredAccess,
+                     &BODY_TO_HEADER(FileObject)->Type->TypeInfo.GenericMapping);
+
    Status = ObInsertObject ((PVOID)FileObject,
-       NULL,
-       DesiredAccess,
-       0,
-       NULL,
-       &LocalHandle);
+                            NULL,
+                            DesiredAccess,
+                            0,
+                            NULL,
+                            &LocalHandle);
    if (!NT_SUCCESS(Status))
      {
- DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
- ObDereferenceObject (FileObject);
- return Status;
      DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
      ObDereferenceObject (FileObject);
      return Status;
      }
 
    if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
      {
- FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
      FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
      }
    if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
      {
- FileObject->Flags |= FO_SYNCHRONOUS_IO;
      FileObject->Flags |= FO_SYNCHRONOUS_IO;
      }
 
    if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
@@ -839,12 +930,12 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    SecurityContext.AccessState = NULL; /* ?? */
    SecurityContext.DesiredAccess = DesiredAccess;
    SecurityContext.FullCreateOptions = 0; /* ?? */
-   
+
    KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
    KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
-   
-   DPRINT("FileObject %x\n", FileObject);
-   DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
+
+   DPRINT("FileObject 0x%p\n", FileObject);
+   DPRINT("FileObject->DeviceObject 0x%p\n", FileObject->DeviceObject);
    /*
     * Create a new IRP to hand to
     * the FS driver: this may fail
@@ -853,8 +944,8 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
    if (Irp == NULL)
      {
- ZwClose(LocalHandle);
- return STATUS_UNSUCCESSFUL;
      ZwClose(LocalHandle);
      return STATUS_UNSUCCESSFUL;
      }
 
    //trigger FileObject/Event dereferencing
@@ -866,7 +957,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    Irp->UserEvent = &FileObject->Event;
    Irp->Overlay.AllocationSize = SafeAllocationSize;
-   
+
    /*
     * Get the stack location for the new
     * IRP and prepare it.
@@ -880,34 +971,34 @@ IoCreateFile(OUT PHANDLE  FileHandle,
 
    switch (CreateFileType)
      {
- default:
- case CreateFileTypeNone:
-   StackLoc->MajorFunction = IRP_MJ_CREATE;
-   StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
-   StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
-   StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
-   StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
-   StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
-   StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
-   break;
- case CreateFileTypeNamedPipe:
-   StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
-   StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
-   StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
-   StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
-   StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
-   StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
-   break;
-
- case CreateFileTypeMailslot:
-   StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
-   StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
-   StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
-   StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
-   StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
-   StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
-   break;
      default:
      case CreateFileTypeNone:
+         StackLoc->MajorFunction = IRP_MJ_CREATE;
+         StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
+         StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+         StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
+         StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
+         StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
+         StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
+         break;
+
     case CreateFileTypeNamedPipe:
+        StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
+        StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
+        StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+        StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
+        StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
+        StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
+        break;
+
     case CreateFileTypeMailslot:
+        StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
+        StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
+        StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
+        StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
+        StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
+        StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
+        break;
      }
 
    /*
@@ -921,33 +1012,33 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    
    if (Status == STATUS_PENDING)
      {
- KeWaitForSingleObject(&FileObject->Event,
-         Executive,
-         AccessMode,
-         FALSE,
-         NULL);
- Status = LocalIoStatusBlock.Status;
      KeWaitForSingleObject(&FileObject->Event,
+                             Executive,
+                             AccessMode,
+                             FALSE,
+                             NULL);
      Status = LocalIoStatusBlock.Status;
      }
    if (!NT_SUCCESS(Status))
      {
- DPRINT("Failing create request with status %x\n", Status);
-        FileObject->DeviceObject = NULL;
-        FileObject->Vpb = NULL;
      DPRINT("Failing create request with status %x\n", Status);
+       FileObject->DeviceObject = NULL;
+       FileObject->Vpb = NULL;
 
- ZwClose(LocalHandle);
      ZwClose(LocalHandle);
      }
    else
      {
-  _SEH_TRY
-    {
-       *FileHandle = LocalHandle;
-       *IoStatusBlock = LocalIoStatusBlock;
-    }
-  _SEH_HANDLE
-    {
-       Status = _SEH_GetExceptionCode();
-    }
-  _SEH_END;
+       _SEH_TRY
+         {
+           *FileHandle = LocalHandle;
+           *IoStatusBlock = LocalIoStatusBlock;
+         }
+       _SEH_HANDLE
+         {
+           Status = _SEH_GetExceptionCode();
+         }
+       _SEH_END;
      }
 
    /* cleanup EABuffer if captured */
@@ -958,7 +1049,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
 
    ASSERT_IRQL(PASSIVE_LEVEL);
 
-   DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
+   DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle));
 
    return Status;
 }
@@ -991,22 +1082,22 @@ IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,
 /*
  * NAME       EXPORTED
  *  IoCreateStreamFileObject@8
- *  
+ *
  * DESCRIPTION
- *  
+ *
  * ARGUMENTS
  * FileObject
  *  ?
- *  
+ *
  * DeviceObject
  *  ?
- *  
+ *
  * RETURN VALUE
  *
  * NOTE
- *  
+ *
  * REVISIONS
- * 
+ *
  * @implemented
  */
 PFILE_OBJECT 
@@ -1014,55 +1105,53 @@ STDCALL
 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
                          PDEVICE_OBJECT DeviceObject)
 {
-  PFILE_OBJECT CreatedFileObject;
-  NTSTATUS Status;
-
-  DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
-  FileObject, DeviceObject);
-
-  ASSERT_IRQL(PASSIVE_LEVEL);
-
-  Status = ObCreateObject(KernelMode,
-     IoFileObjectType,
-     NULL,
-     KernelMode,
-     NULL,
-     sizeof(FILE_OBJECT),
-     0,
-     0,
-     (PVOID*)&CreatedFileObject);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("Could not create FileObject\n");
-      return (NULL);
-    }
-
-  if (FileObject != NULL)
-    {
-      DeviceObject = FileObject->DeviceObject;
-    }
-  DeviceObject = IoGetAttachedDevice(DeviceObject);
-
-  DPRINT("DeviceObject %x\n", DeviceObject);
+    PFILE_OBJECT CreatedFileObject;
+    NTSTATUS Status;
+    
+    /* FIXME: This function should call ObInsertObject. The "Lite" version 
+       doesnt. This function is also called from IoCreateFile for some 
+       reason. These hacks need to be removed.
+    */
 
-  if (DeviceObject->Vpb && 
-      DeviceObject->Vpb->DeviceObject)
-    {
-      CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
-    }
-  else
+    DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
+            FileObject, DeviceObject);
+    PAGED_CODE();
+
+    /* Create the File Object */
+    Status = ObCreateObject(KernelMode,
+                            IoFileObjectType,
+                            NULL,
+                            KernelMode,
+                            NULL,
+                            sizeof(FILE_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)&CreatedFileObject);
+    if (!NT_SUCCESS(Status))
     {
-      CreatedFileObject->DeviceObject = DeviceObject; 
+        DPRINT1("Could not create FileObject\n");
+        return (NULL);
     }
-  CreatedFileObject->Vpb = DeviceObject->Vpb;
-  CreatedFileObject->Type = IO_TYPE_FILE;
-  CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
-
-  // shouldn't we initialize the lock event, and several other things here too?
-  KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
-  KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
 
-  return CreatedFileObject;
+    /* Choose Device Object */
+    if (FileObject) DeviceObject = FileObject->DeviceObject;
+    DPRINT("DeviceObject 0x%p\n", DeviceObject);
+    
+    /* HACK */
+    DeviceObject = IoGetAttachedDevice(DeviceObject);
+    
+    /* Set File Object Data */
+    CreatedFileObject->DeviceObject = DeviceObject; 
+    CreatedFileObject->Vpb = DeviceObject->Vpb;
+    CreatedFileObject->Type = IO_TYPE_FILE;
+    CreatedFileObject->Flags |= FO_STREAM_FILE;
+
+    /* Initialize Lock and Event */
+    KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
+    KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
+
+    /* Return file */
+    return CreatedFileObject;
 }
 
 /*
@@ -1077,6 +1166,7 @@ IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,
     UNIMPLEMENTED;
     return 0;
 }
+
 /*
  * @unimplemented
  */
@@ -1092,7 +1182,7 @@ IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,
 /*
  * @implemented
  */
-PGENERIC_MAPPING 
+PGENERIC_MAPPING
 STDCALL
 IoGetFileObjectGenericMapping(VOID)
 {
@@ -1125,7 +1215,7 @@ IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
 /*
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
                        IN FILE_INFORMATION_CLASS FileInformationClass,
@@ -1140,20 +1230,20 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
     BOOLEAN LocalEvent = FALSE;
     KEVENT Event;
     NTSTATUS Status;
-   
+
     ASSERT(FileInformation != NULL);
-   
+
     Status = ObReferenceObjectByPointer(FileObject,
                                         FILE_READ_ATTRIBUTES,
                                         IoFileObjectType,
                                         KernelMode);
     if (!NT_SUCCESS(Status)) return(Status);
-   
-    DPRINT("FileObject %x\n", FileObject);
-   
+
+    DPRINT("FileObject 0x%p\n", FileObject);
+
     /* Get the Device Object */
     DeviceObject = IoGetRelatedDeviceObject(FileObject);
-    
+
     /* Check if we should use Sync IO or not */
     if (FileObject->Flags & FO_SYNCHRONOUS_IO)
     {
@@ -1166,10 +1256,10 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
         KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
         LocalEvent = TRUE;
     }
-   
+
     /* Allocate the IRP */
-    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-     
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+
     /* Set the IRP */
     Irp->Tail.Overlay.OriginalFileObject = FileObject;
     Irp->RequestorMode = KernelMode;
@@ -1178,42 +1268,42 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
     Irp->UserEvent = (LocalEvent) ? &Event : NULL;
     Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
     Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   
+
     /* Set the Stack Data */
     StackPtr = IoGetNextIrpStackLocation(Irp);
-    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;    
+    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
     StackPtr->FileObject = FileObject;
-   
+
     /* Set Parameters */
     StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
     StackPtr->Parameters.QueryFile.Length = Length;
-   
+
     /* Call the Driver */
     Status = IoCallDriver(FileObject->DeviceObject, Irp);
-    
+
     if (Status == STATUS_PENDING)
     {
         if (LocalEvent)
         {
-            KeWaitForSingleObject(&Event, 
-                                  Executive, 
-                                  KernelMode, 
-                                  FileObject->Flags & FO_ALERTABLE_IO, 
+            KeWaitForSingleObject(&Event,
+                                  Executive,
+                                  KernelMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = IoStatusBlock.Status;
         }
         else
         {
             KeWaitForSingleObject(&FileObject->Event,
-                                  Executive, 
-                                  KernelMode, 
-                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  Executive,
+                                  KernelMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = FileObject->FinalStatus;
         }
     }
-        
-   
+
+
     /* Return the Length and Status. ReturnedLength is NOT optional */
     *ReturnedLength = IoStatusBlock.Information;
     return Status;
@@ -1234,7 +1324,7 @@ IoSetFileOrigin(IN PFILE_OBJECT FileObject,
 /**
  * @name NtCancelIoFile
  *
- * Cancel all pending I/O operations in the current thread for specified 
+ * Cancel all pending I/O operations in the current thread for specified
  * file object.
  *
  * @param FileHandle
@@ -1248,7 +1338,7 @@ IoSetFileOrigin(IN PFILE_OBJECT FileObject,
  *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtCancelIoFile(IN HANDLE FileHandle,
                OUT PIO_STATUS_BLOCK IoStatusBlock)
@@ -1262,7 +1352,7 @@ NtCancelIoFile(IN HANDLE FileHandle,
    BOOLEAN OurIrpsInList = FALSE;
    LARGE_INTEGER Interval;
 
-   if ((ULONG_PTR)IoStatusBlock >= MmUserProbeAddress &&
+   if ((ULONG_PTR)IoStatusBlock >= (ULONG_PTR)MmUserProbeAddress &&
        KeGetPreviousMode() == UserMode)
       return STATUS_ACCESS_VIOLATION;
 
@@ -1292,7 +1382,7 @@ NtCancelIoFile(IN HANDLE FileHandle,
          /* Don't break here, we want to cancel all IRPs for the file object. */
          OurIrpsInList = TRUE;
       }
-   }   
+   }
 
    KfLowerIrql(OldIrql);
 
@@ -1348,14 +1438,14 @@ NtCancelIoFile(IN HANDLE FileHandle,
 /*
  * NAME       EXPORTED
  * NtCreateFile@44
- * 
+ *
  * DESCRIPTION
  * Entry point to call IoCreateFile with
  * default parameters.
  *
  * ARGUMENTS
  *  See IoCreateFile.
- * 
+ *
  * RETURN VALUE
  *  See IoCreateFile.
  *
@@ -1365,7 +1455,7 @@ NtCancelIoFile(IN HANDLE FileHandle,
  *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtCreateFile(PHANDLE FileHandle,
              ACCESS_MASK DesiredAccess,
@@ -1407,41 +1497,48 @@ NtCreateMailslotFile(OUT PHANDLE FileHandle,
                      IN ULONG MaxMessageSize,
                      IN PLARGE_INTEGER TimeOut)
 {
-   MAILSLOT_CREATE_PARAMETERS Buffer;
-   
-   DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
-   "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
-   FileHandle,DesiredAccess,ObjectAttributes,
-   ObjectAttributes->ObjectName->Buffer);
-   
-   ASSERT_IRQL(PASSIVE_LEVEL);
-   
-   if (TimeOut != NULL)
-     {
- Buffer.ReadTimeout.QuadPart = TimeOut->QuadPart;
- Buffer.TimeoutSpecified = TRUE;
-     }
-   else
-     {
- Buffer.TimeoutSpecified = FALSE;
-     }
-   Buffer.MailslotQuota = MailslotQuota;
-   Buffer.MaximumMessageSize = MaxMessageSize;
-
-   return IoCreateFile(FileHandle,
-         DesiredAccess,
-         ObjectAttributes,
-         IoStatusBlock,
-         NULL,
-         FILE_ATTRIBUTE_NORMAL,
-         FILE_SHARE_READ | FILE_SHARE_WRITE,
-         FILE_CREATE,
-         CreateOptions,
-         NULL,
-         0,
-         CreateFileTypeMailslot,
-         (PVOID)&Buffer,
-         0);
+    MAILSLOT_CREATE_PARAMETERS Buffer;
+
+    DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
+           "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
+           FileHandle,DesiredAccess,ObjectAttributes,
+           ObjectAttributes->ObjectName->Buffer);
+    PAGED_CODE();
+
+    /* Check for Timeout */
+    if (TimeOut)
+    {
+        /* Enable it */
+        Buffer.TimeoutSpecified = TRUE;
+
+        /* FIXME: Add SEH */
+        Buffer.ReadTimeout = *TimeOut;
+    }
+    else
+    {
+        /* No timeout */
+        Buffer.TimeoutSpecified = FALSE;
+    }
+
+    /* Set Settings */
+    Buffer.MailslotQuota = MailslotQuota;
+    Buffer.MaximumMessageSize = MaxMessageSize;
+
+    /* Call I/O */
+    return IoCreateFile(FileHandle,
+                        DesiredAccess,
+                        ObjectAttributes,
+                        IoStatusBlock,
+                        NULL,
+                        FILE_ATTRIBUTE_NORMAL,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        FILE_CREATE,
+                        CreateOptions,
+                        NULL,
+                        0,
+                        CreateFileTypeMailslot,
+                        (PVOID)&Buffer,
+                        0);
 }
 
 NTSTATUS
@@ -1461,53 +1558,60 @@ NtCreateNamedPipeFile(PHANDLE FileHandle,
                       ULONG OutboundQuota,
                       PLARGE_INTEGER DefaultTimeout)
 {
-  NAMED_PIPE_CREATE_PARAMETERS Buffer;
-
-  DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
-  "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
-  FileHandle,DesiredAccess,ObjectAttributes,
-  ObjectAttributes->ObjectName->Buffer);
+    NAMED_PIPE_CREATE_PARAMETERS Buffer;
 
-  ASSERT_IRQL(PASSIVE_LEVEL);
+    DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
+           "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
+            FileHandle,DesiredAccess,ObjectAttributes,
+            ObjectAttributes->ObjectName->Buffer);
+    PAGED_CODE();
 
-  if (DefaultTimeout != NULL)
+    /* Check for Timeout */
+    if (DefaultTimeout)
     {
-      Buffer.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart;
-      Buffer.TimeoutSpecified = TRUE;
+        /* Enable it */
+        Buffer.TimeoutSpecified = TRUE;
+
+        /* FIXME: Add SEH */
+        Buffer.DefaultTimeout = *DefaultTimeout;
     }
-  else
+    else
     {
-      Buffer.TimeoutSpecified = FALSE;
-    }
-  Buffer.NamedPipeType = NamedPipeType;
-  Buffer.ReadMode = ReadMode;
-  Buffer.CompletionMode = CompletionMode;
-  Buffer.MaximumInstances = MaximumInstances;
-  Buffer.InboundQuota = InboundQuota;
-  Buffer.OutboundQuota = OutboundQuota;
-
-  return IoCreateFile(FileHandle,
-        DesiredAccess,
-        ObjectAttributes,
-        IoStatusBlock,
-        NULL,
-        FILE_ATTRIBUTE_NORMAL,
-        ShareAccess,
-        CreateDisposition,
-        CreateOptions,
-        NULL,
-        0,
-        CreateFileTypeNamedPipe,
-        (PVOID)&Buffer,
-        0);
+        /* No timeout */
+        Buffer.TimeoutSpecified = FALSE;
+    }
+
+    /* Set Settings */
+    Buffer.NamedPipeType = NamedPipeType;
+    Buffer.ReadMode = ReadMode;
+    Buffer.CompletionMode = CompletionMode;
+    Buffer.MaximumInstances = MaximumInstances;
+    Buffer.InboundQuota = InboundQuota;
+    Buffer.OutboundQuota = OutboundQuota;
+
+    /* Call I/O */
+    return IoCreateFile(FileHandle,
+                        DesiredAccess,
+                        ObjectAttributes,
+                        IoStatusBlock,
+                        NULL,
+                        FILE_ATTRIBUTE_NORMAL,
+                        ShareAccess,
+                        CreateDisposition,
+                        CreateOptions,
+                        NULL,
+                        0,
+                        CreateFileTypeNamedPipe,
+                        (PVOID)&Buffer,
+                        0);
 }
 
 /*
  * NAME       EXPORTED
  * NtDeleteFile@4
- *  
+ *
  * DESCRIPTION
- *  
+ *
  * ARGUMENTS
  * ObjectAttributes
  *  ?
@@ -1515,10 +1619,10 @@ NtCreateNamedPipeFile(PHANDLE FileHandle,
  * RETURN VALUE
  *
  * REVISIONS
- * 
+ *
  * @unimplemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
@@ -1526,22 +1630,81 @@ NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
     return(STATUS_NOT_IMPLEMENTED);
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+NtDeviceIoControlFile(IN HANDLE DeviceHandle,
+                      IN HANDLE Event OPTIONAL,
+                      IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+                      IN PVOID UserApcContext OPTIONAL,
+                      OUT PIO_STATUS_BLOCK IoStatusBlock,
+                      IN ULONG IoControlCode,
+                      IN PVOID InputBuffer,
+                      IN ULONG InputBufferLength OPTIONAL,
+                      OUT PVOID OutputBuffer,
+                      IN ULONG OutputBufferLength OPTIONAL)
+{
+    /* Call the Generic Function */
+    return IopDeviceFsIoControl(DeviceHandle,
+                                Event,
+                                UserApcRoutine,
+                                UserApcContext,
+                                IoStatusBlock,
+                                IoControlCode,
+                                InputBuffer,
+                                InputBufferLength,
+                                OutputBuffer,
+                                OutputBufferLength,
+                                TRUE);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+NtFsControlFile(IN HANDLE DeviceHandle,
+                IN HANDLE Event OPTIONAL,
+                IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+                IN PVOID UserApcContext OPTIONAL,
+                OUT PIO_STATUS_BLOCK IoStatusBlock,
+                IN ULONG IoControlCode,
+                IN PVOID InputBuffer,
+                IN ULONG InputBufferLength OPTIONAL,
+                OUT PVOID OutputBuffer,
+                IN ULONG OutputBufferLength OPTIONAL)
+{
+    return IopDeviceFsIoControl(DeviceHandle,
+                                Event,
+                                UserApcRoutine,
+                                UserApcContext,
+                                IoStatusBlock,
+                                IoControlCode,
+                                InputBuffer,
+                                InputBufferLength,
+                                OutputBuffer,
+                                OutputBufferLength,
+                                FALSE);
+}
+
 NTSTATUS
 STDCALL
 NtFlushWriteBuffer(VOID)
 {
-  KeFlushWriteBuffer();
-  return STATUS_SUCCESS;
+    KeFlushWriteBuffer();
+    return STATUS_SUCCESS;
 }
 
 /*
  * FUNCTION: Flushes cached file data to disk
  * ARGUMENTS:
  *       FileHandle = Points to the file
- *  IoStatusBlock = Caller must supply storage to receive the result of 
+ *  IoStatusBlock = Caller must supply storage to receive the result of
  *                       the flush buffers operation. The information field is
  *                       set to number of bytes flushed to disk.
- * RETURNS: Status 
+ * RETURNS: Status
  * REMARKS: This function maps to the win32 FlushFileBuffers
  */
 NTSTATUS
@@ -1576,7 +1739,7 @@ NtFlushBuffersFile(IN  HANDLE FileHandle,
     {
         DeviceObject = IoGetRelatedDeviceObject(FileObject);
     }
-    
+
     /* Check if we should use Sync IO or not */
     if (FileObject->Flags & FO_SYNCHRONOUS_IO)
     {
@@ -1591,12 +1754,12 @@ NtFlushBuffersFile(IN  HANDLE FileHandle,
     }
 
     /* Allocate the IRP */
-    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
     {
         ObDereferenceObject(FileObject);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
-    
+
     /* Set up the IRP */
     Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
     Irp->RequestorMode = PreviousMode;
@@ -1609,26 +1772,26 @@ NtFlushBuffersFile(IN  HANDLE FileHandle,
     StackPtr = IoGetNextIrpStackLocation(Irp);
     StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
     StackPtr->FileObject = FileObject;
-    
+
     /* Call the Driver */
     Status = IoCallDriver(DeviceObject, Irp);
     if (Status == STATUS_PENDING)
     {
         if (LocalEvent)
         {
-            KeWaitForSingleObject(&Event, 
-                                  Executive, 
-                                  PreviousMode, 
-                                  FileObject->Flags & FO_ALERTABLE_IO, 
+            KeWaitForSingleObject(&Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = IoStatusBlock->Status;
         }
         else
         {
             KeWaitForSingleObject(&FileObject->Event,
-                                  Executive, 
-                                  PreviousMode, 
-                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = FileObject->FinalStatus;
         }
@@ -1644,9 +1807,9 @@ NtFlushBuffersFile(IN  HANDLE FileHandle,
 NTSTATUS
 STDCALL
 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
-                            IN HANDLE Event OPTIONAL, 
-                            IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
-                            IN PVOID ApcContext OPTIONAL, 
+                            IN HANDLE Event OPTIONAL,
+                            IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+                            IN PVOID ApcContext OPTIONAL,
                             OUT PIO_STATUS_BLOCK IoStatusBlock,
                             OUT PVOID Buffer,
                             IN ULONG BufferSize,
@@ -1659,13 +1822,13 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
    PIO_STACK_LOCATION IoStack;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status = STATUS_SUCCESS;
-   
+
    DPRINT("NtNotifyChangeDirectoryFile()\n");
-   
+
    PAGED_CODE();
 
    PreviousMode = ExGetPreviousMode();
-   
+
    if(PreviousMode != KernelMode)
    {
      _SEH_TRY
@@ -1685,7 +1848,7 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
        Status = _SEH_GetExceptionCode();
      }
      _SEH_END;
-     
+
      if(!NT_SUCCESS(Status))
      {
        return Status;
@@ -1699,18 +1862,18 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
                                        (PVOID *)&FileObject,
                                        NULL);
     if (Status != STATUS_SUCCESS) return(Status);
-   
-   
+
+
    DeviceObject = FileObject->DeviceObject;
-   
-   
-   Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+
+
+   Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (Irp==NULL)
      {
- ObDereferenceObject(FileObject);
- return STATUS_UNSUCCESSFUL;
      ObDereferenceObject(FileObject);
      return STATUS_UNSUCCESSFUL;
      }
-   
+
    if (Event == NULL)
      {
        Event = &FileObject->Event;
@@ -1726,24 +1889,24 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
    Irp->UserBuffer = Buffer;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-   
+
    IoStack = IoGetNextIrpStackLocation(Irp);
-   
+
    IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
    IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
    IoStack->Flags = 0;
    IoStack->Control = 0;
    IoStack->DeviceObject = DeviceObject;
    IoStack->FileObject = FileObject;
-   
+
    if (WatchTree)
      {
- IoStack->Flags = SL_WATCH_TREE;
      IoStack->Flags = SL_WATCH_TREE;
      }
 
    IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
    IoStack->Parameters.NotifyDirectory.Length = BufferSize;
-   
+
    Status = IoCallDriver(FileObject->DeviceObject,Irp);
 
    /* FIXME: Should we wait here or not for synchronously opened files? */
@@ -1756,197 +1919,179 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
  */
 NTSTATUS
 STDCALL
-NtLockFile(IN HANDLE   FileHandle,
-           IN HANDLE   EventHandle OPTIONAL,
-           IN PIO_APC_ROUTINE  ApcRoutine OPTIONAL,
-           IN PVOID   ApcContext OPTIONAL,
+NtLockFile(IN HANDLE FileHandle,
+           IN HANDLE EventHandle OPTIONAL,
+           IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+           IN PVOID ApcContext OPTIONAL,
            OUT PIO_STATUS_BLOCK IoStatusBlock,
-           IN PLARGE_INTEGER  ByteOffset,
-           IN PLARGE_INTEGER  Length,
-           IN PULONG   Key,
-           IN BOOLEAN   FailImmediatedly,
-           IN BOOLEAN   ExclusiveLock
- )
+           IN PLARGE_INTEGER ByteOffset,
+           IN PLARGE_INTEGER Length,
+           IN PULONG  Key,
+           IN BOOLEAN FailImmediately,
+           IN BOOLEAN ExclusiveLock)
 {
-  PFILE_OBJECT FileObject = NULL;
-  PLARGE_INTEGER LocalLength = NULL;
-  PKEVENT Event = NULL;
-  PIRP Irp = NULL;
-  PIO_STACK_LOCATION StackPtr;
-  PDEVICE_OBJECT DeviceObject;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status;
+    PFILE_OBJECT FileObject = NULL;
+    PLARGE_INTEGER LocalLength = NULL;
+    PIRP Irp = NULL;
+    PIO_STACK_LOCATION StackPtr;
+    PDEVICE_OBJECT DeviceObject;
+    PKEVENT Event = NULL;
+    BOOLEAN LocalEvent = FALSE;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    OBJECT_HANDLE_INFORMATION HandleInformation;
+     
+    /* FIXME: instead of this, use SEH */
+    if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
 
-  // FIXME: instead of this, use SEH when available?
-  if (!Length || !ByteOffset)
-  {
-    Status = STATUS_INVALID_PARAMETER;
-    goto fail;
-  }
-
-  PreviousMode = ExGetPreviousMode();
-
-  Status = ObReferenceObjectByHandle(FileHandle,
-         0,
-         IoFileObjectType,
-         PreviousMode,
-         (PVOID*)&FileObject,
-         NULL);
-  if (!NT_SUCCESS(Status))
-  {
-    goto fail;
-  }
-
-  DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
-  Irp = IoAllocateIrp(DeviceObject->StackSize,
-        TRUE);
-  if (Irp == NULL)
-  {
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    goto fail;
-  }
-
-  if (EventHandle != NULL && !FailImmediatedly)
-  {
-    Status = ObReferenceObjectByHandle(EventHandle,
-           SYNCHRONIZE,
-           ExEventObjectType,
-           PreviousMode,
-           (PVOID*)&Event,
-           NULL);
-    if (!NT_SUCCESS(Status))
+    /* Get File Object */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       0,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&FileObject,
+                                       &HandleInformation);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
+    if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
     {
-      goto fail;
-    }
-  }
-  else
-  {
-    Event = &FileObject->Event;
-    KeResetEvent(Event);
-  }
-
-  /* Trigger FileObject/Event dereferencing */
-  Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
-  Irp->RequestorMode = PreviousMode;
-  Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
-  Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
-  Irp->UserEvent = Event;
-  Irp->UserIosb = IoStatusBlock;
-  Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
-  StackPtr = IoGetNextIrpStackLocation(Irp);
-  StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
-  StackPtr->MinorFunction = IRP_MN_LOCK;
-  StackPtr->FileObject = FileObject;
-
-  if (ExclusiveLock)
-    StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
-
-  if (FailImmediatedly)
-    StackPtr->Flags |= SL_FAIL_IMMEDIATELY;
-
-  LocalLength = ExAllocatePoolWithTag(NonPagedPool,
-          sizeof(LARGE_INTEGER),
-          TAG_LOCK);
-  if (!LocalLength)
-  {
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    goto fail;
-  }
-
-  *LocalLength = *Length;
-
-  StackPtr->Parameters.LockControl.Length = LocalLength;
-  StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
-  StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
-  IoSetCompletionRoutine(Irp,
-    IopLockFileCompletionRoutine,
-    LocalLength,
-    TRUE,
-    TRUE,
-    TRUE);
-
-  /* Can't touch FileObject after IoCallDriver since it might be freed */
-  Status = IofCallDriver(DeviceObject, Irp);
-  if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
-  {
-    Status = KeWaitForSingleObject(Event,
-       Executive,
-       PreviousMode,
-       FileObject->Flags & FO_ALERTABLE_IO,
-       NULL);
-
-    if (Status != STATUS_WAIT_0)
-    {
-      DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n");
-      /*
-       * FIXME: Should do some special processing here if alertable wait
-       * was interupted by user apc or a thread alert (STATUS_ALERTED, STATUS_USER_APC)
-       */
-      return Status; /* Set status to something else? */
+        DPRINT1("Invalid access rights\n");
+        ObDereferenceObject(FileObject);
+        return STATUS_ACCESS_DENIED;
     }
 
-    Status = IoStatusBlock->Status;
-  }
-
-  return Status;
+    /* Get Event Object */
+    if (EventHandle)
+    {
+        Status = ObReferenceObjectByHandle(EventHandle,
+                                           EVENT_MODIFY_STATE,
+                                           ExEventObjectType,
+                                           PreviousMode,
+                                           (PVOID *)&Event,
+                                           NULL);
+        if (Status != STATUS_SUCCESS) return(Status);
+        KeClearEvent(Event);
+    }
 
-fail:;
-  if (LocalLength)
-    ExFreePool(LocalLength);
+    /* Check if this is a direct open or not */
+    if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+    {
+        DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+    }
+    else
+    {
+        DeviceObject = IoGetRelatedDeviceObject(FileObject);
+    }
 
-  if (Irp)
-    IoFreeIrp(Irp);
+    /* 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;
+    }
+
+    /* Allocate the IRP */
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Allocate local buffer */  
+    LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+                                        sizeof(LARGE_INTEGER),
+                                        TAG_LOCK);
+    if (!LocalLength)
+    {
+        IoFreeIrp(Irp);
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    *LocalLength = *Length;
+    
+    /* Set up the IRP */
+    Irp->RequestorMode = PreviousMode;
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = Event;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+    /* Set up Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+    StackPtr->MinorFunction = IRP_MN_LOCK;
+    StackPtr->FileObject = FileObject;
+    
+    /* Set Parameters */
+    StackPtr->Parameters.LockControl.Length = LocalLength;
+    StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
+    StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
 
-  if (Event)
-    ObDereferenceObject(Event);
+    /* Set Flags */
+    if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
+    if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
 
-  if (FileObject)
-    ObDereferenceObject(FileObject);
+    /* Call the Driver */
+    FileObject->LockOperation = TRUE;
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (!LocalEvent)
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
 
-  return Status;
+    /* Return the Status */
+    return Status;
 }
 
 /*
  * NAME       EXPORTED
  *  NtOpenFile@24
- *  
+ *
  * DESCRIPTION
  *  Opens an existing file (simpler than NtCreateFile).
  *
  * ARGUMENTS
  * FileHandle (OUT)
  *  Variable that receives the file handle on return;
- *  
+ *
  * DesiredAccess
  *  Access desired by the caller to the file;
- *  
+ *
  * ObjectAttributes
  *  Structue describing the file to be opened;
- *  
+ *
  * IoStatusBlock (OUT)
  *  Receives details about the result of the
  *  operation;
- *  
+ *
  * ShareAccess
  *  Type of shared access the caller requires;
- *  
+ *
  * OpenOptions
  *  Options for the file open.
  *
  * RETURN VALUE
  *  Status.
- *  
+ *
  * NOTE
  *  Undocumented.
  *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtOpenFile(PHANDLE FileHandle,
            ACCESS_MASK DesiredAccess,
@@ -1972,41 +2117,41 @@ NtOpenFile(PHANDLE FileHandle,
                         0);
 }
 
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
                       OUT PFILE_BASIC_INFORMATION FileInformation)
 {
-  IO_STATUS_BLOCK IoStatusBlock;
-  HANDLE FileHandle;
-  NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE FileHandle;
+    NTSTATUS Status;
 
-  /* Open the file */
-  Status = ZwOpenFile (&FileHandle,
-         SYNCHRONIZE | FILE_READ_ATTRIBUTES,
-         ObjectAttributes,
-         &IoStatusBlock,
-         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-         FILE_SYNCHRONOUS_IO_NONALERT);
-  if (!NT_SUCCESS (Status))
+    /* Open the file */
+    Status = ZwOpenFile(&FileHandle,
+                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+                        ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS (Status))
     {
-      DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
-      return Status;
+        DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
+        return Status;
     }
 
-  /* Get file attributes */
-  Status = ZwQueryInformationFile (FileHandle,
-       &IoStatusBlock,
-       FileInformation,
-       sizeof(FILE_BASIC_INFORMATION),
-       FileBasicInformation);
-  ZwClose (FileHandle);
-  if (!NT_SUCCESS (Status))
+    /* Get file attributes */
+    Status = ZwQueryInformationFile(FileHandle,
+                                    &IoStatusBlock,
+                                    FileInformation,
+                                    sizeof(FILE_BASIC_INFORMATION),
+                                    FileBasicInformation);
+    if (!NT_SUCCESS (Status))
     {
-      DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
+        DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
     }
 
-  return Status;
+    ZwClose(FileHandle);
+    return Status;
 }
 
 /*
@@ -2027,10 +2172,10 @@ NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
  *  FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
  *
  *   Length = Size of the storage supplied
- *   FileInformationClass = Indicates the type of information requested.  
- *   ReturnSingleEntry = Specify true if caller only requests the first 
+ *   FileInformationClass = Indicates the type of information requested.
+ *   ReturnSingleEntry = Specify true if caller only requests the first
  *                            directory found.
- *   FileName = Initial directory name to query, that may contain wild 
+ *   FileName = Initial directory name to query, that may contain wild
  *                   cards.
  *        RestartScan = Number of times the action should be repeated
  * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
@@ -2038,7 +2183,7 @@ NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
  *       STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
  */
 NTSTATUS
-STDCALL 
+STDCALL
 NtQueryDirectoryFile(IN HANDLE FileHandle,
                      IN HANDLE PEvent OPTIONAL,
                      IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
@@ -2049,116 +2194,133 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
                      IN FILE_INFORMATION_CLASS FileInformationClass,
                      IN BOOLEAN ReturnSingleEntry,
                      IN PUNICODE_STRING FileName OPTIONAL,
-                     IN BOOLEAN RestartScan
- )
-
+                     IN BOOLEAN RestartScan)
 {
-   PIRP Irp;
-   PDEVICE_OBJECT DeviceObject;
-   PFILE_OBJECT FileObject;
-   PIO_STACK_LOCATION IoStack;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   DPRINT("NtQueryDirectoryFile()\n");
-   
-   PAGED_CODE();
+    PIRP Irp;
+    PDEVICE_OBJECT DeviceObject;
+    PFILE_OBJECT FileObject;
+    PIO_STACK_LOCATION StackPtr;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    BOOLEAN LocalEvent = FALSE;
+    PKEVENT Event = NULL;
 
-   PreviousMode = ExGetPreviousMode();
-   
-   if(PreviousMode != KernelMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForWrite(IoStatusBlock,
-                     sizeof(IO_STATUS_BLOCK),
-                     sizeof(ULONG));
-       ProbeForWrite(FileInformation,
-                     Length,
-                     sizeof(ULONG));
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
+    DPRINT("NtQueryDirectoryFile()\n");
+    PAGED_CODE();
 
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
+    /* Validate User-Mode Buffers */
+    if(PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+            ProbeForWrite(FileInformation,
+                          Length,
+                          sizeof(ULONG));
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
 
-   Status = ObReferenceObjectByHandle(FileHandle,
-          FILE_LIST_DIRECTORY,
-          IoFileObjectType,
-          PreviousMode,
-          (PVOID *)&FileObject,
-          NULL);
-   
-   if (Status != STATUS_SUCCESS)
-     {
- return(Status);
-     }
-   DeviceObject = FileObject->DeviceObject;
-   
-   Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
-   if (Irp==NULL)
-     {
- ObDereferenceObject(FileObject);
- return STATUS_UNSUCCESSFUL;
-     }
-   
-   /* Trigger FileObject/Event dereferencing */
-   Irp->Tail.Overlay.OriginalFileObject = FileObject;
-   Irp->RequestorMode = PreviousMode;
-   Irp->UserIosb = IoStatusBlock;
-   Irp->UserEvent = &FileObject->Event;
-   Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   KeResetEvent( &FileObject->Event );
-   Irp->UserBuffer=FileInformation;
-   Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
-   Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-   
-   IoStack = IoGetNextIrpStackLocation(Irp);
-   
-   IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
-   IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
-   IoStack->Flags = 0;
-   IoStack->Control = 0;
-   IoStack->DeviceObject = DeviceObject;
-   IoStack->FileObject = FileObject;
-   
-   if (RestartScan)
-     {
- IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
-     }
-   if (ReturnSingleEntry)
-     {
- IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
-     }
-   if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0)
-     {
- IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
-     }
+        if(!NT_SUCCESS(Status)) return Status;
+    }
 
-   IoStack->Parameters.QueryDirectory.FileInformationClass = 
-     FileInformationClass;
-   IoStack->Parameters.QueryDirectory.FileName = FileName;
-   IoStack->Parameters.QueryDirectory.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;
-     }
+    /* Get File Object */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       FILE_LIST_DIRECTORY,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID *)&FileObject,
+                                       NULL);
+    if (Status != STATUS_SUCCESS) return(Status);
+
+    /* Get Event Object */
+    if (PEvent)
+    {
+        Status = ObReferenceObjectByHandle(PEvent,
+                                           EVENT_MODIFY_STATE,
+                                           ExEventObjectType,
+                                           PreviousMode,
+                                           (PVOID *)&Event,
+                                           NULL);
+        if (Status != STATUS_SUCCESS) return(Status);
+        KeClearEvent(Event);
+    }
+
+    /* 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;
+    }
+
+    /* Allocate the IRP */
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Set up the IRP */
+    Irp->RequestorMode = PreviousMode;
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = Event;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->UserBuffer = FileInformation;
+    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+
+    /* Set up Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->FileObject = FileObject;
+    StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
+    StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
+
+    /* Set Parameters */
+    StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
+    StackPtr->Parameters.QueryDirectory.FileName = FileName;
+    StackPtr->Parameters.QueryDirectory.FileIndex = 0;
+    StackPtr->Parameters.QueryDirectory.Length = Length;
+    StackPtr->Flags = 0;
+    if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
+    if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
+
+    /* Call the Driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (!LocalEvent)
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
 
-   return(Status);
+    /* Return the Status */
+    return Status;
 }
 
 /*
@@ -2179,41 +2341,41 @@ NtQueryEaFile(IN HANDLE FileHandle,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
 {
-  IO_STATUS_BLOCK IoStatusBlock;
-  HANDLE FileHandle;
-  NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE FileHandle;
+    NTSTATUS Status;
 
-  /* Open the file */
-  Status = ZwOpenFile (&FileHandle,
-         SYNCHRONIZE | FILE_READ_ATTRIBUTES,
-         ObjectAttributes,
-         &IoStatusBlock,
-         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-         FILE_SYNCHRONOUS_IO_NONALERT);
-  if (!NT_SUCCESS (Status))
+    /* Open the file */
+    Status = ZwOpenFile(&FileHandle,
+                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+                        ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS (Status))
     {
-      DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
-      return Status;
+        DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
+        return Status;
     }
 
-  /* Get file attributes */
-  Status = ZwQueryInformationFile (FileHandle,
-       &IoStatusBlock,
-       FileInformation,
-       sizeof(FILE_NETWORK_OPEN_INFORMATION),
-       FileNetworkOpenInformation);
-  ZwClose (FileHandle);
-  if (!NT_SUCCESS (Status))
+    /* Get file attributes */
+    Status = ZwQueryInformationFile(FileHandle,
+                                    &IoStatusBlock,
+                                    FileInformation,
+                                    sizeof(FILE_NETWORK_OPEN_INFORMATION),
+                                    FileNetworkOpenInformation);
+    if (!NT_SUCCESS (Status))
     {
-      DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
+        DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
     }
 
-  return Status;
+    ZwClose (FileHandle);
+    return Status;
 }
 
 /*
@@ -2240,7 +2402,7 @@ NtQueryInformationFile(HANDLE FileHandle,
     ASSERT(IoStatusBlock != NULL);
     ASSERT(FileInformation != NULL);
 
-    DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+    DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
            "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
             Length, FileInformationClass);
 
@@ -2283,8 +2445,8 @@ NtQueryInformationFile(HANDLE FileHandle,
         return STATUS_ACCESS_DENIED;
     }
 
-    DPRINT("FileObject %x\n", FileObject);
-        
+    DPRINT("FileObject 0x%p\n", FileObject);
+
     /* Check if this is a direct open or not */
     if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
     {
@@ -2294,7 +2456,7 @@ NtQueryInformationFile(HANDLE FileHandle,
     {
         DeviceObject = IoGetRelatedDeviceObject(FileObject);
     }
-    
+
     /* Check if we should use Sync IO or not */
     if (FileObject->Flags & FO_SYNCHRONOUS_IO)
     {
@@ -2309,15 +2471,15 @@ NtQueryInformationFile(HANDLE FileHandle,
     }
 
     /* Allocate the IRP */
-    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
     {
         ObDereferenceObject(FileObject);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
-    
+
     /* Allocate the System Buffer */
-    if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, 
-                                                                  Length, 
+    if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                                  Length,
                                                                   TAG_SYSB)))
     {
         IoFreeIrp(Irp);
@@ -2334,7 +2496,7 @@ NtQueryInformationFile(HANDLE FileHandle,
     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;
@@ -2343,26 +2505,26 @@ NtQueryInformationFile(HANDLE FileHandle,
     /* 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, 
+            KeWaitForSingleObject(&Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = IoStatusBlock->Status;
         }
         else
         {
             KeWaitForSingleObject(&FileObject->Event,
-                                  Executive, 
-                                  PreviousMode, 
-                                  FileObject->Flags & FO_ALERTABLE_IO, 
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
             Status = FileObject->FinalStatus;
         }
@@ -2405,7 +2567,7 @@ NtQueryQuotaInformationFile(IN HANDLE FileHandle,
  *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtReadFile(IN HANDLE FileHandle,
            IN HANDLE Event OPTIONAL,
@@ -2417,133 +2579,178 @@ NtReadFile(IN HANDLE FileHandle,
            IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
            IN PULONG Key OPTIONAL)
 {
-  NTSTATUS Status;
-  PFILE_OBJECT FileObject;
-  PIRP Irp = NULL;
-  PIO_STACK_LOCATION StackPtr;
-  KPROCESSOR_MODE PreviousMode;
-  PKEVENT EventObject = NULL;
-
-  DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
-  "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
-  IoStatusBlock);
-
-  if (IoStatusBlock == NULL)
-    return STATUS_ACCESS_VIOLATION;
-
-  PreviousMode = ExGetPreviousMode();
-
-  Status = ObReferenceObjectByHandle(FileHandle,
-         FILE_READ_DATA,
-         IoFileObjectType,
-         PreviousMode,
-         (PVOID*)&FileObject,
-         NULL);
-  if (!NT_SUCCESS(Status))
-  {
-    return Status;
-  }
-
-  if (ByteOffset == NULL ||
-      (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
-       ByteOffset->u.HighPart == 0xffffffff))
-  {
-    /* a valid ByteOffset is required if asynch. op. */
-    if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
-    {
-      DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
-      ObDereferenceObject(FileObject);
-      return STATUS_INVALID_PARAMETER;
-    }
-
-    ByteOffset = &FileObject->CurrentByteOffset;
-  }
-
-  if (Event != NULL)
-  {
-    Status = ObReferenceObjectByHandle(Event,
-           SYNCHRONIZE,
-           ExEventObjectType,
-           PreviousMode,
-           (PVOID*)&EventObject,
-           NULL);
-    if (!NT_SUCCESS(Status))
-      {
-        ObDereferenceObject(FileObject);
- return Status;
-      }
+    NTSTATUS Status = STATUS_SUCCESS;
+    PFILE_OBJECT FileObject;
+    PIRP Irp = NULL;
+    PDEVICE_OBJECT DeviceObject;
+    PIO_STACK_LOCATION StackPtr;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    BOOLEAN LocalEvent = FALSE;
+    PKEVENT EventObject = NULL;
 
-    KeClearEvent(EventObject);
-  }
-
-  _SEH_TRY
-  {
-     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
-            FileObject->DeviceObject,
-            Buffer,
-            Length,
-            ByteOffset,
-     EventObject,
+    DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+           "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
             IoStatusBlock);
-  }
-  _SEH_HANDLE
-  {
-     Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  if (!NT_SUCCESS(Status) || Irp == NULL)
-  {
-     if (Event)
-     {
-        ObDereferenceObject(&EventObject);
-     }
-     ObDereferenceObject(FileObject);
-     if (Irp)
-     {
-        IoFreeIrp(Irp);
-     }
-     return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
-  }
-
-  KeClearEvent(&FileObject->Event);
-
-  /* Trigger FileObject/Event dereferencing */
-  Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
-  Irp->RequestorMode = PreviousMode;
-
-  Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
-  Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
-
-  StackPtr = IoGetNextIrpStackLocation(Irp);
-  StackPtr->FileObject = FileObject;
-  StackPtr->Parameters.Read.Key = Key ? *Key : 0;
+    PAGED_CODE();
 
-  Status = IoCallDriver(FileObject->DeviceObject, Irp);
-  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)
+    /* Validate User-Mode Buffers */
+    if(PreviousMode != KernelMode)
     {
-      /* Wait failed. */
-      return Status;
-    }
+        _SEH_TRY
+        {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+            #if 0
+            ProbeForWrite(Buffer,
+                          Length,
+                          sizeof(ULONG));
+            #endif
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
 
-    Status = IoStatusBlock->Status;
-  }
+        if(!NT_SUCCESS(Status)) return Status;
+    }
 
-  return Status;
-}
+    /* Get File Object */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       FILE_READ_DATA,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&FileObject,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check the Byte Offset */
+    if (!ByteOffset ||
+        (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+         ByteOffset->u.HighPart == -1))
+    {
+        /* a valid ByteOffset is required if asynch. op. */
+        if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+        {
+            DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
+            ObDereferenceObject(FileObject);
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Use the Current Byte OFfset */
+        ByteOffset = &FileObject->CurrentByteOffset;
+    }
+
+    /* Check for event */
+    if (Event)
+    {
+        /* Reference it */
+        Status = ObReferenceObjectByHandle(Event,
+                                           EVENT_MODIFY_STATE,
+                                           ExEventObjectType,
+                                           PreviousMode,
+                                           (PVOID*)&EventObject,
+                                           NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            return Status;
+        }
+        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;
+    }
+
+    /* Create the IRP */
+    _SEH_TRY
+    {
+        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                           DeviceObject,
+                                           Buffer,
+                                           Length,
+                                           ByteOffset,
+                                           EventObject,
+                                           IoStatusBlock);
+        if (Irp == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+    _SEH_HANDLE
+    {
+        Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    /* Cleanup if IRP Allocation Failed */
+    if (!NT_SUCCESS(Status))
+    {
+        if (Event) ObDereferenceObject(EventObject);
+        ObDereferenceObject(FileObject);
+        return Status;
+    }
+
+    /* Set up IRP Data */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = PreviousMode;
+    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+    Irp->Flags |= IRP_READ_OPERATION;
+#if 0
+    /* FIXME:
+     *    Vfat doesn't handle non cached files correctly.
+     */     
+    if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
+#endif      
+
+    /* Setup Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->FileObject = FileObject;
+    StackPtr->Parameters.Read.Key = Key ? *Key : 0;
+
+    /* Call the Driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (!LocalEvent)
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
+
+    /* Return the Status */
+    return Status;
+}
 
 /*
  * NAME       EXPORTED
  * NtReadFileScatter
- * 
+ *
  * DESCRIPTION
  *
  * ARGUMENTS
@@ -2571,7 +2778,7 @@ NtReadFileScatter(IN HANDLE FileHandle,
 /*
  * @unimplemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtSetEaFile(IN HANDLE FileHandle,
             IN PIO_STATUS_BLOCK IoStatusBlock,
@@ -2592,181 +2799,288 @@ NtSetInformationFile(HANDLE FileHandle,
                      ULONG Length,
                      FILE_INFORMATION_CLASS 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;
-
-  ASSERT(IoStatusBlock != NULL);
-  ASSERT(FileInformation != NULL);
-
-  DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
-         "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
-         Length, FileInformationClass);
-
-  PreviousMode = ExGetPreviousMode();
-
-  /* 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;
+    OBJECT_HANDLE_INFORMATION HandleInformation;
+    PIO_STACK_LOCATION StackPtr;
+    PFILE_OBJECT FileObject;
+    PDEVICE_OBJECT DeviceObject;
+    PIRP Irp;
+    KEVENT Event;
+    BOOLEAN LocalEvent = FALSE;
+    NTSTATUS Status = STATUS_SUCCESS;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    BOOLEAN Failed = FALSE;
+
+    DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
+           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
+            Length, FileInformationClass);
+
+    if (PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            if (IoStatusBlock != NULL)
+            {
+                ProbeForWrite(IoStatusBlock,
+                              sizeof(IO_STATUS_BLOCK),
+                              sizeof(ULONG));
+            }
+            
+            if (Length != 0)
+            {
+                ProbeForRead(FileInformation,
+                             Length,
+                             1);
+            }
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
     }
     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;
+        ASSERT(IoStatusBlock != NULL);
+        ASSERT(FileInformation != NULL);
+    }
 
-        ObDereferenceObject(Queue);
-      }
+    /* 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 0x%p\n", FileObject);
+
+    /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
+    /* Handle IO Completion Port quickly */
+    if (FileInformationClass == FileCompletionInformation)
+    {
+        PVOID Queue;
+        PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
+        PIO_COMPLETION_CONTEXT Context;
+
+        if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+        {
+            Status = STATUS_INFO_LENGTH_MISMATCH;
+        }
+        else
+        {
+            /* Reference the Port */
+            Status = ObReferenceObjectByHandle(CompletionInfo->Port,
+                                               IO_COMPLETION_MODIFY_STATE,
+                                               IoCompletionType,
+                                               PreviousMode,
+                                               (PVOID*)&Queue,
+                                               NULL);
+            if (NT_SUCCESS(Status))
+            {
+                /* Allocate the Context */
+                Context = ExAllocatePoolWithTag(PagedPool,
+                                                sizeof(IO_COMPLETION_CONTEXT),
+                                                TAG('I', 'o', 'C', 'p'));
+
+                /* Set the Data */
+                Context->Key = CompletionInfo->Key;
+                Context->Port = Queue;
+                FileObject->CompletionContext = Context;
+
+                /* Dereference the Port now */
+                ObDereferenceObject(Queue);
+            }
+        }
+
+        /* Complete the I/O */
+        ObDereferenceObject(FileObject);
+        return Status;
+    }
+
+    /* 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;
+    }
+
+    /* Allocate the IRP */
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Allocate the System Buffer */
+    if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                                  Length,
+                                                                  TAG_SYSB)))
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failfreeirp;
+    }
+
+    /* Copy the data inside */
+    if (PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            /* no need to probe again */
+            RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+                          FileInformation,
+                          Length);
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        if (!NT_SUCCESS(Status))
+        {
+            ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer,
+                              TAG_SYSB);
+            Irp->AssociatedIrp.SystemBuffer = NULL;
+failfreeirp:
+            IoFreeIrp(Irp);
+            ObDereferenceObject(FileObject);
+            return Status;
+        }
+    }
+    else
+    {
+        RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+                      FileInformation,
+                      Length);
+    }
+
+    /* Set up the IRP */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = PreviousMode;
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
+    Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+
+    /* Set up Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
+    StackPtr->FileObject = FileObject;
+
+    /* Set the Parameters */
+    StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
+    StackPtr->Parameters.SetFile.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);
+            _SEH_TRY
+            {
+                Status = IoStatusBlock->Status;
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+        }
+        else
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            _SEH_TRY
+            {
+                Status = FileObject->FinalStatus;
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+        }
     }
 
-    ObDereferenceObject(FileObject);
+    /* Return the Status */
     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;
-  }
-
-  ExFreePool(SystemBuffer);
-
-  return Status;
 }
 
 /*
  * @unimplemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtSetQuotaInformationFile(HANDLE FileHandle,
                           PIO_STATUS_BLOCK IoStatusBlock,
-                          PFILE_USER_QUOTA_INFORMATION Buffer,
+                          PFILE_QUOTA_INFORMATION Buffer,
                           ULONG BufferLength)
 {
     UNIMPLEMENTED;
@@ -2784,93 +3098,124 @@ NtUnlockFile(IN  HANDLE FileHandle,
              IN  PLARGE_INTEGER Length,
              OUT PULONG Key OPTIONAL)
 {
-  PFILE_OBJECT FileObject = NULL;
-  PLARGE_INTEGER LocalLength = NULL;
-  PIRP Irp = NULL;
-  PIO_STACK_LOCATION StackPtr;
-  PDEVICE_OBJECT DeviceObject;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status;
+    PFILE_OBJECT FileObject = NULL;
+    PLARGE_INTEGER LocalLength = NULL;
+    PIRP Irp = NULL;
+    PIO_STACK_LOCATION StackPtr;
+    PDEVICE_OBJECT DeviceObject;
+    KEVENT Event;
+    BOOLEAN LocalEvent = FALSE;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    OBJECT_HANDLE_INFORMATION HandleInformation;
+     
+    /* FIXME: instead of this, use SEH */
+    if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
 
-  // FIXME: instead of this, use SEH when available
-  if (!Length || !ByteOffset)
-  {
-    Status = STATUS_INVALID_PARAMETER;
-    goto fail;
-  }
-
-  PreviousMode = ExGetPreviousMode();
-
-  /*
-   * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
-   * It should ONLY fail if we desire an access that conflict with granted access!
-   */
-  Status = ObReferenceObjectByHandle(FileHandle,
-         0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
-         IoFileObjectType,
-         PreviousMode,
-         (PVOID*)&FileObject,
-         NULL);
-  if (!NT_SUCCESS(Status))
-  {
-    goto fail;
-  }
-
-  DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
-  Irp = IoAllocateIrp(DeviceObject->StackSize,
-        TRUE);
-  if (Irp == NULL)
-  {
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    goto fail;
-  }
-
-  /* Trigger FileObject/Event dereferencing */
-  Irp->Tail.Overlay.OriginalFileObject = FileObject;
-  Irp->RequestorMode = PreviousMode;
-  Irp->UserIosb = IoStatusBlock;
-  Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
-  StackPtr = IoGetNextIrpStackLocation(Irp);
-  StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
-  StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
-  StackPtr->DeviceObject = DeviceObject;
-  StackPtr->FileObject = FileObject;
-
-  LocalLength = ExAllocatePoolWithTag(NonPagedPool,
-          sizeof(LARGE_INTEGER),
-          TAG_LOCK);
-  if (!LocalLength)
-  {
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    goto fail;
-  }
-
-  *LocalLength = *Length;
-
-  StackPtr->Parameters.LockControl.Length = LocalLength;
-  StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
-  StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
-
-  /* Allways synchronous */
-  Status = IofCallDriver(DeviceObject, Irp);
-
-  ExFreePool(LocalLength);
-
-  return Status;
-
-fail:;
-  if (LocalLength)
-    ExFreePool(LocalLength);
-
-  if (Irp)
-    IoFreeIrp(Irp);
+    /* Get File Object */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       0,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&FileObject,
+                                       &HandleInformation);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
+    if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+    {
+        DPRINT1("Invalid access rights\n");
+        ObDereferenceObject(FileObject);
+        return STATUS_ACCESS_DENIED;
+    }
+
+    /* Check if this is a direct open or not */
+    if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+    {
+        DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+    }
+    else
+    {
+        DeviceObject = IoGetRelatedDeviceObject(FileObject);
+    }
 
-  if (FileObject)
-    ObDereferenceObject(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;
+    }
+
+    /* Allocate the IRP */
+    if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Allocate local buffer */  
+    LocalLength = ExAllocatePoolWithTag(NonPagedPool,
+                                        sizeof(LARGE_INTEGER),
+                                        TAG_LOCK);
+    if (!LocalLength)
+    {
+        IoFreeIrp(Irp);
+        ObDereferenceObject(FileObject);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    *LocalLength = *Length;
+    
+    /* Set up the IRP */
+    Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
+    Irp->RequestorMode = PreviousMode;
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+    /* Set up Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+    StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
+    StackPtr->FileObject = FileObject;
+    
+    /* Set Parameters */
+    StackPtr->Parameters.LockControl.Length = LocalLength;
+    StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
+    StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
+
+    /* 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;
+        }
+    }
 
-  return Status;
+    /* Return the Status */
+    return Status;
 }
 
 /*
@@ -2887,7 +3232,7 @@ fail:;
  *
  * @implemented
  */
-NTSTATUS 
+NTSTATUS
 STDCALL
 NtWriteFile (IN HANDLE FileHandle,
              IN HANDLE Event OPTIONAL,
@@ -2899,158 +3244,209 @@ NtWriteFile (IN HANDLE FileHandle,
              IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
              IN PULONG Key OPTIONAL)
 {
-  OBJECT_HANDLE_INFORMATION HandleInformation;
-  NTSTATUS Status;
-  PFILE_OBJECT FileObject;
-  PIRP Irp = NULL;
-  PIO_STACK_LOCATION StackPtr;
-  KPROCESSOR_MODE PreviousMode;
-  PKEVENT EventObject = NULL;
-  LARGE_INTEGER Offset;
-
-  DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
-  "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
-  IoStatusBlock);
-
-  if (IoStatusBlock == NULL)
-    return STATUS_ACCESS_VIOLATION;
-
-  PreviousMode = ExGetPreviousMode();
-
-  Status = ObReferenceObjectByHandle(FileHandle,
-         0,
-         IoFileObjectType,
-         PreviousMode,
-         (PVOID*)&FileObject,
-         &HandleInformation);
-  if (!NT_SUCCESS(Status))
-  {
-    return Status;
-  }
-
-  /* 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;
-      }
+    OBJECT_HANDLE_INFORMATION HandleInformation;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PFILE_OBJECT FileObject;
+    PIRP Irp = NULL;
+    PDEVICE_OBJECT DeviceObject;
+    PIO_STACK_LOCATION StackPtr;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    BOOLEAN LocalEvent = FALSE;
+    PKEVENT EventObject = NULL;
 
-      ByteOffset = &FileObject->CurrentByteOffset;
-    }
-  }
-  else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
-  {
-    /* a valid ByteOffset is required if asynch. op. */
-    if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+    DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+            "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
+            IoStatusBlock);
+
+    /* Validate User-Mode Buffers */
+    if(PreviousMode != KernelMode)
     {
-      DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
-      ObDereferenceObject(FileObject);
-      return STATUS_INVALID_PARAMETER;
+        _SEH_TRY
+        {
+            #if 0
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+
+            ProbeForRead(Buffer,
+                         Length,
+                         sizeof(ULONG));
+            #endif
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if(!NT_SUCCESS(Status)) return Status;
     }
 
-    Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
-    Offset.u.HighPart = 0xffffffff;
-    ByteOffset = &Offset;
-  }
+    /* Get File Object */
+    Status = ObReferenceObjectByHandle(FileHandle,
+                                       0,
+                                       IoFileObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&FileObject,
+                                       &HandleInformation);
+    if (!NT_SUCCESS(Status)) return Status;
 
-  if (Event != NULL)
-  {
-    Status = ObReferenceObjectByHandle(Event,
-           SYNCHRONIZE,
-           ExEventObjectType,
-           PreviousMode,
-           (PVOID*)&EventObject,
-           NULL);
-    if (!NT_SUCCESS(Status))
+    /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
+    if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
     {
-      ObDereferenceObject(FileObject);
-      return Status;
+        DPRINT1("Invalid access rights\n");
+        ObDereferenceObject(FileObject);
+        return STATUS_ACCESS_DENIED;
     }
 
-    KeClearEvent(EventObject);
-  }
-
-  _SEH_TRY
-  {
-     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
-            FileObject->DeviceObject,
-            Buffer,
-            Length,
-            ByteOffset,
-     EventObject,
-            IoStatusBlock);
-  }
-  _SEH_HANDLE
-  {
-     Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  if (!NT_SUCCESS(Status) || Irp == NULL)
-  {
-     if (Event)
-     {
-        ObDereferenceObject(&EventObject);
-     }
-     ObDereferenceObject(FileObject);
-     if (Irp)
-     {
-        IoFreeIrp(Irp);
-     }
-     return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
-  }
+    /* Check if we got write Access */
+    if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
+    {
+        /* Check the Byte Offset */
+        if (!ByteOffset ||
+            (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+             ByteOffset->u.HighPart == -1))
+        {
+            /* a valid ByteOffset is required if asynch. op. */
+            if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
+            {
+                DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
+                ObDereferenceObject(FileObject);
+                return STATUS_INVALID_PARAMETER;
+            }
+
+            /* Use the Current Byte OFfset */
+            ByteOffset = &FileObject->CurrentByteOffset;
+        }
+    }
+    else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
+    {
+        /* 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;
+        }
 
-  KeClearEvent(&FileObject->Event);
+        /* Give the drivers somethign to understand */
+        ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
+        ByteOffset->u.HighPart = 0xffffffff;
+    }
 
-  /* Trigger FileObject/Event dereferencing */
-  Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    /* Check if we got an event */
+    if (Event)
+    {
+        /* Reference it */
+        Status = ObReferenceObjectByHandle(Event,
+                                           EVENT_MODIFY_STATE,
+                                           ExEventObjectType,
+                                           PreviousMode,
+                                           (PVOID*)&EventObject,
+                                           NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            return Status;
+        }
+        KeClearEvent(EventObject);
+    }
 
-  Irp->RequestorMode = PreviousMode;
+    /* Check if this is a direct open or not */
+    if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
+    {
+        DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+    }
+    else
+    {
+        DeviceObject = IoGetRelatedDeviceObject(FileObject);
+    }
 
-  Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
-  Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+    /* 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;
+    }
 
-  StackPtr = IoGetNextIrpStackLocation(Irp);
-  StackPtr->FileObject = FileObject;
-  StackPtr->Parameters.Write.Key = Key ? *Key : 0;
+    /* Build the IRP */
+    _SEH_TRY
+    {
+        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+                                           DeviceObject,
+                                           Buffer,
+                                           Length,
+                                           ByteOffset,
+                                           EventObject,
+                                           IoStatusBlock);
+        if (Irp == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+    _SEH_HANDLE
+    {
+        Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
 
-  Status = IoCallDriver(FileObject->DeviceObject, Irp);
-  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)
+    /* Cleanup on failure */
+    if (!NT_SUCCESS(Status))
     {
-      /* Wait failed. */
-      return Status;
+        if (Event)
+        {
+            ObDereferenceObject(&EventObject);
+        }
+        ObDereferenceObject(FileObject);
+        return Status;
     }
 
-    Status = IoStatusBlock->Status;
-  }
+   /* Set up IRP Data */
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->RequestorMode = PreviousMode;
+    Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
+    Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
+    Irp->Flags |= IRP_WRITE_OPERATION;
+#if 0    
+    /* FIXME:
+     *    Vfat doesn't handle non cached files correctly.
+     */     
+    if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
+#endif    
+
+    /* Setup Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->FileObject = FileObject;
+    StackPtr->Parameters.Write.Key = Key ? *Key : 0;
+    if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
+
+    /* Call the Driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        if (!LocalEvent)
+        {
+            KeWaitForSingleObject(&FileObject->Event,
+                                  Executive,
+                                  PreviousMode,
+                                  FileObject->Flags & FO_ALERTABLE_IO,
+                                  NULL);
+            Status = FileObject->FinalStatus;
+        }
+    }
 
-  return Status;
+    /* Return the Status */
+    return Status;
 }
 
 /*
  * NAME       EXPORTED
  * NtWriteFileGather
- * 
+ *
  * DESCRIPTION
  *
  * ARGUMENTS