- Guard the copying to the IOSB.  
- Do the main processing on success or if previous STATUS_PENDING was returned. 
  Do not use some of the IRP and FO flags at this point.   
- Set all results before signaling the events.  
- Signal the FO event previous the user event.    
- Made the code a little bit shorter.
Modified: trunk/reactos/ntoskrnl/io/irp.c

Modified: trunk/reactos/ntoskrnl/io/irp.c
--- trunk/reactos/ntoskrnl/io/irp.c	2005-05-05 09:59:38 UTC (rev 14987)
+++ trunk/reactos/ntoskrnl/io/irp.c	2005-05-05 10:59:34 UTC (rev 14988)
@@ -1222,6 +1222,8 @@
     PFILE_OBJECT FileObject;
     PIRP Irp;
     PMDL Mdl, NextMdl;
+    PKEVENT UserEvent;
+    BOOLEAN SyncIrp;
 
     if (Apc) DPRINT("IoSecondStageCompletition with APC: %x\n", Apc);
    
@@ -1230,6 +1232,9 @@
     Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc);
     DPRINT("IoSecondStageCompletition, %x\n", Irp);
      
+    UserEvent = Irp->UserEvent;
+    SyncIrp = Irp->Flags & IRP_SYNCHRONOUS_API ? TRUE : FALSE;
+
     /* Handle Buffered case first */
     if (Irp->Flags & IRP_BUFFERED_IO)
     {
@@ -1264,144 +1269,92 @@
         } while (Mdl);
     }
     Irp->MdlAddress = NULL;
-    
-    if (Irp->UserIosb)
+
+    /* Remove the IRP from the list of Thread Pending IRPs */
+    RemoveEntryList(&Irp->ThreadListEntry);
+    InitializeListHead(&Irp->ThreadListEntry);  
+
+    if (NT_SUCCESS(Irp->IoStatus.Status) || Irp->PendingReturned)
     {
-       /*  Save the IOSB Information */
-       *Irp->UserIosb = Irp->IoStatus;
-    }
+       _SEH_TRY
+       {
+          /*  Save the IOSB Information */
+          *Irp->UserIosb = Irp->IoStatus;
+       }
+       _SEH_HANDLE
+       {
+          /* Ignore any error */
+       }
+       _SEH_END;
 
