- 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 */