TDI timeouts & IRP cancellation...

Hi,

Below is some code that have to work but it does not… So what goes on:
IoCallDriver() returns immidiately (no STATUS_PENDING returned so no
KeWaitForSingleObject() initiated). Then TdiBrideOnComplete() is invoked.
I do return STATUS_MORE_PROCESSING_REQUIRED so the IRP is not freed. After
this I clear event explicitly by calling KeClearEvent(), call
IoCompleteRequest() with the address of the IRP i use to complete
processing of IRP and call KeWaitForSingleObject() to wait until the
completion of IRP processing/freeing. But this last call BLOCKS FOREVER!!
WHY??? WHAT AM I DOING WRONG? What’s the correct way to implement timeouts
in calling TDI?

Thanks for help,
Anton

NTSTATUS
TdiBrideOnComplete(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pvoidContext
)
{
DbgPrint( “TdiBride:TdiBrideOnComplete(): ENTERed…\n” );

//
// set signalling event
//
KeSetEvent(
( PKEVENT )( pvoidContext ),
IO_NO_INCREMENT,
FALSE
);

DbgPrint( “TdiBride:TdiBrideOnComplete(): BEFORE exit…\n” );

//
// return correct status
//
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
TdiBrideCallEx(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PKEVENT pkEvent,
IN PIO_STATUS_BLOCK pIoStatusBlock
)
{
NTSTATUS ntStatus;

NTSTATUS ntStatusFinal;

LARGE_INTEGER largeIntegerTimeout;

DbgPrint( “TdiBride:TdiBrideCallEx(): ENTERed…\n” );

/*
DbgPrint(
“TdiBride:TdiBrideCallEx(): KIRQL == %u…\n”,
KeGetCurrentIrql()
);
*/

/*

//
// set completion routine on the IRP
//
IoSetCompletionRoutine(
pIrp,
TdiBrideOnComplete,
pkEvent,
TRUE,
TRUE,
TRUE
);

*/

//
// try to call underlying device object
//
ntStatus =
IoCallDriver(
pDeviceObject,
pIrp
);

//
// check for the status of IoCallDriver(…)
//
if ( ntStatus == STATUS_PENDING )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): IoCallDriver() is pending…\n”
);

//
// prepare timeout…
//

largeIntegerTimeout.QuadPart = 10000L; // debug…
//10000000L; // in seconds…

largeIntegerTimeout.QuadPart *= DEFAULT_TIMEOUT_IN_SECONDS; // convert to
seconds…

largeIntegerTimeout.QuadPart = - ( largeIntegerTimeout.QuadPart ); //
relative time to wait…

//
// wait for async I/O completion
//
ntStatus =
KeWaitForSingleObject(
pkEvent,
//UserRequest,
Executive,
KernelMode,
FALSE,
&largeIntegerTimeout // our timeout
//NULL
);

//
// check if this is timeout
//
if ( ntStatus == STATUS_TIMEOUT )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): call timeouted…\n” );

//
// cancel pending request
//
IoCancelIrp( pIrp );

//
// clear event
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);
}
}

//
// check for the status of KeWaitForSingleObject() or IoCallDriver()
call…
//
if ( NT_SUCCESS( ntStatus ) == FALSE )
{
DbgPrint(
“TdiBride:TdiBrideCallEx(): KeWaitForSingleObject() or IoCallDriver()
failed, status == 0x%08X\n”,
ntStatus
);

//
// set final status to failed status
//
ntStatusFinal = ntStatus;
}
else
{
DbgPrint(
“TdiBride:TdiBrideCallEx(): KeWaitForSingleObject() or IoCallDriver()
OK, status == 0x%08X\n”,
pIoStatusBlock->Status
);

//
// set final status to IRP status
//
ntStatusFinal = pIoStatusBlock->Status;
}

//
// clear event
//
KeClearEvent( pkEvent );

//
// complete request in second time
//
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);

//
// clear last wait
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);

DbgPrint(
“TdiBride:TdiBrideCallEx(): EXITing with status == 0x%08X…\n”,
ntStatusFinal
);

//
// return final status
//
return ntStatusFinal;
}


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

STATUS_MORE_PROCESSING_REQUIRED will not retain the IRP unless the IRP
is marked as ‘Pending’, otherwise it will be freed.

Regards,
Youssef

-----Original Message-----
From: xxxxx@hotmail.com
[mailto:xxxxx@hotmail.com]
Sent: Thursday, May 17, 2001 5:00 PM
To: NT Developers Interest List
Subject: [ntdev] TDI timeouts & IRP cancellation…

Hi,

Below is some code that have to work but it does not… So what goes on:
IoCallDriver() returns immidiately (no STATUS_PENDING returned so no
KeWaitForSingleObject() initiated). Then TdiBrideOnComplete() is
invoked.
I do return STATUS_MORE_PROCESSING_REQUIRED so the IRP is not freed.
After
this I clear event explicitly by calling KeClearEvent(), call
IoCompleteRequest() with the address of the IRP i use to complete
processing of IRP and call KeWaitForSingleObject() to wait until the
completion of IRP processing/freeing. But this last call BLOCKS
FOREVER!!
WHY??? WHAT AM I DOING WRONG? What’s the correct way to implement
timeouts
in calling TDI?