-    /* Check for Success but allow failure for Async IRPs */
-    if (NT_SUCCESS(Irp->IoStatus.Status) || 
-        (Irp->PendingReturned &&
-        !(Irp->Flags & IRP_SYNCHRONOUS_API) &&
-        (FileObject == NULL || FileObject->Flags & FO_SYNCHRONOUS_IO)))
-    {    
-    
-        /* Check if there's an event */
-        if (Irp->UserEvent)
-        {
-            /* Signal the Event */
-            KeSetEvent(Irp->UserEvent, 0, FALSE);
-            
-            /* Check if we should signal the File Object Event as well */
-            if (FileObject)
-            {
-                /* Dereference the Event if this is an ASYNC IRP */
-                if (!Irp->Flags & IRP_SYNCHRONOUS_API)
-                {
-                    ObDereferenceObject(Irp->UserEvent);
-                }
-                
-                 /* If the File Object is SYNC, then we need to signal its event too */
-                if (FileObject->Flags & FO_SYNCHRONOUS_IO)
-                {
-                    /* Signal Event */
-                    KeSetEvent(&FileObject->Event, 0, FALSE);
-                
-                    /* Set the Status */
-                    FileObject->FinalStatus = Irp->IoStatus.Status;
-                }
-            }
-        }
-        else if (FileObject)
-        {
-            /* Signal the File Object Instead */
-            KeSetEvent(&FileObject->Event, 0, FALSE);
-        
-            /* Set the Status */
-            FileObject->FinalStatus = Irp->IoStatus.Status;
-        }
-        
-        /* Remove the IRP from the list of Thread Pending IRPs */
-        RemoveEntryList(&Irp->ThreadListEntry);
-        InitializeListHead(&Irp->ThreadListEntry);  
-    
-        /* Now call the User APC if one was requested */
-        if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
-        {
-            KeInitializeApc(&Irp->Tail.Apc,
-                            KeGetCurrentThread(),
-                            CurrentApcEnvironment,
-                            IoSecondStageCompletion_KernelApcRoutine,
-                            IoSecondStageCompletion_RundownApcRoutine,
-                            (PKNORMAL_ROUTINE)Irp->Overlay.AsynchronousParameters.UserApcRoutine,
-                            Irp->RequestorMode,
-                            Irp->Overlay.AsynchronousParameters.UserApcContext);
+       if (FileObject)
+       {
+          if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+	  {
+             /* Set the Status */
+             FileObject->FinalStatus = Irp->IoStatus.Status;
 
-            KeInsertQueueApc(&Irp->Tail.Apc,
-                             Irp->UserIosb,
-                             NULL,
-                             2);
-        }
-        else if (FileObject && FileObject->CompletionContext)
-        {
-            /* Call the IO Completion Port if we have one, instead */
-            IoSetIoCompletion(FileObject->CompletionContext->Port,
-                              FileObject->CompletionContext->Key,
-                              Irp->Overlay.AsynchronousParameters.UserApcContext,
-                              Irp->IoStatus.Status,
-                              Irp->IoStatus.Information,
-                              FALSE);
-        }
-        else
-        {
-            /* Don't have anything, free it */
-            IoFreeIrp(Irp);
-        }
-        
-        /* Dereference the File Object */
-        if (FileObject) ObDereferenceObject(FileObject);
-    }
-    else
-    {   
-        /* Remove the IRP from the list of Thread Pending IRPs */
-        RemoveEntryList(&Irp->ThreadListEntry);
-        InitializeListHead(&Irp->ThreadListEntry);  
-        
-        /* Signal the Events only if PendingReturned and we have a File Object */
-        if (FileObject && Irp->PendingReturned)
-        {
-            /* Check for SYNC IRP */
-            if (Irp->Flags & IRP_SYNCHRONOUS_API)
-            {
-           
-                /* Signal our event if we have one */
-                if (Irp->UserEvent)
-                {
-                    KeSetEvent(Irp->UserEvent, 0, FALSE);
-                }
-                else
-                {
-                    /* Signal the File's Event instead */
-                    KeSetEvent(&FileObject->Event, 0, FALSE);
-                }
-            }
-            else
-            {
-                /* We'll report the Status to the File Object, not the IRP */
-                FileObject->FinalStatus = Irp->IoStatus.Status;
-                
-                /* Signal the File Object ONLY if this was Async */
+	     if (UserEvent != &FileObject->Event)
+	     {
+	        /* Signal Event */
                 KeSetEvent(&FileObject->Event, 0, FALSE);
-            }
-        }
+	     }
+	  }
+       }
         
-        /* Dereference the Event if it's an ASYNC IRP on a File Object */
-        if (Irp->UserEvent && !(Irp->Flags & IRP_SYNCHRONOUS_API) && FileObject)
-        {
-            if (Irp->UserEvent != &FileObject->Event)
-            {
-                ObDereferenceObject(Irp->UserEvent);
-            }   
-        }
-        
-        /* Dereference the File Object */
-        if (FileObject) ObDereferenceObject(FileObject);
-        
-        /* Free the IRP */
-        IoFreeIrp(Irp);
+       /* Signal the user event, if one exist */
+       if (UserEvent)
+       {
+          KeSetEvent(UserEvent, 0, FALSE);
+       }
+
+       /* Now call the User APC if one was requested */
+       if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
+       {
+          KeInitializeApc(&Irp->Tail.Apc,
+                          KeGetCurrentThread(),
+                          CurrentApcEnvironment,
+                          IoSecondStageCompletion_KernelApcRoutine,
+                          IoSecondStageCompletion_RundownApcRoutine,
+                          (PKNORMAL_ROUTINE)Irp->Overlay.AsynchronousParameters.UserApcRoutine,
+                          Irp->RequestorMode,
+                          Irp->Overlay.AsynchronousParameters.UserApcContext);
+
+          KeInsertQueueApc(&Irp->Tail.Apc,
+                           Irp->UserIosb,
+                           NULL,
+                           2);
+	  Irp = NULL;
+       }
+       else if (FileObject && FileObject->CompletionContext)
+       {
+          /* Call the IO Completion Port if we have one, instead */
+          IoSetIoCompletion(FileObject->CompletionContext->Port,
+                            FileObject->CompletionContext->Key,
+                            Irp->Overlay.AsynchronousParameters.UserApcContext,
+                            Irp->IoStatus.Status,
+                            Irp->IoStatus.Information,
+                            FALSE);
+	  Irp = NULL;
+       }
     }
+    
+    if (Irp)
+    {
+       IoFreeIrp(Irp);
+    }
+
+    if (FileObject)
+    {
+       /* Dereference the user event, if it is an event object */
+       if (UserEvent && !SyncIrp && UserEvent != &FileObject->Event) 
+       {
+          ObDereferenceObject(UserEvent);
+       }
+
+       /* Dereference the File Object */
+       ObDereferenceObject(FileObject);
+    }
 }
 
 /* EOF */