- 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.


svn path=/trunk/; revision=14988
This commit is contained in:
Hartmut Birr 2005-05-05 10:59:34 +00:00
parent e80efe27d7
commit 4200c75f3b

View file

@ -1222,6 +1222,8 @@ IoSecondStageCompletion(PKAPC Apc,
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PIRP Irp; PIRP Irp;
PMDL Mdl, NextMdl; PMDL Mdl, NextMdl;
PKEVENT UserEvent;
BOOLEAN SyncIrp;
if (Apc) DPRINT("IoSecondStageCompletition with APC: %x\n", Apc); if (Apc) DPRINT("IoSecondStageCompletition with APC: %x\n", Apc);
@ -1230,6 +1232,9 @@ IoSecondStageCompletion(PKAPC Apc,
Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc); Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc);
DPRINT("IoSecondStageCompletition, %x\n", Irp); DPRINT("IoSecondStageCompletition, %x\n", Irp);
UserEvent = Irp->UserEvent;
SyncIrp = Irp->Flags & IRP_SYNCHRONOUS_API ? TRUE : FALSE;
/* Handle Buffered case first */ /* Handle Buffered case first */
if (Irp->Flags & IRP_BUFFERED_IO) if (Irp->Flags & IRP_BUFFERED_IO)
{ {
@ -1265,58 +1270,44 @@ IoSecondStageCompletion(PKAPC Apc,
} }
Irp->MdlAddress = NULL; 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)
{
_SEH_TRY
{ {
/* Save the IOSB Information */ /* Save the IOSB Information */
*Irp->UserIosb = Irp->IoStatus; *Irp->UserIosb = Irp->IoStatus;
} }
_SEH_HANDLE
/* 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)))
{ {
/* Ignore any error */
}
_SEH_END;
/* 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) 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) if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Set the Status */
FileObject->FinalStatus = Irp->IoStatus.Status;
if (UserEvent != &FileObject->Event)
{ {
/* Signal Event */ /* Signal Event */
KeSetEvent(&FileObject->Event, 0, FALSE); KeSetEvent(&FileObject->Event, 0, FALSE);
}
}
}
/* Set the Status */ /* Signal the user event, if one exist */
FileObject->FinalStatus = Irp->IoStatus.Status; if (UserEvent)
}
}
}
else if (FileObject)
{ {
/* Signal the File Object Instead */ KeSetEvent(UserEvent, 0, FALSE);
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 */ /* Now call the User APC if one was requested */
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL) if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
{ {
@ -1333,6 +1324,7 @@ IoSecondStageCompletion(PKAPC Apc,
Irp->UserIosb, Irp->UserIosb,
NULL, NULL,
2); 2);
Irp = NULL;
} }
else if (FileObject && FileObject->CompletionContext) else if (FileObject && FileObject->CompletionContext)
{ {
@ -1343,64 +1335,25 @@ IoSecondStageCompletion(PKAPC Apc,
Irp->IoStatus.Status, Irp->IoStatus.Status,
Irp->IoStatus.Information, Irp->IoStatus.Information,
FALSE); FALSE);
Irp = NULL;
} }
else }
if (Irp)
{ {
/* Don't have anything, free it */
IoFreeIrp(Irp); IoFreeIrp(Irp);
} }
/* Dereference the File Object */ if (FileObject)
if (FileObject) ObDereferenceObject(FileObject);
}
else
{ {
/* Remove the IRP from the list of Thread Pending IRPs */ /* Dereference the user event, if it is an event object */
RemoveEntryList(&Irp->ThreadListEntry); if (UserEvent && !SyncIrp && UserEvent != &FileObject->Event)
InitializeListHead(&Irp->ThreadListEntry);
/* Signal the Events only if PendingReturned and we have a File Object */
if (FileObject && Irp->PendingReturned)
{ {
/* Check for SYNC IRP */ ObDereferenceObject(UserEvent);
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 */
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 */ /* Dereference the File Object */
if (FileObject) ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
/* Free the IRP */
IoFreeIrp(Irp);
} }
} }