Problem with Tdi client - asynchronous trasmitting

Hello,

I have discovered one problem which I could not solve yet.
Driver(TDI client) start thread wuch send some kind of info directly to tcpip
driver, using TDI_SEND and TdiBuildInternalDeviceControlIrp.
I set completion routine which does nothing
except deallocates mdl and returns STATUS_MORE_PROCESSING_REQUIRED.
Event doesn’t set because of asynchronous
nature of data transmission. Everything works fine. But… When I’m trying
to stop thread I could not because PsTerminateSystemThread calls
IoCancelThreadIo and in the turn does nothing - thread has list of
Irps(windbg shows them). What can I do?
I do not call IoFreeIrp(according to Max S.).
May be I have to call IoAllocateIrp and call IoFreeIrp in completion
routine?


Best regards,
Sergey mailto:kipnis@wp.pl

Hello Sergey,

Monday, May 26, 2003, 4:47:57 PM, you wrote:

It seems that problem was solved. IoAllocateIrp instead of
IoBuildDeviceIoControlRequest and IoFreeIrp in completion routine.
Completion routine returns STATUS_MORE_PROCESSING_REQUIRED still.
Is this approach correct?
Should I call IoMarkIrpPending in the Completion routine? My driver is
topmost one) and it doesn’t care what happened inside tcpip.sys.

SK> I have discovered one problem which I could not solve yet.
SK> Driver(TDI client) start thread wuch send some kind of info directly to tcpip
SK> driver, using TDI_SEND and TdiBuildInternalDeviceControlIrp.
SK> I set completion routine which does nothing
SK> except deallocates mdl and returns STATUS_MORE_PROCESSING_REQUIRED.
SK> Event doesn’t set because of asynchronous
SK> nature of data transmission. Everything works fine. But… When I’m trying
SK> to stop thread I could not because PsTerminateSystemThread calls
SK> IoCancelThreadIo and in the turn does nothing - thread has list of
SK> Irps(windbg shows them). What can I do?
SK> I do not call IoFreeIrp(according to Max S.).
SK> May be I have to call IoAllocateIrp and call IoFreeIrp in completion
SK> routine?


Best regards,
Sergey mailto:kipnis@wp.pl

Forget about TdiBuildInternalDeviceControlIrp, use IoAllocateIrp
instead.

In this case, you will be able to get rid of the worker thread too,
sending TDI_SEND IRPs directly, even from DISPATCH_LEVEL, and solving
all problems with PsTerminateSystemThread :slight_smile:

Max

----- Original Message -----
From: “Sergey Kipnis”
To: “NT Developers Interest List”
Sent: Monday, May 26, 2003 6:47 PM
Subject: [ntdev] Problem with Tdi client - asynchronous trasmitting

> Hello,
>
> I have discovered one problem which I could not solve yet.
> Driver(TDI client) start thread wuch send some kind of info directly
to tcpip
> driver, using TDI_SEND and TdiBuildInternalDeviceControlIrp.
> I set completion routine which does nothing
> except deallocates mdl and returns STATUS_MORE_PROCESSING_REQUIRED.
> Event doesn’t set because of asynchronous
> nature of data transmission. Everything works fine. But… When I’m
trying
> to stop thread I could not because PsTerminateSystemThread calls
> IoCancelThreadIo and in the turn does nothing - thread has list of
> Irps(windbg shows them). What can I do?
> I do not call IoFreeIrp(according to Max S.).
> May be I have to call IoAllocateIrp and call IoFreeIrp in
completion
> routine?
>
> –
> Best regards,
> Sergey mailto:kipnis@wp.pl
>
>
>
> —
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to
xxxxx@lists.osr.com

> Should I call IoMarkIrpPending in the Completion routine?

Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not do
this.

Max

Hello Maxim,

Monday, May 26, 2003, 6:07:36 PM, you wrote:

> Should I call IoMarkIrpPending in the Completion routine?

MSS> Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not do
MSS> this.

Should I call IoFreeIrp in the completion routine? It seems that system will
call it if I return STATUS_MORE_PROCESSING_REQUIRED.


Best regards,
Sergey mailto:kipnis@wp.pl

> MSS> Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not
do

MSS> this.

Should I call IoFreeIrp in the completion routine? It seems that
system will
call it if I return STATUS_MORE_PROCESSING_REQUIRED.

