I think you are confusing dispatch routine rules with completion
routines rules. The pattern of
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp);
return ntStatus;
is correct for a dispatch routine, not a completion routine. Think of
the return value from a completion routine as a BOOLEAN, not an
NTSTATUS. If TRUE, the return value tells the io manager to continue
completing the request. If FALSE, the return value tells the io manager
to no longer continue completing the request. The NTSTATUS values are
mapped to the BOOLEAN decision like this
if (return NTSTATUS == STATUS_MORE_PROCESSING_REQUIRED), result is FALSE
else (return NSTATUS is any other value), result is TRUE
so given this, let’s look at the snippet again
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp); <– complete the request once
return ntStatus; <– by returning NTSTATUS !=
STATUS_MORE_PROCESSING_REQUIRED you are telling the io manager to
continue completion, but you already completed the request above! This
will result in corruption or a bugcheck depending on the irp’s state
Both of these snippets are functionally equivalent, they both complete
the request back to the caller
1)
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
// no call to IoCompleteRequest
return Irp->IoStatus.Status;
d
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Wednesday, August 01, 2007 6:56 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Valid return values from a completion routine
Hi,
I would like to have some clarifications regarding status values that
can be returned from a completion routine.
I thought that returning ContinueCompletion from a completion routine
propagated the status of the lower driver, but this link:
http://msdn2.microsoft.com/en-us/library/ms798250.aspx recomments to
call IoCompleteRequest and return the same status that was returned by a
lower driver. Which is the right way?
Which of the following completion routine should be used to propagate
the status returned by the lower driver.
static NTSTATUS
Power_SystemPowerCompleted_1(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PVOID Context
)
{
NTSTATUS ntStatus;
// …
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp);
return ntStatus;
}
static NTSTATUS
Power_SystemPowerCompleted_2(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PVOID Context
)
{
// …
return ContinueCompletion;
}
static NTSTATUS
Power_HandleSystemPower(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
Power_SystemPowerCompleted,
NULL,
TRUE, TRUE, TRUE);
PoCallDriver(GetDeviceExtension(DeviceObject)->LowerDeviceObject, Irp);
return STATUS_PENDING;
}
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer