[ros-diffs] [ion] 22790: - NtWriteFile: - Allow async i/o access on mailslots, without a byte offset. - Fix sync semantics just like for the other functions until now. - Fix a potential object leak in a failure case. - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves. - Use deferred I/O as an optimization.

ion at svn.reactos.org ion at svn.reactos.org
Mon Jul 3 03:17:14 CEST 2006


Author: ion
Date: Mon Jul  3 05:17:14 2006
New Revision: 22790

URL: http://svn.reactos.org/svn/reactos?rev=22790&view=rev
Log:
- NtWriteFile:
  - Allow async i/o access on mailslots, without a byte offset.
  - Fix sync semantics just like for the other functions until now.
  - Fix a potential object leak in  a failure case.
  - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves.
  - Use deferred I/O as an optimization.

Modified:
    trunk/reactos/ntoskrnl/io/iomgr/iofunc.c

Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c?rev=22790&r1=22789&r2=22790&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul  3 05:17:14 2006
@@ -26,9 +26,9 @@
 // TODO:
 //  - Lock/Unlock <= DONE
 //  - Query/Set Volume Info <= DONE
-//  - Read/Write file
-//  - QuerySet/ File Info
-//  - NtQueryDirectoryFile
+//  - Read/Write file <= DONE
+//  - Query/Set File Info
+//  - QueryDirectoryFile
 //
 ///
 
@@ -2450,20 +2450,19 @@
             IN PLARGE_INTEGER ByteOffset OPTIONAL,
             IN PULONG Key OPTIONAL)
 {
-    OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
     NTSTATUS Status = STATUS_SUCCESS;
     PFILE_OBJECT FileObject;
-    PIRP Irp = NULL;
+    PIRP Irp;
     PDEVICE_OBJECT DeviceObject;
     PIO_STACK_LOCATION StackPtr;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    BOOLEAN Synchronous = FALSE;
     PKEVENT EventObject = NULL;
     LARGE_INTEGER CapturedByteOffset;
     ULONG CapturedKey = 0;
-    ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
+    BOOLEAN Synchronous = FALSE;
+    PMDL Mdl;
+    OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
     PAGED_CODE();
-
     CapturedByteOffset.QuadPart = 0;
 
     /* Get File Object */
@@ -2475,79 +2474,71 @@
                                        &ObjectHandleInfo);
     if (!NT_SUCCESS(Status)) return Status;
 
-    /* If this is a named pipe, make sure we don't ask for FILE_APPEND_DATA as it
-       overlaps with the FILE_CREATE_PIPE_INSTANCE access right! */
-    if (!(FileObject->Flags & FO_NAMED_PIPE))
-        DesiredAccess |= FILE_APPEND_DATA;
-
     /* Validate User-Mode Buffers */