No, you must call it yourself.

Max

Hello Maxim,

Tuesday, May 27, 2003, 12:23:22 AM, you wrote:

Still I have a small problem.

After few minutes of normal job system refuses to call My Completion
routine anymore.

Code is simple

// completion routine
NTSTATUS HstdSendComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
// mdl buffer
if (Irp->MdlAddress != NULL)
{
MmUnlockPages(Irp->MdlAddress);
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
}

// Free buffer
if(Context)
{
CSendCompleteContext* p = (CSendCompleteContext*)Context;
if(p->m_Buf && p->m_fooDeleteProc )
{
p->m_fooDeleteProc(p->m_Buf); // delete preallocated buffer
}
delete p;
}

IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS CTdiInfo::SendBuffer( CClientNote* pClient,
DWORD len,
char* buf,
FOO_DeleteProc DeleteProc )
{
NTSTATUS ret;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
PMDL pMdl;

// sending
IRP* pIrp = IoAllocateIrp( m_pDeviceObject->StackSize, FALSE );

//DumpTime(“HTSD: 2”);
if ( pIrp == NULL ) // validate pointer
ret = STATUS_INSUFFICIENT_RESOURCES;
else
{
pMdl = IoAllocateMdl (
buf, // buffer pointer - virtual address
len, // length
FALSE, // not secondary
FALSE, // don’t charge quota
NULL ); // don’t use irp
if ( pMdl ) // validate mdl pointer
{
__try
{
MmProbeAndLockPages ( pMdl, KernelMode, IoModifyAccess ); // probe & lock
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
dump ( “EXCEPTION: MmProbeAndLockPages\n” );
IoFreeMdl( pMdl );
pMdl = NULL;
}
}
if ( pMdl )
{
// internal code
CSendCompleteContext* x = 0;
if( DeleteProc )
{
// data will be destroyed in Completion
// routine
x = new CSendCompleteContext;
x->m_Buf = buf;
x->m_fooDeleteProc = DeleteProc;
}
// building
TdiBuildSend(
pIrp,
m_pDeviceObject,
pClient->m_pEp->m_Object,
HstdSendComplete, // completion routine
x, // completion context
pMdl,
0, // flags
len
);
// marking
IoMarkIrpPending(pIrp);
// calling
ret = IoCallDriver( m_pDeviceObject, pIrp );

// post-processing
if ( ret == STATUS_PENDING ) // make all request synchronous
{
ret = STATUS_SUCCESS;
}
else
{
if(ret != STATUS_SUCCESS)
{
dump(“HSTD: IoCallDriver ret = %X\n”, ret );
return ret;
}
}

if(ret != STATUS_SUCCESS)
{
dump(“Send failed with status %X\n”, ret );
}
}
else
{
IoFreeIrp(pIrp);
ret = STATUS_INSUFFICIENT_RESOURCES;
}
}

return ret;
}

> MSS> Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not
MSS> do
> MSS> this.
>
> Should I call IoFreeIrp in the completion routine? It seems that
MSS> system will
> call it if I return STATUS_MORE_PROCESSING_REQUIRED.

MSS> No, you must call it yourself.

MSS> Max

MSS> —
MSS> You are currently subscribed to ntdev as: kipnis@wp.pl
MSS> To unsubscribe send a blank email to xxxxx@lists.osr.com


Best regards,
Sergey mailto:kipnis@wp.pl

In the below code I assume you’ve written operator new to allocate from
the NonPagedPool, since you are calling delete inside of a completion
routine (which could be called at dispatch level).

  • Nick Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Sergey Kipnis
Sent: Sunday, June 22, 2003 9:24 AM
To: NT Developers Interest List
Subject: [ntdev] Re: Problem with Tdi client - asynchronous
trasmitting

Hello Maxim,

Tuesday, May 27, 2003, 12:23:22 AM, you wrote:

Still I have a small problem.

After few minutes of normal job system refuses to call My
Completion routine anymore.

Code is simple

// completion routine
NTSTATUS HstdSendComplete(PDEVICE_OBJECT DeviceObject, PIRP
Irp, PVOID Context) {
// mdl buffer
if (Irp->MdlAddress != NULL)
{
MmUnlockPages(Irp->MdlAddress);
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
}

// Free buffer
if(Context)
{
CSendCompleteContext* p = (CSendCompleteContext*)Context;
if(p->m_Buf && p->m_fooDeleteProc )
{
p->m_fooDeleteProc(p->m_Buf); // delete
preallocated buffer
}
delete p;
}

IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS CTdiInfo::SendBuffer( CClientNote* pClient,
DWORD len,
char* buf,
FOO_DeleteProc DeleteProc )
{
NTSTATUS ret;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
PMDL pMdl;

// sending
IRP* pIrp = IoAllocateIrp( m_pDeviceObject->StackSize, FALSE );

//DumpTime(“HTSD: 2”);
if ( pIrp == NULL ) // validate pointer
ret = STATUS_INSUFFICIENT_RESOURCES;
else
{
pMdl = IoAllocateMdl (
buf, // buffer pointer - virtual address
len, // length
FALSE, // not secondary
FALSE, // don’t charge quota
NULL ); // don’t use irp
if ( pMdl ) // validate mdl pointer
{
__try
{
MmProbeAndLockPages ( pMdl, KernelMode,
IoModifyAccess ); // probe & lock
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
dump ( “EXCEPTION: MmProbeAndLockPages\n” );
IoFreeMdl( pMdl );
pMdl = NULL;
}
}
if ( pMdl )
{
// internal code
CSendCompleteContext* x = 0;
if( DeleteProc )
{
// data will be destroyed in Completion
// routine
x = new CSendCompleteContext;
x->m_Buf = buf;
x->m_fooDeleteProc = DeleteProc;
}
// building
TdiBuildSend(
pIrp,
m_pDeviceObject,
pClient->m_pEp->m_Object,
HstdSendComplete, //
completion routine
x, // completion context
pMdl,
0, // flags
len
);
// marking
IoMarkIrpPending(pIrp);
// calling
ret = IoCallDriver( m_pDeviceObject, pIrp );

// post-processing
if ( ret == STATUS_PENDING )
// make all request synchronous
{
ret = STATUS_SUCCESS;
}
else
{
if(ret != STATUS_SUCCESS)
{
dump(“HSTD: IoCallDriver ret = %X\n”, ret );
return ret;
}
}

if(ret != STATUS_SUCCESS)
{
dump(“Send failed with status %X\n”, ret );
}
}
else
{
IoFreeIrp(pIrp);
ret = STATUS_INSUFFICIENT_RESOURCES;
}
}

return ret;
}

>> MSS> Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not
MSS> do
>> MSS> this.
>>
>> Should I call IoFreeIrp in the completion routine? It seems that
MSS> system will
>> call it if I return STATUS_MORE_PROCESSING_REQUIRED.

MSS> No, you must call it yourself.

MSS> Max

MSS> —
MSS> You are currently subscribed to ntdev as: kipnis@wp.pl
MSS> To unsubscribe send a blank email to
MSS> xxxxx@lists.osr.com


Best regards,
Sergey mailto:kipnis@wp.pl


You are currently subscribed to ntdev as: xxxxx@nryan.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Hello Nick,

Sunday, June 22, 2003, 9:25:32 PM, you wrote:

Of course, I’m using NonPagePool.

Is it correct to call IoCallDriver and do NOT wait for return?
Assuming I have high traffic more than 2000 packets per second?

Btw, I have very strange behaviour of ReWaitForSingleObject(if I will
wait for return from IoCallDriver) - time spent here is about 200-400
millisecond.

NR> In the below code I assume you’ve written operator new to allocate from
NR> the NonPagedPool, since you are calling delete inside of a completion
NR> routine (which could be called at dispatch level).

NR> - Nick Ryan

> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Sergey Kipnis
> Sent: Sunday, June 22, 2003 9:24 AM
> To: NT Developers Interest List
> Subject: [ntdev] Re: Problem with Tdi client - asynchronous
> trasmitting
>
>
> Hello Maxim,
>
> Tuesday, May 27, 2003, 12:23:22 AM, you wrote:
>
> Still I have a small problem.
>
> After few minutes of normal job system refuses to call My
> Completion routine anymore.
>
> Code is simple
>
> // completion routine
> NTSTATUS HstdSendComplete(PDEVICE_OBJECT DeviceObject, PIRP
> Irp, PVOID Context) {
> // mdl buffer
> if (Irp->MdlAddress != NULL)
> {
> MmUnlockPages(Irp->MdlAddress);
> IoFreeMdl(Irp->MdlAddress);
> Irp->MdlAddress = NULL;
> }
>
> // Free buffer
> if(Context)
> {
> CSendCompleteContext* p = (CSendCompleteContext*)Context;
> if(p->m_Buf && p->m_fooDeleteProc )
> {
> p->m_fooDeleteProc(p->m_Buf); // delete
> preallocated buffer
> }
> delete p;
> }
>
> IoFreeIrp(Irp);
> return STATUS_MORE_PROCESSING_REQUIRED;
> }
>
>
> NTSTATUS CTdiInfo::SendBuffer( CClientNote* pClient,
> DWORD len,
> char* buf,
> FOO_DeleteProc DeleteProc )
> {
> NTSTATUS ret;
> IO_STATUS_BLOCK IoStatus;
> KEVENT Event;
> PMDL pMdl;
>
> // sending
> IRP* pIrp = IoAllocateIrp( m_pDeviceObject->StackSize, FALSE );
>
> //DumpTime(“HTSD: 2”);
> if ( pIrp == NULL ) // validate pointer
> ret = STATUS_INSUFFICIENT_RESOURCES;
> else
> {
> pMdl = IoAllocateMdl (
> buf, // buffer pointer - virtual address
> len, // length
> FALSE, // not secondary
> FALSE, // don’t charge quota
> NULL ); // don’t use irp
> if ( pMdl ) // validate mdl pointer
> {
> __try
> {
> MmProbeAndLockPages ( pMdl, KernelMode,
> IoModifyAccess ); // probe & lock
> }
> __except ( EXCEPTION_EXECUTE_HANDLER )
> {
> dump ( “EXCEPTION: MmProbeAndLockPages\n” );
> IoFreeMdl( pMdl );
> pMdl = NULL;
> }
> }
> if ( pMdl )
> {
> // internal code
> CSendCompleteContext* x = 0;
> if( DeleteProc )
> {
> // data will be destroyed in Completion
> // routine
> x = new CSendCompleteContext;
> x->m_Buf = buf;
> x->m_fooDeleteProc = DeleteProc;
> }
> // building
> TdiBuildSend(
> pIrp,
> m_pDeviceObject,
> pClient->m_pEp->m_Object,
> HstdSendComplete, //
> completion routine
> x, // completion context
> pMdl,
> 0, // flags
> len
> );
> // marking
> IoMarkIrpPending(pIrp);
> // calling
> ret = IoCallDriver( m_pDeviceObject, pIrp );
>
> // post-processing
> if ( ret == STATUS_PENDING )
> // make all request synchronous
> {
> ret = STATUS_SUCCESS;
> }
> else
> {
> if(ret != STATUS_SUCCESS)
> {
> dump(“HSTD: IoCallDriver ret = %X\n”, ret );
> return ret;
> }
> }
>
> if(ret != STATUS_SUCCESS)
> {
> dump(“Send failed with status %X\n”, ret );
> }
> }
> else
> {
> IoFreeIrp(pIrp);
> ret = STATUS_INSUFFICIENT_RESOURCES;
> }
> }
>
> return ret;
> }
>
>
>
> >> MSS> Since you return STATUS_MORE_PROCESSING_REQUIRED, you must not
> MSS> do
> >> MSS> this.
> >>
> >> Should I call IoFreeIrp in the completion routine? It seems that
> MSS> system will
> >> call it if I return STATUS_MORE_PROCESSING_REQUIRED.
>
> MSS> No, you must call it yourself.
>
> MSS> Max
>
>
>
> MSS> —
> MSS> You are currently subscribed to ntdev as: kipnis@wp.pl
> MSS> To unsubscribe send a blank email to
> MSS> xxxxx@lists.osr.com
>
>
>
> –
> Best regards,
> Sergey mailto:kipnis@wp.pl
>
>
>
> —
> You are currently subscribed to ntdev as: xxxxx@nryan.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

NR> —
NR> You are currently subscribed to ntdev as: kipnis@wp.pl
NR> To unsubscribe send a blank email to xxxxx@lists.osr.com


Best regards,
Sergey mailto:kipnis@wp.pl