- Changed IopCompleteRequest back to the old schematics (rev 14933) with some minor corrections.

- The status results are always set before an event is signaled.    
- Some checks for ASYNC irp's were wrong (missing brackets, now replaced with SyncIrp).    
- Don't signal the FO event if it is the same as the UserEvent.  
- Set the IOSB on error for async irp's with a sync FO (fix bug #609).    

IMHO, the old schematics is wrong, because on error it is possible that an event
isn't signaled if the driver has previous returned STATUS_PENDING.   
In this case, the caller will wait forever.

svn path=/trunk/; revision=15117
This commit is contained in:
Hartmut Birr 2005-05-08 10:26:34 +00:00
parent 35deccffea
commit 83fb8b7c7c

View file

@ -117,6 +117,162 @@ IopCompleteRequest(PKAPC Apc,
RemoveEntryList(&Irp->ThreadListEntry);
InitializeListHead(&Irp->ThreadListEntry);
#if 1
/* Check for Success but allow failure for Async IRPs */
if (NT_SUCCESS(Irp->IoStatus.Status) ||
(Irp->PendingReturned &&
!SyncIrp &&
(FileObject == NULL || FileObject->Flags & FO_SYNCHRONOUS_IO)))
{
_SEH_TRY
{
/* Save the IOSB Information */
*Irp->UserIosb = Irp->IoStatus;
}
_SEH_HANDLE
{
/* Ignore any error */
}
_SEH_END;
/* Check if there's an event */
if (UserEvent)
{
/* Check if we should signal the File Object Event as well */
if (FileObject)
{
/* If the File Object is SYNC, then we need to signal its event too */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Set the Status */
FileObject->FinalStatus = Irp->IoStatus.Status;
/* Signal Event */
KeSetEvent(&FileObject->Event, 0, FALSE);
}
}
/* Signal the Event */
KeSetEvent(UserEvent, 0, FALSE);
/* Dereference the Event if this is an ASYNC IRP */
if (FileObject && !SyncIrp && UserEvent != &FileObject->Event)
{
ObDereferenceObject(UserEvent);
}
}
else if (FileObject)
{
/* Set the Status */
FileObject->FinalStatus = Irp->IoStatus.Status;
/* Signal the File Object Instead */
KeSetEvent(&FileObject->Event, 0, FALSE);
}
/* Now call the User APC if one was requested */
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
{
KeInitializeApc(&Irp->Tail.Apc,
KeGetCurrentThread(),
CurrentApcEnvironment,
IopFreeIrpKernelApc,
IopAbortIrpKernelApc,
(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;
}
}
else
{
/* Signal the Events only if PendingReturned and we have a File Object */
if (FileObject && Irp->PendingReturned)
{
/* Check for SYNC IRP */
if (SyncIrp)
{
/* Set the status in this case only */
_SEH_TRY
{
*Irp->UserIosb = Irp->IoStatus;
}
_SEH_HANDLE
{
/* Ignore any error */
}
_SEH_END;
/* Signal our event if we have one */
if (UserEvent)
{
KeSetEvent(UserEvent, 0, FALSE);
}
else
{
/* Signal the File's Event instead */
KeSetEvent(&FileObject->Event, 0, FALSE);
}
}
else
{
#if 1
/* FIXME: This is necessary to fix bug #609 */
_SEH_TRY
{
*Irp->UserIosb = Irp->IoStatus;
}
_SEH_HANDLE
{
/* Ignore any error */
}
_SEH_END;
#endif
/* 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 (UserEvent && !SyncIrp && FileObject)
{
if (UserEvent != &FileObject->Event)
{
ObDereferenceObject(UserEvent);
}
}
}
/* Dereference the File Object */
if (FileObject) ObDereferenceObject(FileObject);
if (Irp)
{
/* Free the IRP */
IoFreeIrp(Irp);
}
#else
if (NT_SUCCESS(Irp->IoStatus.Status) || Irp->PendingReturned)
{
_SEH_TRY
@ -198,6 +354,7 @@ IopCompleteRequest(PKAPC Apc,
/* Dereference the File Object */
ObDereferenceObject(FileObject);
}
#endif
}
/* FUNCTIONS *****************************************************************/