- Same changes for IoSertInformation: Lock the FO, queue the IRP, support alerted...
authorAlex Ionescu <aionescu@gmail.com>
Sun, 2 Jul 2006 16:41:49 +0000 (16:41 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 2 Jul 2006 16:41:49 +0000 (16:41 +0000)
svn path=/trunk/; revision=22771

reactos/ntoskrnl/io/iomgr/iofunc.c

index 6274683..b360147 100644 (file)
@@ -635,59 +635,100 @@ IoSetInformation(IN PFILE_OBJECT FileObject,
     PIRP Irp;\r
     PDEVICE_OBJECT DeviceObject;\r
     PIO_STACK_LOCATION StackPtr;\r
+    BOOLEAN LocalEvent = FALSE;\r
+    KEVENT Event;\r
     NTSTATUS Status;\r
+    PAGED_CODE();\r
 \r
-    if (FileInformationClass == FileCompletionInformation)\r
-    {\r
-        return STATUS_NOT_IMPLEMENTED;\r
-    }\r
-\r
-    Status = ObReferenceObjectByPointer(FileObject,\r
-                                        0, /* FIXME - depends on the information class */\r
-                                        IoFileObjectType,\r
-                                        KernelMode);\r
-    if (!NT_SUCCESS(Status)) return(Status);\r
-\r
+    /* Reference the object */\r
+    ObReferenceObject(FileObject);\r
 \r
-    DeviceObject = FileObject->DeviceObject;\r
+    /* Check if this is a file that was opened for Synch I/O */\r
+    if (FileObject->Flags & FO_SYNCHRONOUS_IO)\r
+    {\r
+        /* Lock it */\r
+        IopLockFileObject(FileObject);\r
 \r
-    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);\r
-    if (!Irp)\r
+        /* Use File Object event */\r
+        KeClearEvent(&FileObject->Event);\r
+    }\r
+    else\r
     {\r
-        ObDereferenceObject(FileObject);\r
-        return STATUS_INSUFFICIENT_RESOURCES;\r
+        /* Use local event */\r
+        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);\r
+        LocalEvent = TRUE;\r
     }\r
 \r
-    /* Trigger FileObject/Event dereferencing */\r
+    /* Get the Device Object */\r
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);\r
+\r
+    /* Allocate the IRP */\r
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);\r
+    if (!Irp) return IopCleanupFailedIrp(FileObject, NULL);\r
+\r
+    /* Set the IRP */\r
     Irp->Tail.Overlay.OriginalFileObject = FileObject;\r
     Irp->RequestorMode = KernelMode;\r
-    Irp->AssociatedIrp.SystemBuffer = FileInformation;\r
+    Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;\r
     Irp->UserIosb = &IoStatusBlock;\r
-    Irp->UserEvent = &FileObject->Event;\r
+    Irp->UserEvent = (LocalEvent) ? &Event : NULL;\r
+    Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;\r
+    Irp->Flags |= IRP_BUFFERED_IO;\r
+    Irp->AssociatedIrp.SystemBuffer = FileInformation;\r
     Irp->Tail.Overlay.Thread = PsGetCurrentThread();\r
-    KeResetEvent( &FileObject->Event );\r
 \r
+    /* Set the Stack Data */\r
     StackPtr = IoGetNextIrpStackLocation(Irp);\r
     StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;\r
-    StackPtr->MinorFunction = 0;\r
-    StackPtr->Flags = 0;\r
-    StackPtr->Control = 0;\r
-    StackPtr->DeviceObject = DeviceObject;\r
     StackPtr->FileObject = FileObject;\r
+\r
+    /* Set Parameters */\r
     StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;\r
     StackPtr->Parameters.SetFile.Length = Length;\r
 \r
+    /* Queue the IRP */\r
+    IopQueueIrpToThread(Irp);\r
+\r
+    /* Call the Driver */\r
     Status = IoCallDriver(FileObject->DeviceObject, Irp);\r
-    if (Status==STATUS_PENDING)\r
+\r
+    /* Check if this was synch I/O */\r
+    if (!LocalEvent)\r
     {\r
-        KeWaitForSingleObject(&FileObject->Event,\r
+        /* Check if the requet is pending */\r
+        if (Status == STATUS_PENDING)\r
+        {\r
+            /* Wait on the file object */\r
+            Status = KeWaitForSingleObject(&FileObject->Event,\r
+                                           Executive,\r
+                                           KernelMode,\r
+                                           FileObject->Flags & FO_ALERTABLE_IO,\r
+                                           NULL);\r
+            if (Status == STATUS_ALERTED)\r
+            {\r
+                /* Abort the operation */\r
+                IopAbortInterruptedIrp(&FileObject->Event, Irp);\r
+            }\r
+\r
+            /* Get the final status */\r
+            Status = FileObject->FinalStatus;\r
+        }\r
+\r
+        /* Release the file lock */\r
+        IopUnlockFileObject(FileObject);\r
+    }\r
+    else if (Status == STATUS_PENDING)\r
+    {\r
+        /* Wait on the local event and get the final status */\r
+        KeWaitForSingleObject(&Event,\r
                               Executive,\r
                               KernelMode,\r
-                              FileObject->Flags & FO_ALERTABLE_IO,\r
+                              FALSE,\r
                               NULL);\r
         Status = IoStatusBlock.Status;\r
     }\r
 \r
+    /* Return the status */\r
     return Status;\r
 }\r
 \r