Thanks for help,
Anton

NTSTATUS
TdiBrideOnComplete(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pvoidContext
)
{
DbgPrint( “TdiBride:TdiBrideOnComplete(): ENTERed…\n” );

//
// set signalling event
//
KeSetEvent(
( PKEVENT )( pvoidContext ),
IO_NO_INCREMENT,
FALSE
);

DbgPrint( “TdiBride:TdiBrideOnComplete(): BEFORE exit…\n” );

//
// return correct status
//
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
TdiBrideCallEx(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PKEVENT pkEvent,
IN PIO_STATUS_BLOCK pIoStatusBlock
)
{
NTSTATUS ntStatus;

NTSTATUS ntStatusFinal;

LARGE_INTEGER largeIntegerTimeout;

DbgPrint( “TdiBride:TdiBrideCallEx(): ENTERed…\n” );

/*
DbgPrint(
“TdiBride:TdiBrideCallEx(): KIRQL == %u…\n”,
KeGetCurrentIrql()
);
*/

/*

//
// set completion routine on the IRP
//
IoSetCompletionRoutine(
pIrp,
TdiBrideOnComplete,
pkEvent,
TRUE,
TRUE,
TRUE
);

*/

//
// try to call underlying device object
//
ntStatus =
IoCallDriver(
pDeviceObject,
pIrp
);

//
// check for the status of IoCallDriver(…)
//
if ( ntStatus == STATUS_PENDING )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): IoCallDriver() is
pending…\n”
);

//
// prepare timeout…
//

largeIntegerTimeout.QuadPart = 10000L; // debug…
//10000000L; // in seconds…

largeIntegerTimeout.QuadPart *=
DEFAULT_TIMEOUT_IN_SECONDS; // convert to
seconds…

largeIntegerTimeout.QuadPart = - (
largeIntegerTimeout.QuadPart ); //
relative time to wait…

//
// wait for async I/O completion
//
ntStatus =
KeWaitForSingleObject(
pkEvent,
//UserRequest,
Executive,
KernelMode,
FALSE,
&largeIntegerTimeout // our timeout
//NULL
);

//
// check if this is timeout
//
if ( ntStatus == STATUS_TIMEOUT )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): call
timeouted…\n” );

//
// cancel pending request
//
IoCancelIrp( pIrp );

//
// clear event
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);
}
}

//
// check for the status of KeWaitForSingleObject() or
IoCallDriver()
call…
//
if ( NT_SUCCESS( ntStatus ) == FALSE )
{
DbgPrint(
“TdiBride:TdiBrideCallEx():
KeWaitForSingleObject() or IoCallDriver()
failed, status == 0x%08X\n”,
ntStatus
);

//
// set final status to failed status
//
ntStatusFinal = ntStatus;
}
else
{
DbgPrint(
“TdiBride:TdiBrideCallEx():
KeWaitForSingleObject() or IoCallDriver()
OK, status == 0x%08X\n”,
pIoStatusBlock->Status
);

//
// set final status to IRP status
//
ntStatusFinal = pIoStatusBlock->Status;
}

//
// clear event
//
KeClearEvent( pkEvent );

//
// complete request in second time
//
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);

//
// clear last wait
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);

DbgPrint(
“TdiBride:TdiBrideCallEx(): EXITing with status ==
0x%08X…\n”,
ntStatusFinal
);

//
// return final status
//
return ntStatusFinal;
}


You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Hi Anton,

The problem in the code below is that your completion routine will not
be called again, thus your event will not be signalled.
IoCompleteRequest will begin processing IRP stack locations above yours.
All you need to do is remove the KeWaitForSingleObject.

//
// complete request in second time
//
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);

//
// clear last wait
//
KeWaitForSingleObject( <------------- Remove this.
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);

Also,
Please scratch my last e-mail, it was not accurate.

What I meant to say was that if you call IoCallDriver and the driver
below you completes the IRP with STATUS_SUCCESS and you return
STATUS_MORE_PROCESSING REQUIRED from your completion routine, you should
not return STATUS_SUCCESS to the driver who called you without calling
IoCompleteRequest first. This is because the IoManager will call
IopCompleteRequest (that’s not a typo), which frees the IRP. The
following piece of code should help clarify my point:

IOMANAGER(SIMPLIFIED):

Status = IoCallDriver(DeviceObject, Irp);

If (status == STATUS_PENDING) {
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
TRUE,
0);
} else {
IopCompleteRequest(…);
}

This isn’t the real IoManager code but the concept is similar. Either
way, this has nothing to do with your problem, since you’re obviously
calling IoCompleteRequest and not just returning STATUS_SUCCESS;

Sorry for any confusion.

Regards,
Youssef

