Cleanup isn't necessary after calling the driver in NtQueryDirectoryFile.
[reactos.git] / reactos / ntoskrnl / io / file.c
index f4b70f8..c8107ff 100644 (file)
@@ -50,7 +50,7 @@ IopCreateFile(PVOID ObjectBody,
   POBJECT_TYPE ParentObjectType;
   NTSTATUS Status;
 
-  DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+  DPRINT("IopCreateFile(ObjectBody 0x%p, Parent 0x%p, RemainingPath %S)\n",
          ObjectBody,
          Parent,
          RemainingPath);
@@ -69,7 +69,7 @@ IopCreateFile(PVOID ObjectBody,
       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)->NameInfo->Name,
+             &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name,
              BODY_TO_HEADER(Parent)->Type->Name.Buffer,
              RemainingPath);
       return(STATUS_UNSUCCESSFUL);
@@ -81,7 +81,7 @@ IopCreateFile(PVOID ObjectBody,
                                       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);
     }
 
@@ -89,7 +89,7 @@ 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)
         {
@@ -129,8 +129,7 @@ IopCreateFile(PVOID ObjectBody,
               DeviceObject = DeviceObject->Vpb->DeviceObject;
               DPRINT("FsDeviceObject %lx\n", DeviceObject);
             }
-          RtlpCreateUnicodeString(&(FileObject->FileName),
-                                  RemainingPath, NonPagedPool);
+          RtlCreateUnicodeString(&FileObject->FileName, RemainingPath);
         }
     }
   else
@@ -143,18 +142,17 @@ IopCreateFile(PVOID ObjectBody,
         }
 
       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);
+      RtlCreateUnicodeString(&FileObject->FileName, RemainingPath);
     }
 
   DPRINT("FileObject->FileName %wZ\n",
          &FileObject->FileName);
   FileObject->DeviceObject = DeviceObject;
-  DPRINT("FileObject %x DeviceObject %x\n",
+  DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
          FileObject,
          DeviceObject);
   FileObject->Vpb = DeviceObject->Vpb;
@@ -241,7 +239,10 @@ IopSecurityFile(PVOID ObjectBody,
                 SECURITY_OPERATION_CODE OperationCode,
                 SECURITY_INFORMATION SecurityInformation,
                 PSECURITY_DESCRIPTOR SecurityDescriptor,
-                PULONG BufferLength)
+                PULONG BufferLength,
+                PSECURITY_DESCRIPTOR *OldSecurityDescriptor,    
+                POOL_TYPE PoolType,
+                PGENERIC_MAPPING GenericMapping)
 {
     IO_STATUS_BLOCK IoStatusBlock;
     PIO_STACK_LOCATION StackPtr;
@@ -324,6 +325,7 @@ IopSecurityFile(PVOID ObjectBody,
 
     /* Set Stack Parameters */
     StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = MajorFunction;
     StackPtr->FileObject = FileObject;
 
     /* Set Parameters */
@@ -399,7 +401,7 @@ IopQueryNameFile(PVOID ObjectBody,
                  ULONG Length,
                  PULONG ReturnLength)
 {
-    PVOID LocalInfo;
+    POBJECT_NAME_INFORMATION LocalInfo;
     PFILE_OBJECT FileObject;
     ULONG LocalReturnLength;
     NTSTATUS Status;
@@ -428,7 +430,7 @@ IopQueryNameFile(PVOID ObjectBody,
     
     /* Write Device Path */
     Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
-                                            &((POBJECT_NAME_INFORMATION)LocalInfo)->Name);
+                                            &(LocalInfo)->Name);
 
     /* Query the File name */
     Status = IoQueryFileInformation(FileObject,
@@ -531,10 +533,10 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle,
     BOOLEAN LocalEvent = FALSE;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
 
-    DPRINT("IopDeviceFsIoControl(DeviceHandle %x Event %x UserApcRoutine %x "
-           "UserApcContext %x IoStatusBlock %x IoControlCode %x "
-           "InputBuffer %x InputBufferLength %x OutputBuffer %x "
-           "OutputBufferLength %x)\n",
+    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);
@@ -749,17 +751,18 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    PFILE_OBJECT  FileObject = NULL;
    PDEVICE_OBJECT DeviceObject;
    PIRP   Irp;
-   PIO_STACK_LOCATION StackLoc;
+   PEXTENDED_IO_STACK_LOCATION StackLoc;
    IO_SECURITY_CONTEXT  SecurityContext;
    KPROCESSOR_MODE      AccessMode;
    HANDLE               LocalHandle;
-   IO_STATUS_BLOCK      LocalIoStatusBlock;
    LARGE_INTEGER        SafeAllocationSize;
    PVOID                SystemEaBuffer = NULL;
    NTSTATUS  Status = STATUS_SUCCESS;
+   AUX_DATA AuxData;
+   ACCESS_STATE AccessState;
 
-   DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
-          "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
+   DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
+          "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
           FileHandle,DesiredAccess,ObjectAttributes,
           ObjectAttributes->ObjectName->Buffer);
 
@@ -779,18 +782,13 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    {
      _SEH_TRY
      {
-       ProbeForWrite(FileHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
+       ProbeForWriteHandle(FileHandle);
        ProbeForWrite(IoStatusBlock,
                      sizeof(IO_STATUS_BLOCK),
                      sizeof(ULONG));
        if(AllocationSize != NULL)
        {
-         ProbeForRead(AllocationSize,
-                      sizeof(LARGE_INTEGER),
-                      sizeof(ULONG));
-         SafeAllocationSize = *AllocationSize;
+         SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
        }
        else
          SafeAllocationSize.QuadPart = 0;
@@ -844,6 +842,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
      DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
    }
 
+   /* First try to open an existing named object */
    Status = ObOpenObjectByName(ObjectAttributes,
                                NULL,
                                NULL,
@@ -854,6 +853,10 @@ IoCreateFile(OUT PHANDLE  FileHandle,
 
    if (NT_SUCCESS(Status))
    {
+      OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+      OBJECT_ATTRIBUTES tmpObjectAttributes;
+      UNICODE_STRING ObjectName;
+
       Status = ObReferenceObjectByHandle(LocalHandle,
                                          DesiredAccess,
                                          NULL,
@@ -870,8 +873,43 @@ IoCreateFile(OUT PHANDLE  FileHandle,
          ObDereferenceObject (DeviceObject);
          return STATUS_OBJECT_NAME_COLLISION;
       }
+
+      Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                          AccessMode,
+                                          NULL,
+                                          &ObjectCreateInfo,
+                                          &ObjectName);
+      if (!NT_SUCCESS(Status))
+      {
+         ObDereferenceObject (DeviceObject);
+         return Status;
+      }
+         
+      InitializeObjectAttributes(&tmpObjectAttributes,
+                                 NULL,
+                                 ObjectCreateInfo.Attributes & OBJ_INHERIT,
+                                 0,
+                                 NULL);
+      ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+      
       /* FIXME: wt... */
-      FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
+      Status = ObCreateObject(KernelMode,
+                              IoFileObjectType,
+                              &tmpObjectAttributes,
+                              KernelMode,
+                              NULL,
+                              sizeof(FILE_OBJECT),
+                              0,
+                              0,
+                              (PVOID*)&FileObject);
+
+   
+      /* Set File Object Data */
+      FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject); 
+      FileObject->Vpb = FileObject->DeviceObject->Vpb;
+
       /* HACK */
       FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
       DPRINT("%wZ\n", ObjectAttributes->ObjectName);
@@ -909,6 +947,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    if (!NT_SUCCESS(Status))
      {
        DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
+       ObMakeTemporaryObject(FileObject);
        ObDereferenceObject (FileObject);
        return Status;
      }
@@ -925,16 +964,22 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
      FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
 
+    /* 
+     * FIXME: We should get the access state from Ob once this function becomes
+     * a parse routine once the Ob is refactored.
+     */
+   SeCreateAccessState(&AccessState, &AuxData, FILE_ALL_ACCESS, NULL);
+
    SecurityContext.SecurityQos = NULL; /* ?? */
-   SecurityContext.AccessState = NULL; /* ?? */
+   SecurityContext.AccessState = &AccessState;
    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
@@ -950,7 +995,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
    //trigger FileObject/Event dereferencing
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->RequestorMode = AccessMode;
-   Irp->UserIosb = &LocalIoStatusBlock;
+   Irp->UserIosb = IoStatusBlock;
    Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
    Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
@@ -961,7 +1006,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
     * Get the stack location for the new
     * IRP and prepare it.
     */
-   StackLoc = IoGetNextIrpStackLocation(Irp);
+   StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
    StackLoc->MinorFunction = 0;
    StackLoc->Flags = (UCHAR)Options;
    StackLoc->Control = 0;
@@ -1016,7 +1061,7 @@ IoCreateFile(OUT PHANDLE  FileHandle,
                              AccessMode,
                              FALSE,
                              NULL);
-       Status = LocalIoStatusBlock.Status;
+       Status = IoStatusBlock->Status;
      }
    if (!NT_SUCCESS(Status))
      {
@@ -1031,7 +1076,6 @@ IoCreateFile(OUT PHANDLE  FileHandle,
        _SEH_TRY
          {
            *FileHandle = LocalHandle;
-           *IoStatusBlock = LocalIoStatusBlock;
          }
        _SEH_HANDLE
          {
@@ -1048,7 +1092,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;
 }
@@ -1112,7 +1156,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
        reason. These hacks need to be removed.
     */
 
-    DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
+    DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
             FileObject, DeviceObject);
     PAGED_CODE();
 
@@ -1134,7 +1178,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
 
     /* Choose Device Object */
     if (FileObject) DeviceObject = FileObject->DeviceObject;
-    DPRINT("DeviceObject %x\n", DeviceObject);
+    DPRINT("DeviceObject 0x%p\n", DeviceObject);
     
     /* HACK */
     DeviceObject = IoGetAttachedDevice(DeviceObject);
@@ -1238,7 +1282,7 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
                                         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);
@@ -1342,21 +1386,41 @@ STDCALL
 NtCancelIoFile(IN HANDLE FileHandle,
                OUT PIO_STATUS_BLOCK IoStatusBlock)
 {
-   NTSTATUS Status;
    PFILE_OBJECT FileObject;
    PETHREAD Thread;
-   PLIST_ENTRY IrpEntry;
    PIRP Irp;
    KIRQL OldIrql;
    BOOLEAN OurIrpsInList = FALSE;
    LARGE_INTEGER Interval;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PAGED_CODE();
+
+   PreviousMode = KeGetPreviousMode();
+
+   if (PreviousMode != KernelMode)
+   {
+      _SEH_TRY
+      {
+         ProbeForWrite(IoStatusBlock,
+                       sizeof(IO_STATUS_BLOCK),
+                       sizeof(ULONG));
+      }
+      _SEH_HANDLE
+      {
+         Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
 
-   if ((ULONG_PTR)IoStatusBlock >= (ULONG_PTR)MmUserProbeAddress &&
-       KeGetPreviousMode() == UserMode)
-      return STATUS_ACCESS_VIOLATION;
+      if (!NT_SUCCESS(Status)) return Status;
+   }
 
-   Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType,
-                                      KeGetPreviousMode(), (PVOID*)&FileObject,
+   Status = ObReferenceObjectByHandle(FileHandle,
+                                      0,
+                                      IoFileObjectType,
+                                      PreviousMode,
+                                      (PVOID*)&FileObject,
                                       NULL);
    if (!NT_SUCCESS(Status))
       return Status;
@@ -1370,11 +1434,9 @@ NtCancelIoFile(IN HANDLE FileHandle,
     */
 
    Thread = PsGetCurrentThread();
-   for (IrpEntry = Thread->IrpList.Flink;
-        IrpEntry != &Thread->IrpList;
-        IrpEntry = IrpEntry->Flink)
+
+   LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
    {
-      Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
       if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
       {
          IoCancelIrp(Irp);
@@ -1402,11 +1464,8 @@ NtCancelIoFile(IN HANDLE FileHandle,
        * forever.
        */
 
-      for (IrpEntry = Thread->IrpList.Flink;
-           IrpEntry != &Thread->IrpList;
-           IrpEntry = IrpEntry->Flink)
+      LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)           
       {
-         Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
          if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
          {
             OurIrpsInList = TRUE;
@@ -1498,24 +1557,40 @@ NtCreateMailslotFile(OUT PHANDLE FileHandle,
 {
     MAILSLOT_CREATE_PARAMETERS Buffer;
 
-    DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
-           "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
-           FileHandle,DesiredAccess,ObjectAttributes,
-           ObjectAttributes->ObjectName->Buffer);
+    DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
+           "ObjectAttributes 0x%p)\n",
+           FileHandle,DesiredAccess,ObjectAttributes);
+
     PAGED_CODE();
 
     /* Check for Timeout */
-    if (TimeOut)
+    if (TimeOut != NULL)
     {
-        /* Enable it */
-        Buffer.TimeoutSpecified = TRUE;
+        if (KeGetPreviousMode() != KernelMode)
+        {
+            NTSTATUS Status = STATUS_SUCCESS;
+
+            _SEH_TRY
+            {
+                Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
 
-        /* FIXME: Add SEH */
-        Buffer.ReadTimeout = *TimeOut;
+            if (!NT_SUCCESS(Status)) return Status;
+        }
+        else
+        {
+            Buffer.ReadTimeout = *TimeOut;
+        }
+
+        Buffer.TimeoutSpecified = TRUE;
     }
     else
     {
-        /* No timeout */
         Buffer.TimeoutSpecified = FALSE;
     }
 
@@ -1559,26 +1634,40 @@ NtCreateNamedPipeFile(PHANDLE FileHandle,
 {
     NAMED_PIPE_CREATE_PARAMETERS Buffer;
 
-    DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
-           "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
-            FileHandle,DesiredAccess,ObjectAttributes,
-            ObjectAttributes->ObjectName->Buffer);
+    DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
+           "ObjectAttributes 0x%p)\n",
+            FileHandle,DesiredAccess,ObjectAttributes);
+
     PAGED_CODE();
 
     /* Check for Timeout */
-    if (DefaultTimeout)
+    if (DefaultTimeout != NULL)
     {
-        /* Enable it */
-        Buffer.TimeoutSpecified = TRUE;
+        if (KeGetPreviousMode() != KernelMode)
+        {
+            NTSTATUS Status = STATUS_SUCCESS;
 
-        /* FIXME: Add SEH */
-        Buffer.DefaultTimeout = *DefaultTimeout;
+            _SEH_TRY
+            {
+                Buffer.DefaultTimeout = ProbeForReadLargeInteger(DefaultTimeout);
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+
+            if (!NT_SUCCESS(Status)) return Status;
+        }
+        else
+        {
+            Buffer.DefaultTimeout = *DefaultTimeout;
+        }
+
+        Buffer.TimeoutSpecified = TRUE;
     }
     else
-    {
-        /* No timeout */
         Buffer.TimeoutSpecified = FALSE;
-    }
 
     /* Set Settings */
     Buffer.NamedPipeType = NamedPipeType;
@@ -1692,6 +1781,8 @@ NTSTATUS
 STDCALL
 NtFlushWriteBuffer(VOID)
 {
+    PAGED_CODE();
+
     KeFlushWriteBuffer();
     return STATUS_SUCCESS;
 }
@@ -1714,20 +1805,56 @@ NtFlushBuffersFile(IN  HANDLE FileHandle,
     PFILE_OBJECT FileObject = NULL;
     PIRP Irp;
     PIO_STACK_LOCATION StackPtr;
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_SUCCESS;
     PDEVICE_OBJECT DeviceObject;
     KEVENT Event;
     BOOLEAN LocalEvent = FALSE;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
+    OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
+    KPROCESSOR_MODE PreviousMode;
+
+    PAGED_CODE();
+
+    PreviousMode = KeGetPreviousMode();
+
+    if (PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if (!NT_SUCCESS(Status)) return Status;
+    }
 
     /* Get the File Object */
     Status = ObReferenceObjectByHandle(FileHandle,
-                                       FILE_WRITE_DATA,
-                                       NULL,
+                                       0,
+                                       IoFileObjectType,
                                        PreviousMode,
                                        (PVOID*)&FileObject,
-                                       NULL);
-    if (Status != STATUS_SUCCESS) return(Status);
+                                       &ObjectHandleInfo);
+    if (!NT_SUCCESS(Status)) return(Status);
+
+    /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
+       granted. However, if this is a named pipe, make sure we don't ask for
+       FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
+       access right! */
+    if (!(FileObject->Flags & FO_NAMED_PIPE))
+        DesiredAccess |= FILE_APPEND_DATA;
+    if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
+                                  DesiredAccess))
+    {
+        ObDereferenceObject(FileObject);
+        return STATUS_ACCESS_DENIED;
+    }
 
     /* Check if this is a direct open or not */
     if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
@@ -1925,7 +2052,7 @@ NtLockFile(IN HANDLE FileHandle,
            OUT PIO_STATUS_BLOCK IoStatusBlock,
            IN PLARGE_INTEGER ByteOffset,
            IN PLARGE_INTEGER Length,
-           IN PULONG  Key,
+           IN ULONG  Key,
            IN BOOLEAN FailImmediately,
            IN BOOLEAN ExclusiveLock)
 {
@@ -1936,12 +2063,17 @@ NtLockFile(IN HANDLE FileHandle,
     PDEVICE_OBJECT DeviceObject;
     PKEVENT Event = NULL;
     BOOLEAN LocalEvent = FALSE;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
+    LARGE_INTEGER CapturedByteOffset, CapturedLength;
     NTSTATUS Status = STATUS_SUCCESS;
     OBJECT_HANDLE_INFORMATION HandleInformation;
-     
-    /* FIXME: instead of this, use SEH */
-    if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
+
+    PAGED_CODE();
+
+    PreviousMode = KeGetPreviousMode();
+
+    CapturedByteOffset.QuadPart = 0;
+    CapturedLength.QuadPart = 0;
 
     /* Get File Object */
     Status = ObReferenceObjectByHandle(FileHandle,
@@ -1952,12 +2084,41 @@ NtLockFile(IN HANDLE FileHandle,
                                        &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)))
+    if (PreviousMode != KernelMode)
     {
-        DPRINT1("Invalid access rights\n");
-        ObDereferenceObject(FileObject);
-        return STATUS_ACCESS_DENIED;
+        /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless
+           we're in KernelMode! */
+        if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+        {
+            DPRINT1("Invalid access rights\n");
+            ObDereferenceObject(FileObject);
+            return STATUS_ACCESS_DENIED;
+        }
+
+        _SEH_TRY
+        {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+            CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+            CapturedLength = ProbeForReadLargeInteger(Length);
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            return Status;
+        }
+    }
+    else
+    {
+        CapturedByteOffset = *ByteOffset;
+        CapturedLength = *Length;
     }
 
     /* Get Event Object */
@@ -2011,7 +2172,7 @@ NtLockFile(IN HANDLE FileHandle,
         ObDereferenceObject(FileObject);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
-    *LocalLength = *Length;
+    *LocalLength = CapturedLength;
     
     /* Set up the IRP */
     Irp->RequestorMode = PreviousMode;
@@ -2028,8 +2189,8 @@ NtLockFile(IN HANDLE FileHandle,
     
     /* Set Parameters */
     StackPtr->Parameters.LockControl.Length = LocalLength;
-    StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
-    StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
+    StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
+    StackPtr->Parameters.LockControl.Key = Key;
 
     /* Set Flags */
     if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
@@ -2117,21 +2278,84 @@ NtOpenFile(PHANDLE FileHandle,
 }
 
 NTSTATUS
-STDCALL
-NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
-                      OUT PFILE_BASIC_INFORMATION FileInformation)
+IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                       IN FILE_INFORMATION_CLASS FileInformationClass,
+                       OUT PVOID FileInformation)
 {
     IO_STATUS_BLOCK IoStatusBlock;
     HANDLE FileHandle;
     NTSTATUS Status;
+    KPROCESSOR_MODE AccessMode;
+    UNICODE_STRING ObjectName;
+    OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+    OBJECT_ATTRIBUTES LocalObjectAttributes;
+    ULONG BufferSize;
+    union
+    {
+        FILE_BASIC_INFORMATION BasicInformation;
+        FILE_NETWORK_OPEN_INFORMATION NetworkOpenInformation;
+    }LocalFileInformation;
+
+    if (FileInformationClass == FileBasicInformation)
+    {
+        BufferSize = sizeof(FILE_BASIC_INFORMATION);
+    }
+    else if (FileInformationClass == FileNetworkOpenInformation)
+    {
+        BufferSize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+    }
+    else
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    AccessMode = ExGetPreviousMode();
+
+    if (AccessMode != KernelMode)
+    {
+        Status = STATUS_SUCCESS;
+        _SEH_TRY
+        {
+            ProbeForWrite(FileInformation,
+                          BufferSize,
+                          sizeof(ULONG));
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        if (NT_SUCCESS(Status))
+        {
+            Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                                AccessMode,
+                                                NULL,
+                                                &ObjectCreateInfo,
+                                                &ObjectName);
+        }
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+        InitializeObjectAttributes(&LocalObjectAttributes,
+                                   &ObjectName,
+                                   ObjectCreateInfo.Attributes,
+                                   ObjectCreateInfo.RootDirectory,
+                                   ObjectCreateInfo.SecurityDescriptor);
+    }
 
     /* Open the file */
     Status = ZwOpenFile(&FileHandle,
                         SYNCHRONIZE | FILE_READ_ATTRIBUTES,
-                        ObjectAttributes,
+                        AccessMode == KernelMode ? ObjectAttributes : &LocalObjectAttributes,
                         &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        0,
                         FILE_SYNCHRONOUS_IO_NONALERT);
+    if (AccessMode != KernelMode)
+    {
+        ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+        ExFreePool(ObjectName.Buffer);
+    }
     if (!NT_SUCCESS (Status))
     {
         DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
@@ -2141,18 +2365,55 @@ NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
     /* Get file attributes */
     Status = ZwQueryInformationFile(FileHandle,
                                     &IoStatusBlock,
-                                    FileInformation,
-                                    sizeof(FILE_BASIC_INFORMATION),
-                                    FileBasicInformation);
+                                    AccessMode == KernelMode ? FileInformation : &LocalFileInformation,
+                                    BufferSize,
+                                    FileInformationClass);
     if (!NT_SUCCESS (Status))
     {
         DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
     }
-
     ZwClose(FileHandle);
+
+    if (NT_SUCCESS(Status) && AccessMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            memcpy(FileInformation, &LocalFileInformation, BufferSize);
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+    }
     return Status;
 }
 
+NTSTATUS
+STDCALL
+NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                      OUT PFILE_BASIC_INFORMATION FileInformation)
+{
+    return IopQueryAttributesFile(ObjectAttributes,
+                                  FileBasicInformation,
+                                  FileInformation);
+}
+
+static NTSTATUS NTAPI
+IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject,
+                               IN PIRP Irp,
+                               IN PVOID Context)
+{
+    ASSERT (Context);
+
+    DPRINT("IopQueryDirectoryFileCompletion was called for \'%wZ\'\n", Context);
+
+    ExFreePool(Context);
+
+    return STATUS_SUCCESS;
+}
+
+
 /*
  * @implemented
  *
@@ -2197,12 +2458,13 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
 {
     PIRP Irp;
     PDEVICE_OBJECT DeviceObject;
-    PFILE_OBJECT FileObject;
+    PFILE_OBJECT FileObject = NULL;
     PIO_STACK_LOCATION StackPtr;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status = STATUS_SUCCESS;
     BOOLEAN LocalEvent = FALSE;
     PKEVENT Event = NULL;
+    PUNICODE_STRING SearchPattern = NULL;
 
     DPRINT("NtQueryDirectoryFile()\n");
     PAGED_CODE();
@@ -2218,6 +2480,24 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
             ProbeForWrite(FileInformation,
                           Length,
                           sizeof(ULONG));
+            if (FileName)
+            {
+                UNICODE_STRING CapturedFileName;
+
+                CapturedFileName = ProbeForReadUnicodeString(FileName);
+                ProbeForRead(CapturedFileName.Buffer,
+                             CapturedFileName.MaximumLength,
+                             1);
+                SearchPattern = ExAllocatePool(NonPagedPool, CapturedFileName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING));
+                if (SearchPattern == NULL)
+                {
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    _SEH_LEAVE;
+                }
+                SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)SearchPattern + sizeof(UNICODE_STRING));
+                SearchPattern->MaximumLength = CapturedFileName.Length + sizeof(WCHAR);
+                RtlCopyUnicodeString(SearchPattern, &CapturedFileName);
+            }
         }
         _SEH_HANDLE
         {
@@ -2225,7 +2505,10 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
         }
         _SEH_END;
 
-        if(!NT_SUCCESS(Status)) return Status;
+        if(!NT_SUCCESS(Status)) 
+        {
+            goto Cleanup;
+        }
     }
 
     /* Get File Object */
@@ -2235,7 +2518,10 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
                                        PreviousMode,
                                        (PVOID *)&FileObject,
                                        NULL);
-    if (Status != STATUS_SUCCESS) return(Status);
+    if (!NT_SUCCESS(Status))
+    {
+       goto Cleanup;
+    }
 
     /* Get Event Object */
     if (PEvent)
@@ -2246,7 +2532,11 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
                                            PreviousMode,
                                            (PVOID *)&Event,
                                            NULL);
-        if (Status != STATUS_SUCCESS) return(Status);
+        if (!NT_SUCCESS(Status)) 
+        {
+            goto Cleanup;
+        }
+
         KeClearEvent(Event);
     }
 
@@ -2274,8 +2564,8 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
     /* Allocate the IRP */
     if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
     {
-        ObDereferenceObject(FileObject);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Cleanup;
     }
 
     /* Set up the IRP */
@@ -2296,13 +2586,23 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
 
     /* Set Parameters */
     StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
-    StackPtr->Parameters.QueryDirectory.FileName = FileName;
+    StackPtr->Parameters.QueryDirectory.FileName = SearchPattern ? SearchPattern : 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;
 
+    if (SearchPattern)
+    {
+        IoSetCompletionRoutine(Irp,
+                               IopQueryDirectoryFileCompletion,
+                              SearchPattern,
+                              TRUE,
+                              TRUE,
+                              TRUE);
+    }
+
     /* Call the Driver */
     Status = IoCallDriver(DeviceObject, Irp);
     if (Status == STATUS_PENDING)
@@ -2318,6 +2618,23 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
         }
     }
 
+
+    return Status;
+
+Cleanup:
+    if (FileObject != NULL)
+    {
+        ObDereferenceObject(FileObject);
+    }
+    if (Event != NULL)
+    {
+        ObDereferenceObject(Event);
+    }
+    if (SearchPattern != NULL)
+    {
+        ExFreePool(SearchPattern);
+    }
+
     /* Return the Status */
     return Status;
 }
@@ -2345,36 +2662,9 @@ STDCALL
 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
 {
-    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))
-    {
-        DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
-        return 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);
-    }
-
-    ZwClose (FileHandle);
-    return Status;
+  return IopQueryAttributesFile(ObjectAttributes,
+                                FileNetworkOpenInformation,
+                                FileInformation);
 }
 
 /*
@@ -2401,7 +2691,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);
 
@@ -2428,11 +2718,6 @@ NtQueryInformationFile(HANDLE FileHandle,
                 Failed = TRUE;
             break;
 
-        case FileAlignmentInformation:
-            if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
-                Failed = TRUE;
-            break;
-
         default:
             break;
     }
@@ -2444,7 +2729,31 @@ NtQueryInformationFile(HANDLE FileHandle,
         return STATUS_ACCESS_DENIED;
     }
 
-    DPRINT("FileObject %x\n", FileObject);
+    if (FileInformationClass == FilePositionInformation)
+    {
+       if (Length < sizeof(FILE_POSITION_INFORMATION))
+       {
+          Status = STATUS_BUFFER_OVERFLOW;
+       }
+       else
+       {
+          _SEH_TRY
+          {
+             ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset = FileObject->CurrentByteOffset;
+             IoStatusBlock->Information = sizeof(FILE_POSITION_INFORMATION);
+             Status = IoStatusBlock->Status = STATUS_SUCCESS;
+          }
+          _SEH_HANDLE
+          {
+             Status = _SEH_GetExceptionCode();
+          }
+          _SEH_END;
+       }
+       ObDereferenceObject(FileObject);
+       return Status;
+    }
+
+    DPRINT("FileObject 0x%p\n", FileObject);
 
     /* Check if this is a direct open or not */
     if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
@@ -2456,6 +2765,30 @@ NtQueryInformationFile(HANDLE FileHandle,
         DeviceObject = IoGetRelatedDeviceObject(FileObject);
     }
 
+    if (FileInformationClass == FileAlignmentInformation)
+    {
+       if (Length < sizeof(FILE_ALIGNMENT_INFORMATION))
+       {
+          Status = STATUS_BUFFER_OVERFLOW;
+       }
+       else
+       {
+          _SEH_TRY
+          {
+             ((PFILE_ALIGNMENT_INFORMATION)FileInformation)->AlignmentRequirement = DeviceObject->AlignmentRequirement;
+             IoStatusBlock->Information = sizeof(FILE_ALIGNMENT_INFORMATION);
+             Status = IoStatusBlock->Status = STATUS_SUCCESS;
+          }
+          _SEH_HANDLE
+          {
+             Status = _SEH_GetExceptionCode();
+          }
+          _SEH_END;
+       }
+       ObDereferenceObject(FileObject);
+       return Status;
+    }
+
     /* Check if we should use Sync IO or not */
     if (FileObject->Flags & FO_SYNCHRONOUS_IO)
     {
@@ -2575,7 +2908,7 @@ NtReadFile(IN HANDLE FileHandle,
            OUT PIO_STATUS_BLOCK IoStatusBlock,
            OUT PVOID Buffer,
            IN ULONG Length,
-           IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
+           IN PLARGE_INTEGER ByteOffset OPTIONAL,
            IN PULONG Key OPTIONAL)
 {
     NTSTATUS Status = STATUS_SUCCESS;
@@ -2583,14 +2916,19 @@ NtReadFile(IN HANDLE FileHandle,
     PIRP Irp = NULL;
     PDEVICE_OBJECT DeviceObject;
     PIO_STACK_LOCATION StackPtr;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
     BOOLEAN LocalEvent = FALSE;
     PKEVENT EventObject = NULL;
+    LARGE_INTEGER CapturedByteOffset;
 
-    DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
-           "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
+    DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+           "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
             IoStatusBlock);
+
     PAGED_CODE();
+    
+    PreviousMode = KeGetPreviousMode();
+    CapturedByteOffset.QuadPart = 0;
 
     /* Validate User-Mode Buffers */
     if(PreviousMode != KernelMode)
@@ -2600,11 +2938,14 @@ NtReadFile(IN HANDLE FileHandle,
             ProbeForWrite(IoStatusBlock,
                           sizeof(IO_STATUS_BLOCK),
                           sizeof(ULONG));
-            #if 0
             ProbeForWrite(Buffer,
                           Length,
-                          sizeof(ULONG));
-            #endif
+                          1);
+            if (ByteOffset != NULL)
+            {
+                CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+            }
+            /* FIXME - probe other pointers and capture information */
         }
         _SEH_HANDLE
         {
@@ -2614,6 +2955,13 @@ NtReadFile(IN HANDLE FileHandle,
 
         if(!NT_SUCCESS(Status)) return Status;
     }
+    else
+    {
+        if (ByteOffset != NULL)
+        {
+            CapturedByteOffset = *ByteOffset;
+        }
+    }
 
     /* Get File Object */
     Status = ObReferenceObjectByHandle(FileHandle,
@@ -2625,9 +2973,9 @@ NtReadFile(IN HANDLE FileHandle,
     if (!NT_SUCCESS(Status)) return Status;
 
     /* Check the Byte Offset */
-    if (!ByteOffset ||
-        (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
-         ByteOffset->u.HighPart == 0xffffffff))
+    if (ByteOffset == NULL ||
+        (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+         CapturedByteOffset.u.HighPart == -1))
     {
         /* a valid ByteOffset is required if asynch. op. */
         if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
@@ -2638,7 +2986,7 @@ NtReadFile(IN HANDLE FileHandle,
         }
 
         /* Use the Current Byte OFfset */
-        ByteOffset = &FileObject->CurrentByteOffset;
+        CapturedByteOffset = FileObject->CurrentByteOffset;
     }
 
     /* Check for event */
@@ -2687,7 +3035,7 @@ NtReadFile(IN HANDLE FileHandle,
                                            DeviceObject,
                                            Buffer,
                                            Length,
-                                           ByteOffset,
+                                           &CapturedByteOffset,
                                            EventObject,
                                            IoStatusBlock);
         if (Irp == NULL)
@@ -2809,13 +3157,45 @@ NtSetInformationFile(HANDLE FileHandle,
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     BOOLEAN Failed = FALSE;
 
-    ASSERT(IoStatusBlock != NULL);
-    ASSERT(FileInformation != NULL);
-
-    DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
+    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
+    {
+        ASSERT(IoStatusBlock != NULL);
+        ASSERT(FileInformation != NULL);
+    }
+
     /* Get the file object from the file handle */
     Status = ObReferenceObjectByHandle(FileHandle,
                                        0,
@@ -2860,7 +3240,31 @@ NtSetInformationFile(HANDLE FileHandle,
         return STATUS_ACCESS_DENIED;
     }
 
-    DPRINT("FileObject %x\n", FileObject);
+    DPRINT("FileObject 0x%p\n", FileObject);
+
+    if (FileInformationClass == FilePositionInformation)
+    {
+       if (Length < sizeof(FILE_POSITION_INFORMATION))
+       {
+          Status = STATUS_BUFFER_OVERFLOW;
+       }
+       else
+       {
+          _SEH_TRY
+          {
+             FileObject->CurrentByteOffset = ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset;
+             IoStatusBlock->Information = 0;
+             Status = IoStatusBlock->Status = STATUS_SUCCESS;
+          }
+          _SEH_HANDLE
+          {
+             Status = _SEH_GetExceptionCode();
+          }
+          _SEH_END;
+       }
+       ObDereferenceObject(FileObject);
+       return Status;
+    }
 
     /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
     /* Handle IO Completion Port quickly */
@@ -2869,34 +3273,57 @@ NtSetInformationFile(HANDLE FileHandle,
         PVOID Queue;
         PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
         PIO_COMPLETION_CONTEXT Context;
-
-        if (Length < sizeof(FILE_COMPLETION_INFORMATION))
+        
+        if (FileObject->Flags & FO_SYNCHRONOUS_IO || FileObject->CompletionContext != NULL)
         {
-            Status = STATUS_INFO_LENGTH_MISMATCH;
+            Status = STATUS_INVALID_PARAMETER;
         }
         else
         {
-            /* Reference the Port */
-            Status = ObReferenceObjectByHandle(CompletionInfo->Port,
-                                               IO_COMPLETION_MODIFY_STATE,
-                                               IoCompletionType,
-                                               PreviousMode,
-                                               (PVOID*)&Queue,
-                                               NULL);
-            if (NT_SUCCESS(Status))
+            if (Length < sizeof(FILE_COMPLETION_INFORMATION))
             {
-                /* 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);
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            else
+            {
+                /* Reference the Port */
+                Status = ObReferenceObjectByHandle(CompletionInfo->Port, /* FIXME - protect with SEH! */
+                                                   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'));
+
+                    if (Context != NULL)
+                    {
+                        /* Set the Data */
+                        Context->Key = CompletionInfo->Key; /* FIXME - protect with SEH! */
+                        Context->Port = Queue;
+                        
+                        if (InterlockedCompareExchangePointer(&FileObject->CompletionContext,
+                                                              Context,
+                                                              NULL) != NULL)
+                        {
+                            /* someone else set the completion port in the
+                               meanwhile, fail */
+                            ExFreePool(Context);
+                            ObDereferenceObject(Queue);
+                            Status = STATUS_INVALID_PARAMETER;
+                        }
+                    }
+                    else
+                    {
+                        /* Dereference the Port now */
+                        ObDereferenceObject(Queue);
+                        Status = STATUS_INSUFFICIENT_RESOURCES;
+                    }
+                }
             }
         }
 
@@ -2940,13 +3367,43 @@ NtSetInformationFile(HANDLE FileHandle,
                                                                   Length,
                                                                   TAG_SYSB)))
     {
-        IoFreeIrp(Irp);
-        ObDereferenceObject(FileObject);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failfreeirp;
     }
 
     /* Copy the data inside */
-    MmSafeCopyFromUser(Irp->AssociatedIrp.SystemBuffer, FileInformation, Length);
+    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;
@@ -2977,7 +3434,15 @@ NtSetInformationFile(HANDLE FileHandle,
                                   PreviousMode,
                                   FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
-            Status = IoStatusBlock->Status;
+            _SEH_TRY
+            {
+                Status = IoStatusBlock->Status;
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
         }
         else
         {
@@ -2986,7 +3451,15 @@ NtSetInformationFile(HANDLE FileHandle,
                                   PreviousMode,
                                   FileObject->Flags & FO_ALERTABLE_IO,
                                   NULL);
-            Status = FileObject->FinalStatus;
+            _SEH_TRY
+            {
+                Status = FileObject->FinalStatus;
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
         }
     }
 
@@ -3001,7 +3474,7 @@ NTSTATUS
 STDCALL
 NtSetQuotaInformationFile(HANDLE FileHandle,
                           PIO_STATUS_BLOCK IoStatusBlock,
-                          PFILE_QUOTA_INFORMATION Buffer,
+                          PVOID Buffer,
                           ULONG BufferLength)
 {
     UNIMPLEMENTED;
@@ -3017,7 +3490,7 @@ NtUnlockFile(IN  HANDLE FileHandle,
              OUT PIO_STATUS_BLOCK IoStatusBlock,
              IN  PLARGE_INTEGER ByteOffset,
              IN  PLARGE_INTEGER Length,
-             OUT PULONG Key OPTIONAL)
+             IN  ULONG Key OPTIONAL)
 {
     PFILE_OBJECT FileObject = NULL;
     PLARGE_INTEGER LocalLength = NULL;
@@ -3026,12 +3499,17 @@ NtUnlockFile(IN  HANDLE FileHandle,
     PDEVICE_OBJECT DeviceObject;
     KEVENT Event;
     BOOLEAN LocalEvent = FALSE;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
     NTSTATUS Status = STATUS_SUCCESS;
+    LARGE_INTEGER CapturedByteOffset, CapturedLength;
     OBJECT_HANDLE_INFORMATION HandleInformation;
-     
-    /* FIXME: instead of this, use SEH */
-    if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
+
+    PAGED_CODE();
+
+    PreviousMode = KeGetPreviousMode();
+
+    CapturedByteOffset.QuadPart = 0;
+    CapturedLength.QuadPart = 0;
 
     /* Get File Object */
     Status = ObReferenceObjectByHandle(FileHandle,
@@ -3042,12 +3520,41 @@ NtUnlockFile(IN  HANDLE FileHandle,
                                        &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)))
+    if (PreviousMode != KernelMode)
     {
-        DPRINT1("Invalid access rights\n");
-        ObDereferenceObject(FileObject);
-        return STATUS_ACCESS_DENIED;
+        /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
+           in KernelMode! */
+        if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
+        {
+            DPRINT1("Invalid access rights\n");
+            ObDereferenceObject(FileObject);
+            return STATUS_ACCESS_DENIED;
+        }
+
+        _SEH_TRY
+        {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+            CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+            CapturedLength = ProbeForReadLargeInteger(Length);
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            ObDereferenceObject(FileObject);
+            return Status;
+        }
+    }
+    else
+    {
+        CapturedByteOffset = *ByteOffset;
+        CapturedLength = *Length;
     }
 
     /* Check if this is a direct open or not */
@@ -3090,7 +3597,7 @@ NtUnlockFile(IN  HANDLE FileHandle,
         ObDereferenceObject(FileObject);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
-    *LocalLength = *Length;
+    *LocalLength = CapturedLength;
     
     /* Set up the IRP */
     Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
@@ -3108,8 +3615,8 @@ NtUnlockFile(IN  HANDLE FileHandle,
     
     /* Set Parameters */
     StackPtr->Parameters.LockControl.Length = LocalLength;
-    StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
-    StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
+    StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
+    StackPtr->Parameters.LockControl.Key = Key;
 
     /* Call the Driver */
     Status = IoCallDriver(DeviceObject, Irp);
@@ -3165,34 +3672,49 @@ NtWriteFile (IN HANDLE FileHandle,
              IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
              IN PULONG Key OPTIONAL)
 {
-    OBJECT_HANDLE_INFORMATION HandleInformation;
+    OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
     NTSTATUS Status = STATUS_SUCCESS;
     PFILE_OBJECT FileObject;
     PIRP Irp = NULL;
     PDEVICE_OBJECT DeviceObject;
     PIO_STACK_LOCATION StackPtr;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
     BOOLEAN LocalEvent = FALSE;
     PKEVENT EventObject = NULL;
+    LARGE_INTEGER CapturedByteOffset;
+    ULONG CapturedKey = 0;
+    ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
 
-    DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
-            "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
+    DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
+            "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
             IoStatusBlock);
 
+    PAGED_CODE();
+
+    PreviousMode = KeGetPreviousMode();
+    CapturedByteOffset.QuadPart = 0;
+
     /* Validate User-Mode Buffers */
     if(PreviousMode != KernelMode)
     {
         _SEH_TRY
         {
-            #if 0
             ProbeForWrite(IoStatusBlock,
                           sizeof(IO_STATUS_BLOCK),
                           sizeof(ULONG));
 
             ProbeForRead(Buffer,
                          Length,
-                         sizeof(ULONG));
-            #endif
+                         1);
+            if (ByteOffset != NULL)
+            {
+                CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
+            }
+
+            if (Key != NULL)
+            {
+                CapturedKey = ProbeForReadUlong(Key);
+            }
         }
         _SEH_HANDLE
         {
@@ -3202,6 +3724,17 @@ NtWriteFile (IN HANDLE FileHandle,
 
         if(!NT_SUCCESS(Status)) return Status;
     }
+    else
+    {
+        if (ByteOffset != NULL)
+        {
+            CapturedByteOffset = *ByteOffset;
+        }
+        if (Key != NULL)
+        {
+            CapturedKey = *Key;
+        }
+    }
 
     /* Get File Object */
     Status = ObReferenceObjectByHandle(FileHandle,
@@ -3209,24 +3742,29 @@ NtWriteFile (IN HANDLE FileHandle,
                                        IoFileObjectType,
                                        PreviousMode,
                                        (PVOID*)&FileObject,
-                                       &HandleInformation);
+                                       &ObjectHandleInfo);
     if (!NT_SUCCESS(Status)) return Status;
 
-    /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
-    if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
+    /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
+       granted. However, if this is a named pipe, make sure we don't ask for
+       FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
+       access right! */
+    if (!(FileObject->Flags & FO_NAMED_PIPE))
+        DesiredAccess |= FILE_APPEND_DATA;
+    if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
+                                  DesiredAccess))
     {
-        DPRINT1("Invalid access rights\n");
         ObDereferenceObject(FileObject);
         return STATUS_ACCESS_DENIED;
     }
 
     /* Check if we got write Access */
-    if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
+    if (ObjectHandleInfo.GrantedAccess & FILE_WRITE_DATA)
     {
         /* Check the Byte Offset */
-        if (!ByteOffset ||
-            (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
-             ByteOffset->u.HighPart == 0xffffffff))
+        if (ByteOffset == NULL ||
+            (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
+             CapturedByteOffset.u.HighPart == -1))
         {
             /* a valid ByteOffset is required if asynch. op. */
             if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
@@ -3237,10 +3775,11 @@ NtWriteFile (IN HANDLE FileHandle,
             }
 
             /* Use the Current Byte OFfset */
-            ByteOffset = &FileObject->CurrentByteOffset;
+            CapturedByteOffset = FileObject->CurrentByteOffset;
         }
     }
-    else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
+    else if ((ObjectHandleInfo.GrantedAccess & FILE_APPEND_DATA) &&
+             !(FileObject->Flags & FO_NAMED_PIPE))
     {
         /* a valid ByteOffset is required if asynch. op. */
         if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
@@ -3251,8 +3790,8 @@ NtWriteFile (IN HANDLE FileHandle,
         }
 
         /* Give the drivers somethign to understand */
-        ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
-        ByteOffset->u.HighPart = 0xffffffff;
+        CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
+        CapturedByteOffset.u.HighPart = 0xffffffff;
     }
 
     /* Check if we got an event */
@@ -3301,7 +3840,7 @@ NtWriteFile (IN HANDLE FileHandle,
                                            DeviceObject,
                                            Buffer,
                                            Length,
-                                           ByteOffset,
+                                           &CapturedByteOffset,
                                            EventObject,
                                            IoStatusBlock);
         if (Irp == NULL)
@@ -3342,7 +3881,7 @@ NtWriteFile (IN HANDLE FileHandle,
     /* Setup Stack Data */
     StackPtr = IoGetNextIrpStackLocation(Irp);
     StackPtr->FileObject = FileObject;
-    StackPtr->Parameters.Write.Key = Key ? *Key : 0;
+    StackPtr->Parameters.Write.Key = CapturedKey;
     if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
 
     /* Call the Driver */