-    if (PreviousMode != KernelMode)
-    {
-        /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
-           granted. */
-        if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
-                                      DesiredAccess))
-        {
-            ObDereferenceObject(FileObject);
-            return STATUS_ACCESS_DENIED;
-        }
-
+    if(PreviousMode != KernelMode)
+    {
         _SEH_TRY
         {
+            /*
+             * Check if the handle has either FILE_WRITE_DATA or
+             * FILE_APPEND_DATA granted. However, if this is a named pipe,
+             * make sure we don't ask for FILE_APPEND_DATA as it interferes
+             * with the FILE_CREATE_PIPE_INSTANCE access right!
+             */
+            if (!(ObjectHandleInfo.GrantedAccess &
+                 ((!(FileObject->Flags & FO_NAMED_PIPE) ?
+                   FILE_APPEND_DATA : 0) | FILE_WRITE_DATA)))
+            {
+                /* We failed */
+                ObDereferenceObject(FileObject);
+                return STATUS_ACCESS_DENIED;
+            }
+
+            /* Probe the status block */
             ProbeForWrite(IoStatusBlock,
                           sizeof(IO_STATUS_BLOCK),
                           sizeof(ULONG));
+
+            /* Probe the read buffer */
             ProbeForRead(Buffer, Length, 1);
 
+            /* Check if we got a byte offset */
             if (ByteOffset)
             {
+                /* Capture and probe it */
                 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
             }
 
+            /* Capture and probe the key */
             if (Key) CapturedKey = ProbeForReadUlong(Key);
         }
         _SEH_HANDLE
         {
+            /* Get the exception code */
             Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
 
-        if(!NT_SUCCESS(Status)) return Status;
+        /* Check for probe failure */
+        if (!NT_SUCCESS(Status)) return Status;
     }
     else
     {
+        /* Kernel mode: capture directly */
         if (ByteOffset) CapturedByteOffset = *ByteOffset;
         if (Key) CapturedKey = *Key;
     }
 
-    /* check if this is an append operation */
-    if ((ObjectHandleInfo.GrantedAccess & DesiredAccess) == FILE_APPEND_DATA)
+    /* Check if this is an append operation */
+    if ((ObjectHandleInfo.GrantedAccess &
+        (FILE_APPEND_DATA | FILE_WRITE_DATA)) == FILE_APPEND_DATA)
     {
         /* Give the drivers something to understand */
         CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
         CapturedByteOffset.u.HighPart = -1;
     }
 
-    /* Check if we should use Sync IO or not */
-    if (FileObject->Flags & FO_SYNCHRONOUS_IO)
-    {
-        if (ByteOffset == NULL ||
-            (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
-             CapturedByteOffset.u.HighPart == -1))
-        {
-            /* Use the Current Byte OFfset */
-            CapturedByteOffset = FileObject->CurrentByteOffset;
-        }
-
-        Synchronous = TRUE;
-    }
-    else if (ByteOffset == NULL && !(FileObject->Flags & FO_NAMED_PIPE))
-    {
-        ObDereferenceObject(FileObject);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Check if we got an event */
+    /* Check for event */
     if (Event)
     {
         /* Reference it */
@@ -2559,89 +2550,133 @@
                                            NULL);
         if (!NT_SUCCESS(Status))
         {
+            /* Fail */
             ObDereferenceObject(FileObject);
             return Status;
         }
+
+        /* Otherwise reset the event */
         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)
+    {
+        /* Lock the file object */
+        IopLockFileObject(FileObject);
+
+        /* Check if we don't have a byte offset avilable */
+        if (!(ByteOffset) ||
+            ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
+             (CapturedByteOffset.u.HighPart == -1)))
+        {
+            /* Use the Current Byte Offset instead */
+            CapturedByteOffset = FileObject->CurrentByteOffset;
+        }
+
+        /* Rememer we are sync */
+        Synchronous = TRUE;
+    }
+    else if (!(ByteOffset) &&
+             !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT)))
+    {
+        /* Otherwise, this was async I/O without a byte offset, so fail */
+        if (EventObject) ObDereferenceObject(EventObject);
+        ObDereferenceObject(FileObject);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the device object */
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
+
+    /* Clear the File Object's event */
     KeClearEvent(&FileObject->Event);
 
-    /* Build the IRP */
-    _SEH_TRY
-    {
-        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
-                                           DeviceObject,
-                                           Buffer,
-                                           Length,
-                                           &CapturedByteOffset,
-                                           EventObject,
-                                           IoStatusBlock);
-        if (Irp == NULL)
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-        }
-    }
-    _SEH_HANDLE
-    {
-        Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
-
-    /* Cleanup on failure */
-    if (!NT_SUCCESS(Status))
-    {
-        if (Event) ObDereferenceObject(&EventObject);
-        ObDereferenceObject(FileObject);
-        return Status;
-    }
-
-   /* Set up IRP Data */
+    /* Allocate the IRP */
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+    if (!Irp) return IopCleanupFailedIrp(FileObject, NULL);
+
+    /* Set the IRP */
     Irp->Tail.Overlay.OriginalFileObject = FileObject;
-    Irp->RequestorMode = PreviousMode;
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    Irp->RequestorMode = KernelMode;
     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.
-     */     
+    Irp->UserIosb = IoStatusBlock;
+    Irp->UserEvent = EventObject;
+    Irp->PendingReturned = FALSE;
+    Irp->Cancel = FALSE;
+    Irp->CancelRoutine = NULL;
+    Irp->AssociatedIrp.SystemBuffer = NULL;
+    Irp->MdlAddress = NULL;
+
+    /* Set the Stack Data */
+    StackPtr = IoGetNextIrpStackLocation(Irp);
+    StackPtr->MajorFunction = IRP_MJ_WRITE;
+    StackPtr->FileObject = FileObject;
+    StackPtr->Flags = FileObject->Flags & FO_WRITE_THROUGH ?
+                      SL_WRITE_THROUGH : 0;
+    StackPtr->Parameters.Write.Key = CapturedKey;
+    StackPtr->Parameters.Write.Length = Length;
+    StackPtr->Parameters.Write.ByteOffset = CapturedByteOffset;
+
+    /* Check if this is buffered I/O */
+    if (DeviceObject->Flags & DO_BUFFERED_IO)
+    {
+        /* Check if we have a buffer length */
+        if (Length)
+        {
+            /* Allocate a buffer */
+            Irp->AssociatedIrp.SystemBuffer =
+                ExAllocatePoolWithTag(NonPagedPool,
+                                      Length,
+                                      TAG_SYSB);
+
+            /* Copy the buffer and set flags */
+            RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length);
+            Irp->Flags = (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER);
+        }
+        else
+        {
+            /* Not writing anything */
+            Irp->Flags = IRP_BUFFERED_IO;
+        }
+    }
+    else if (DeviceObject->Flags & DO_DIRECT_IO)
+    {
+        /* Check if we have a buffer length */
+        if (Length)
+        {
+            /* Allocate an MDL */
+            Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp);
+            MmProbeAndLockPages(Mdl, PreviousMode, IoReadAccess);
+        }
+
+        /* No allocation flags */
+        Irp->Flags = 0;
+    }
+    else
+    {
+        /* No allocation flags, and use the buffer directly */
+        Irp->Flags = 0;
+        Irp->UserBuffer = Buffer;
+    }
+
+    /* Now set the deferred read flags */
+    Irp->Flags |= (IRP_WRITE_OPERATION | IRP_DEFER_IO_COMPLETION);
+#if 0
+    /* FIXME: VFAT SUCKS */
     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 = CapturedKey;
-    if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
-
-    /* Call the Driver */
-    Status = IoCallDriver(DeviceObject, Irp);
-    if (Status == STATUS_PENDING)
-    {
-        if (Synchronous)
-        {
-            KeWaitForSingleObject(&FileObject->Event,
-                                  Executive,
-                                  PreviousMode,
-                                  FileObject->Flags & FO_ALERTABLE_IO,
-                                  NULL);
-            Status = FileObject->FinalStatus;
-        }
-    }
-
-    /* Return the Status */
-    return Status;
+#endif
+
+    /* Perform the call */
+    return IopPerformSynchronousRequest(DeviceObject,
+                                        Irp,
+                                        FileObject,
+                                        TRUE,
+                                        PreviousMode,
+                                        Synchronous,
+                                        IopWriteTransfer);
 }
 
 NTSTATUS




More information about the Ros-diffs mailing list