-----Original Message-----
From: xxxxx@hotmail.com
[mailto:xxxxx@hotmail.com]
Sent: Thursday, May 17, 2001 5:00 PM
To: NT Developers Interest List
Subject: [ntdev] TDI timeouts & IRP cancellation…

Hi,

Below is some code that have to work but it does not… So what goes on:
IoCallDriver() returns immidiately (no STATUS_PENDING returned so no
KeWaitForSingleObject() initiated). Then TdiBrideOnComplete() is
invoked.
I do return STATUS_MORE_PROCESSING_REQUIRED so the IRP is not freed.
After
this I clear event explicitly by calling KeClearEvent(), call
IoCompleteRequest() with the address of the IRP i use to complete
processing of IRP and call KeWaitForSingleObject() to wait until the
completion of IRP processing/freeing. But this last call BLOCKS
FOREVER!!
WHY??? WHAT AM I DOING WRONG? What’s the correct way to implement
timeouts
in calling TDI?

Thanks for help,
Anton

NTSTATUS
TdiBrideOnComplete(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pvoidContext
)
{
DbgPrint( “TdiBride:TdiBrideOnComplete(): ENTERed…\n” );

//
// set signalling event
//
KeSetEvent(
( PKEVENT )( pvoidContext ),
IO_NO_INCREMENT,
FALSE
);

DbgPrint( “TdiBride:TdiBrideOnComplete(): BEFORE exit…\n” );

//
// return correct status
//
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
TdiBrideCallEx(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PKEVENT pkEvent,
IN PIO_STATUS_BLOCK pIoStatusBlock
)
{
NTSTATUS ntStatus;

NTSTATUS ntStatusFinal;

LARGE_INTEGER largeIntegerTimeout;

DbgPrint( “TdiBride:TdiBrideCallEx(): ENTERed…\n” );

/*
DbgPrint(
“TdiBride:TdiBrideCallEx(): KIRQL == %u…\n”,
KeGetCurrentIrql()
);
*/

/*

//
// set completion routine on the IRP
//
IoSetCompletionRoutine(
pIrp,
TdiBrideOnComplete,
pkEvent,
TRUE,
TRUE,
TRUE
);

*/

//
// try to call underlying device object
//
ntStatus =
IoCallDriver(
pDeviceObject,
pIrp
);

//
// check for the status of IoCallDriver(…)
//
if ( ntStatus == STATUS_PENDING )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): IoCallDriver() is
pending…\n”
);

//
// prepare timeout…
//

largeIntegerTimeout.QuadPart = 10000L; // debug…
//10000000L; // in seconds…

largeIntegerTimeout.QuadPart *=
DEFAULT_TIMEOUT_IN_SECONDS; // convert to
seconds…

largeIntegerTimeout.QuadPart = - (
largeIntegerTimeout.QuadPart ); //
relative time to wait…

//
// wait for async I/O completion
//
ntStatus =
KeWaitForSingleObject(
pkEvent,
//UserRequest,
Executive,
KernelMode,
FALSE,
&largeIntegerTimeout // our timeout
//NULL
);

//
// check if this is timeout
//
if ( ntStatus == STATUS_TIMEOUT )
{
DbgPrint( “TdiBride:TdiBrideCallEx(): call
timeouted…\n” );

//
// cancel pending request
//
IoCancelIrp( pIrp );

//
// clear event
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);
}
}

//
// check for the status of KeWaitForSingleObject() or
IoCallDriver()
call…
//
if ( NT_SUCCESS( ntStatus ) == FALSE )
{
DbgPrint(
“TdiBride:TdiBrideCallEx():
KeWaitForSingleObject() or IoCallDriver()
failed, status == 0x%08X\n”,
ntStatus
);

//
// set final status to failed status
//
ntStatusFinal = ntStatus;
}
else
{
DbgPrint(
“TdiBride:TdiBrideCallEx():
KeWaitForSingleObject() or IoCallDriver()
OK, status == 0x%08X\n”,
pIoStatusBlock->Status
);

//
// set final status to IRP status
//
ntStatusFinal = pIoStatusBlock->Status;
}

//
// clear event
//
KeClearEvent( pkEvent );

//
// complete request in second time
//
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);

//
// clear last wait
//
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);

DbgPrint(
“TdiBride:TdiBrideCallEx(): EXITing with status ==
0x%08X…\n”,
ntStatusFinal
);

//
// return final status
//
return ntStatusFinal;
}


You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Hi,

Thank you for reply. Removing KeWaitForSignleObject() that’s what I did
myself (I was confused by not seeng any messages from TdiBrideOnComplete()
when I was calling IoCompleteRequest() by myself). That removed blocking,
but did not resolve the problem… Sometimes such IRP cancellation crash
TCPIP.SYS so I’ve totally changed IRP cancellation technique -(((

Thanks a lot once again!!

Regards,
Anton

P.S. 2all: Any ideas how to make CORRECT IRP cancellation in TDI client
drivers?


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com