TDI and Vista Problem

hello,

i am working on the TDI driver which will notify about thes ource IP Address to the UserMode app for Each Socket open Request.

i am new to TDI. sorry if i did some mistakes

the driver attaches itself to the TCP-IP by “IoAttachDeviceToDeviceStackSafe”

i filter the IRP_MJ_CREATE request for OpenAddress Request.
when OpenAddress Request gets completed i query for address with the

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

but i am getting 0.0.0.0 in the Address Field.
i googled but could not find any answere. someone in Microsoft news group suggested that i should query after the connection is initiated.

to implement it, i filtered the IRP_MJ_CREATE for OpenConnection reqeust.
in this hadler i set the completion routine and wait for it to complete.

once this is done i tried to query the Address info with the same Macro

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

it fails and returns “STATUS_ADDRESS_NOT_ASSOCIATED”

i looked at the TDI macro and found that there is a mcro called

“TdiBuildAssociateAddress” it needs HANDLE as fourth parameter!!

how do i get HANDLE from File Object?

or am i going in the wrong direction?
i wonder how did it work on XP since i am not doing any this like associating address to the connection. i mean where it gets done in XP then.

i have already post it earlier. but could not find any clues!!

please help!!

regards

You should use packet filtering platformI, rather than TDI, on Vista and above…

Anton Bassov

hello Anton.

thanks for reply.

i saw your post in other news groups too regarding this issue.
you wrote some where that if it is a performce issue then you should look for other alternatives like “WFP” since overhead is present due to the tdx.sys driver wich will forward all request down to the TCPIP.sys.

can’t this be applied to my case. since i am only concerned about the IP of the user logging into the server.

thanks
deep

For TCP you may try to get source address after connection has been
established … For UDP it is kinda hard, usually you really get 0.0.0.0 as
a source address and TDI is a wrong level for this.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello,
>
> i am working on the TDI driver which will notify about thes ource IP
> Address to the UserMode app for Each Socket open Request.
>
> i am new to TDI. sorry if i did some mistakes
>
> the driver attaches itself to the TCP-IP by
> “IoAttachDeviceToDeviceStackSafe”
>
> i filter the IRP_MJ_CREATE request for OpenAddress Request.
> when OpenAddress Request gets completed i query for address with the
>
> TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
> crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);
>
> but i am getting 0.0.0.0 in the Address Field.
> i googled but could not find any answere. someone in Microsoft news group
> suggested that i should query after the connection is initiated.
>
> to implement it, i filtered the IRP_MJ_CREATE for OpenConnection reqeust.
> in this hadler i set the completion routine and wait for it to complete.
>
> once this is done i tried to query the Address info with the same Macro
>
> TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
> crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);
>
> it fails and returns “STATUS_ADDRESS_NOT_ASSOCIATED”
>
> i looked at the TDI macro and found that there is a mcro called
>
> “TdiBuildAssociateAddress” it needs HANDLE as fourth parameter!!
>
> how do i get HANDLE from File Object?
>
> or am i going in the wrong direction?
> i wonder how did it work on XP since i am not doing any this like
> associating address to the connection. i mean where it gets done in XP
> then.
>
> i have already post it earlier. but could not find any clues!!
>
>
> please help!!
>
> regards
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

hello Volodymyr,

thanks for your input,
could you please tell me how should i query the address after connection has been initiated.

i am just clueless how to proceed!!
as in my previous post,
i was trying to set up a completion routine in the OpenConnection request.
when my completion routine gets called i was trying to query the address with

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

this fails and gives me
STATUS_ADDRESS_NOT_ASSOCIATED

how do i associate a address with Open connection request. it needs HANDLE in
TdiBuildAssociateAddress

or i am doing it completely wrong.

could you please some lights as i am really new to TDI?

secondly you mentioned TDI is a wrong level for this. should i consider using WFP if i want UDP support too?

regards
deep

Hello,

could you please tell me how should i query the address after connection
has been initiated.

i am just clueless how to proceed!!
as in my previous post,
i was trying to set up a completion routine in the OpenConnection request.
when my completion routine gets called i was trying to query the address
with

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

this fails and gives me
STATUS_ADDRESS_NOT_ASSOCIATED

If you take a typical sequence of events being taken before connection is
established, the following actions happen:

  1. Address Object A.O. is created via IRP_MJ_CREATE
  2. Connection Object (C.O.) is created via IRP_MJ_CREATE
  3. C.O. is associated with A.O. via IRP_MJ_INTERNAL_DEVICE_CONTROL with
    TDI_ASSOCIATE_ADDRESS
  4. When C.O. and A.O. are associated, and connection is about to be made,
    the TDI_CONNECT is issued

So, it seems like you were trying to get source IP before step 3 finished,
which is wrong. You may request source IP after TDI_CONNECT finished, i.e.,
for example, after completion routine of TDI_CONNECT IRP is called and
before TDI_DISCONNECT is issued for a particular C.O.

secondly you mentioned TDI is a wrong level for this. should i consider
using WFP if i want UDP support too?

My idea here is that, well, UDP stateless protocol, and usually TDI does not
have local address initialized for UDP A.O. (in TDI, the UDP are represented
as A.O.), just because this is not efficient: because one A.O. may be used
to send dg to multiple destinations, and source IP + Port pair might be
different, so, usually UDP source IP + Port is being picked up at NDIS layer
which is lower than TDI.

However :), sometimes if you query source IP for UDP it works, sometime it
does not. Which means (for me, at least), this approach does not work in
general, as there is no 100% garantee you will get real results.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello Volodymyr,
>
> thanks for your input,
> could you please tell me how should i query the address after connection
> has been initiated.
>
> i am just clueless how to proceed!!
> as in my previous post,
> i was trying to set up a completion routine in the OpenConnection request.
> when my completion routine gets called i was trying to query the address
> with
>
> TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
> crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);
>
> this fails and gives me
> STATUS_ADDRESS_NOT_ASSOCIATED
>
> how do i associate a address with Open connection request. it needs
> HANDLE in
> TdiBuildAssociateAddress
>
> or i am doing it completely wrong.
>
> could you please some lights as i am really new to TDI?
>
> secondly you mentioned TDI is a wrong level for this. should i consider
> using WFP if i want UDP support too?
>
>
> regards
> deep
>
>
>
>
>
>
>

You need to understand that in some cases the TDI or Winsock client simply
does not care what the local address is. It is common for an application or
TDI client to pass IPADDR_ANY (0) as the local IP address. The client is
saying “I really don’t care about the local IP address. You (the TCP/IP
driver…) pick the right interface (IP address) for me”.

For UDP on a multi-homed machine each UDP sendto might actually go out on a
different interface. The application doesn’t care which interface as long as
TCP/IP picks one that routes to the destination.

Your filter would like to know the IP address - but no one else cares. That
makes it difficult for you.

Thomas

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-363726-
xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.in
Sent: Wednesday, April 22, 2009 6:39 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] TDI and Vista Problem

hello Volodymyr,

thanks for your input,
could you please tell me how should i query the address after
connection has been initiated.

i am just clueless how to proceed!!
as in my previous post,
i was trying to set up a completion routine in the OpenConnection
request.
when my completion routine gets called i was trying to query the
address with

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

this fails and gives me
STATUS_ADDRESS_NOT_ASSOCIATED

how do i associate a address with Open connection request. it needs
HANDLE in TdiBuildAssociateAddress

or i am doing it completely wrong.

could you please some lights as i am really new to TDI?

secondly you mentioned TDI is a wrong level for this. should i
consider using WFP if i want UDP support too?

regards
deep


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


However :), sometimes if you query source IP for UDP it works, sometime it
does not. Which means (for me, at least), this approach does not work in
general, as there is no 100% garantee you will get real results.

Querying an Address Object for the local address info and receiving 0.0.0.0
is still a correct result. It (INADDR_ANY) means that the transport will
choose a source IP address based on the outbound interface. The Address
Object is thus NOT bound to a local IP address (but likely is bound to a
specific Port in the case of UDP).

Unless one needs to perform some filtering operation on a ‘send’ which is
dependent on the interface, this is not typically an issue. If it is
really necessary to know what IP address is going to get selected then
lookup the best (outbound) interface based on the destination address
information in the TDI_SEND_DATAGRRAM request. The driver will need to have
a copy of the route table and other information to do so, of course. (Or
reverse engineer the IOCTLs from IPHLPAPI.DLL to TCPIP.SYS).

If you search back on this list you will find a (multiple?) discussions
regarding the querying of the local address/port information of a TDI
Connection File Object triggered from the Completion Routine of the
TDI_CONNECT (or TDI_ACCEPT) IRP. If you do not care about ‘inbound’
connections then you can ignore the Connect Event callback on the AO,
otherwise, you need to watch and filter any IRP passed back as an
‘acceptance’ of an inbound connection too.

On NT5 (2K3/XP/2K) the TCPIP.SYS Transport would complete a
TDI_QUERY_ADDRESS_INFO request synchronously and many TDI filters
incorrectly assumed this to always be the case. In NT6 (and in NT5 with
some *other* TDI filters) IoCallDriver() will return STATUS_PENDING. Be
sure to handle the asynchronous case correctly by having a non-threaded IRP
with a Completion Routine to handle the cleanup of the IRP and continuation
of the processing after the address has been queried. Assuming that
IoCallDriver() will return with STATUS_SUCCESS will result in an error.

Good Luck,
Dave Cattley
Consulting Engineer
Systems Software Development

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Volodymyr M.
Shcherbyna
Sent: Wednesday, April 22, 2009 6:49 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] TDI and Vista Problem

Hello,

could you please tell me how should i query the address after connection
has been initiated.

i am just clueless how to proceed!!
as in my previous post,
i was trying to set up a completion routine in the OpenConnection request.
when my completion routine gets called i was trying to query the address
with

TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

this fails and gives me
STATUS_ADDRESS_NOT_ASSOCIATED

If you take a typical sequence of events being taken before connection is
established, the following actions happen:

  1. Address Object A.O. is created via IRP_MJ_CREATE
  2. Connection Object (C.O.) is created via IRP_MJ_CREATE
  3. C.O. is associated with A.O. via IRP_MJ_INTERNAL_DEVICE_CONTROL with
    TDI_ASSOCIATE_ADDRESS
  4. When C.O. and A.O. are associated, and connection is about to be made,
    the TDI_CONNECT is issued

So, it seems like you were trying to get source IP before step 3 finished,
which is wrong. You may request source IP after TDI_CONNECT finished, i.e.,
for example, after completion routine of TDI_CONNECT IRP is called and
before TDI_DISCONNECT is issued for a particular C.O.

secondly you mentioned TDI is a wrong level for this. should i consider
using WFP if i want UDP support too?

My idea here is that, well, UDP stateless protocol, and usually TDI does not

have local address initialized for UDP A.O. (in TDI, the UDP are represented

as A.O.), just because this is not efficient: because one A.O. may be used
to send dg to multiple destinations, and source IP + Port pair might be
different, so, usually UDP source IP + Port is being picked up at NDIS layer

which is lower than TDI.

However :), sometimes if you query source IP for UDP it works, sometime it
does not. Which means (for me, at least), this approach does not work in
general, as there is no 100% garantee you will get real results.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello Volodymyr,
>
> thanks for your input,
> could you please tell me how should i query the address after connection
> has been initiated.
>
> i am just clueless how to proceed!!
> as in my previous post,
> i was trying to set up a completion routine in the OpenConnection request.
> when my completion routine gets called i was trying to query the address
> with
>
> TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
> crQueryAddressInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);
>
> this fails and gives me
> STATUS_ADDRESS_NOT_ASSOCIATED
>
> how do i associate a address with Open connection request. it needs
> HANDLE in
> TdiBuildAssociateAddress
>
> or i am doing it completely wrong.
>
> could you please some lights as i am really new to TDI?
>
> secondly you mentioned TDI is a wrong level for this. should i consider
> using WFP if i want UDP support too?
>
>
> regards
> deep
>
>
>
>
>
>
>


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

hello Volodymyr,

i am very thankful to you for providing me such a valuable info. i just did not know that
it happened like this. surely my lack of knowledge.

i will try as you explained me.

i will filter the TDI_CONNECT IRP and put a CR on it and will wait for it to complete with the
KeWaitForSingleObject()

after this gets completed i will query the Address Information and will let you know the results

regarding the UDP: looks i need to understand more.

Thomas Divine: thanks for more information and clarification!

David R. Cattley:

“” In NT6 (and in NT5 with
some *other* TDI filters) IoCallDriver() will return STATUS_PENDING. Be
sure to handle the asynchronous case correctly by having a non-threaded IRP
with a Completion Routine to handle the cleanup of the IRP and continuation
of the processing after the address has been queried.“”"

if you remember you have already pointed me about this problem and i had fixed that.
thanks for pointing it again!!

i will try to implement it and get back to you all!!

regards
Deep

hello,

i implemented the TDI_CONNECT code. and i did see the IP Address but sometimes later i got a BSOD

NO_MORE_IRP_STACK_LOCATIONS (35)
A higher level driver has attempted to call a lower level driver through
the IoCallDriver() interface, but there are no more stack locations in the
packet, hence, the lower level driver would not be able to access its
parameters, as there are no parameters for it. This is a disasterous
situation, since the higher level driver “thinks” it has filled in the
parameters for the lower level driver (something it MUST do before it calls
it), but since there is no stack location for the latter driver, the former
has written off of the end of the packet. This means that some other memory
has probably been trashed at this point.
Arguments:
Arg1: 8469c008, Address of the IRP
Arg2: 00000000
Arg3: 00000000
Arg4: 00000000

for processing the TDI connect i did like this.

in my dispatch Routine

if (irps->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
if (irps->MinorFunction == TDI_CONNECT )
{
return HandleTDIConnect( irp, cr, ctx);
}
}

in the HandleTDIConnect() function
{
// i allocated a context and build the IRP with the

TdiBuildInternalDeviceControlIrp() macro.

i then setup the completion routine for TDI_CONNECT handler and pass the context.
}

in the completion routine

NTSTATUS crTDIConnect(PDEVICE_OBJECT dev, PIRP irp, PVOID ctx)
{
// with the help of the context i get the IRP that i allocated in the Dispatch routine

//allocate the MDL
mdl = IoAllocateMdl(evt->tai, sizeof(evt->tai), FALSE, FALSE, NULL);
if (!mdl)
goto error;

///build the query information
TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
crQueryADInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);

//call the driver
status = IoCallDriver(dx->dev_lower, evt->qirp);

if (status == STATUS_PENDING )
{
IoCompleteRequest(evt->qirp, IO_NO_INCREMENT);
return CompletionRequest(dev, irp, NULL);

}

in the crQueryADInfo() routine i am returning the STATUS_MORE_PROCESSING_REQUIRED
so that IO manager does not try the complete the IRP.

{

if (irp->MdlAddress)
{
IoFreeMdl(irp->MdlAddress);
irp->MdlAddress = NULL;
}
return STATUS_MORE_PROCESSING_REQUIRED;
}

but sometimes later i got BSOD regarding the STACK_LOCATION

in my dispatch routine i am doing like this for passing the request to the lower lever driver

IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp, cr, ctx, TRUE, TRUE, TRUE);
return IoCallDriver(dx->dev_lower, irp);

could some one please explain me ? here is the stack trace

kd> k
ChildEBP RetAddr
865377fc 818e32d7 nt!RtlpBreakWithStatusInstruction
8653784c 818e3dbd nt!KiBugCheckDebugBreak+0x1c
86537c18 818e3163 nt!KeBugCheck2+0x66d
86537c38 818d201f nt!KeBugCheckEx+0x1e
86537c5c 95f21a3d nt!IofCallDriver+0x30
86537c88 95f218f1 tdidrv!snoopDispatch+0xcd [c:\driver\main.c @ 70]
86537cb8 818d2053 tdidrv!dispatch+0xa1 [c:\driver\main.c @ 142]
86537cd0 88b84e82 nt!IofCallDriver+0x63
86537ce8 88b81642 smb!SmbAsyncConnect+0x15e
86537d1c 88b8166f smb!SmbStartTcpSession+0x23e
86537d30 81a3223b smb!SmbDelayedStartTcpSession+0x21
86537d44 8184e41d nt!IopProcessWorkItem+0x23
86537d7c 819eba1c nt!ExpWorkerThread+0xfd
86537dc0 81844a3e nt!PspSystemThreadStartup+0x9d
00000000 00000000 nt!KiThreadStartup+0x16
kd> !irp 8469c008
Irp is active with 2 stacks 0 is current (= 0x8435b8b8)
No Mdl: No System Buffer: Thread 00000000: Irp stack trace.
cmd flg cl Device File Completion-Context
[f, 3] 0 e0 8435b8b8 846c3400 88b84b44-84692528 Success Error Cancel
\Driver\tdidrv smb!TdiConnectComplete
Args: 00000000 84167250 00000000 00000000
[f, 3] 0 e1 840092f8 846a61b8 95ae8b34-84242188 Success Error Cancel pending
\Driver\Smb mrxsmb!RxTdiAsynchronousConnectCompletion
Args: 00000000 845c75c0 00000000 95af3200
kd> !devstack 840092f8
!DevObj !DrvObj !DevExt ObjectName

840092f8 \Driver\Smb 840093b0 NetbiosSmb
kd> !devstack 8435b8b8
!DevObj !DrvObj !DevExt ObjectName
8435b8b8 \Driver\tdidrv 8435b970
83ff42f0 \Driver\tdx 83ff43a8 Tcp
kd> dt nt!_DEVICE_OBJECT 8435b8b8
+0x000 Type : 3
+0x002 Size : 0xf0
+0x004 ReferenceCount : 0
+0x008 DriverObject : 0x8435bc60 _DRIVER_OBJECT
+0x00c NextDevice : 0x8435bac0 _DEVICE_OBJECT
+0x010 AttachedDevice : (null)
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0x10
+0x020 Characteristics : 0x100
+0x024 Vpb : (null)
+0x028 DeviceExtension : 0x8435b970
+0x02c DeviceType : 0x12
+0x030 StackSize : 2 ‘’
+0x034 Queue :
+0x05c AlignmentRequirement : 0
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : (null)
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 0
+0x0b0 DeviceObjectExtension : 0x8435b9a8 _DEVOBJ_EXTENSION
+0x0b4 Reserved : (null)

regards
Deep

}

This kind of BSOD happens when there is not enought stack locations for IRP.
To avoid this, you have to make sure your TDI filter is loaded after
tcpip.sys and before netbt.sys, as if your filter is loaded after netbt.sys
the IRPs for SMB traffic are finally falling into this situation, the netbt
sends IRP with staklocation count 1, but since there is your driver in
stack, it all blow up. To control drivers load order look here:
http://support.microsoft.com/kb/115486

The second important thing is how do you set your completion routine? If you
look at Microsoft recommendations, the following is the proper order to set
completion routine (let’s assume this is your dispatch routine):

/// you do some calculations

if (b_I_SHOULD_MAKE_CR)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, MyMegaCoolCompletionRoutine,
MyMegaCoolParams, TRUE, TRUE, TRUE);
}
else
{
IoSkipCurrentIrpStackLocation(Irp);
}

/// finally, call next driver in chain

ntStatValue = IoCallDriver(g_pMegaCoolExtension->g_tcpoldobj, Irp);

return ntStatValue;


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello,
>
> i implemented the TDI_CONNECT code. and i did see the IP Address but
> sometimes later i got a BSOD
>
> NO_MORE_IRP_STACK_LOCATIONS (35)
> A higher level driver has attempted to call a lower level driver through
> the IoCallDriver() interface, but there are no more stack locations in the
> packet, hence, the lower level driver would not be able to access its
> parameters, as there are no parameters for it. This is a disasterous
> situation, since the higher level driver “thinks” it has filled in the
> parameters for the lower level driver (something it MUST do before it
> calls
> it), but since there is no stack location for the latter driver, the
> former
> has written off of the end of the packet. This means that some other
> memory
> has probably been trashed at this point.
> Arguments:
> Arg1: 8469c008, Address of the IRP
> Arg2: 00000000
> Arg3: 00000000
> Arg4: 00000000
>
> for processing the TDI connect i did like this.
>
> in my dispatch Routine
>
> if (irps->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
> {
> if (irps->MinorFunction == TDI_CONNECT )
> {
> return HandleTDIConnect( irp, cr, ctx);
> }
> }
>
> in the HandleTDIConnect() function
> {
> // i allocated a context and build the IRP with the
>
> TdiBuildInternalDeviceControlIrp() macro.
>
> i then setup the completion routine for TDI_CONNECT handler and pass the
> context.
> }
>
> in the completion routine
>
> NTSTATUS crTDIConnect(PDEVICE_OBJECT dev, PIRP irp, PVOID ctx)
> {
> // with the help of the context i get the IRP that i allocated in the
> Dispatch routine
>
> //allocate the MDL
> mdl = IoAllocateMdl(evt->tai, sizeof(evt->tai), FALSE, FALSE, NULL);
> if (!mdl)
> goto error;
>
> ///build the query information
> TdiBuildQueryInformation(evt->qirp, dx->dev_lower, irps->FileObject,
> crQueryADInfo, evt, TDI_QUERY_ADDRESS_INFO, mdl);
>
> //call the driver
> status = IoCallDriver(dx->dev_lower, evt->qirp);
>
> if (status == STATUS_PENDING )
> {
> IoCompleteRequest(evt->qirp, IO_NO_INCREMENT);
> return CompletionRequest(dev, irp, NULL);
>
> }
>
>
> in the crQueryADInfo() routine i am returning the
> STATUS_MORE_PROCESSING_REQUIRED
> so that IO manager does not try the complete the IRP.
>
> {
>
> if (irp->MdlAddress)
> {
> IoFreeMdl(irp->MdlAddress);
> irp->MdlAddress = NULL;
> }
> return STATUS_MORE_PROCESSING_REQUIRED;
> }
>
> but sometimes later i got BSOD regarding the STACK_LOCATION
>
> in my dispatch routine i am doing like this for passing the request to the
> lower lever driver
>
> IoCopyCurrentIrpStackLocationToNext(irp);
> IoSetCompletionRoutine(irp, cr, ctx, TRUE, TRUE, TRUE);
> return IoCallDriver(dx->dev_lower, irp);
>
>
> could some one please explain me ? here is the stack trace
>
> kd> k
> ChildEBP RetAddr
> 865377fc 818e32d7 nt!RtlpBreakWithStatusInstruction
> 8653784c 818e3dbd nt!KiBugCheckDebugBreak+0x1c
> 86537c18 818e3163 nt!KeBugCheck2+0x66d
> 86537c38 818d201f nt!KeBugCheckEx+0x1e
> 86537c5c 95f21a3d nt!IofCallDriver+0x30
> 86537c88 95f218f1 tdidrv!snoopDispatch+0xcd [c:\driver\main.c @ 70]
> 86537cb8 818d2053 tdidrv!dispatch+0xa1 [c:\driver\main.c @ 142]
> 86537cd0 88b84e82 nt!IofCallDriver+0x63
> 86537ce8 88b81642 smb!SmbAsyncConnect+0x15e
> 86537d1c 88b8166f smb!SmbStartTcpSession+0x23e
> 86537d30 81a3223b smb!SmbDelayedStartTcpSession+0x21
> 86537d44 8184e41d nt!IopProcessWorkItem+0x23
> 86537d7c 819eba1c nt!ExpWorkerThread+0xfd
> 86537dc0 81844a3e nt!PspSystemThreadStartup+0x9d
> 00000000 00000000 nt!KiThreadStartup+0x16
> kd> !irp 8469c008
> Irp is active with 2 stacks 0 is current (= 0x8435b8b8)
> No Mdl: No System Buffer: Thread 00000000: Irp stack trace.
> cmd flg cl Device File Completion-Context
> [f, 3] 0 e0 8435b8b8 846c3400 88b84b44-84692528 Success Error Cancel
> \Driver\tdidrv smb!TdiConnectComplete
> Args: 00000000 84167250 00000000 00000000
> [f, 3] 0 e1 840092f8 846a61b8 95ae8b34-84242188 Success Error Cancel
> pending
> \Driver\Smb mrxsmb!RxTdiAsynchronousConnectCompletion
> Args: 00000000 845c75c0 00000000 95af3200
> kd> !devstack 840092f8
> !DevObj !DrvObj !DevExt ObjectName
>> 840092f8 \Driver\Smb 840093b0 NetbiosSmb
> kd> !devstack 8435b8b8
> !DevObj !DrvObj !DevExt ObjectName
>> 8435b8b8 \Driver\tdidrv 8435b970
> 83ff42f0 \Driver\tdx 83ff43a8 Tcp
> kd> dt nt!_DEVICE_OBJECT 8435b8b8
> +0x000 Type : 3
> +0x002 Size : 0xf0
> +0x004 ReferenceCount : 0
> +0x008 DriverObject : 0x8435bc60 _DRIVER_OBJECT
> +0x00c NextDevice : 0x8435bac0 _DEVICE_OBJECT
> +0x010 AttachedDevice : (null)
> +0x014 CurrentIrp : (null)
> +0x018 Timer : (null)
> +0x01c Flags : 0x10
> +0x020 Characteristics : 0x100
> +0x024 Vpb : (null)
> +0x028 DeviceExtension : 0x8435b970
> +0x02c DeviceType : 0x12
> +0x030 StackSize : 2 ‘’
> +0x034 Queue :
> +0x05c AlignmentRequirement : 0
> +0x060 DeviceQueue : _KDEVICE_QUEUE
> +0x074 Dpc : _KDPC
> +0x094 ActiveThreadCount : 0
> +0x098 SecurityDescriptor : (null)
> +0x09c DeviceLock : _KEVENT
> +0x0ac SectorSize : 0
> +0x0ae Spare1 : 0
> +0x0b0 DeviceObjectExtension : 0x8435b9a8 _DEVOBJ_EXTENSION
> +0x0b4 Reserved : (null)
>
>
>
> regards
> Deep
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> }
>
>
>
>
>
>
>
>
>

hello Volodymyr,

thanks for the quick response. i will to implement it.
but why was this driver working prior to vista. as i am not doing any change in the load order.

is it because i have added a TDI_CONNECT handler? since the same thing was working for Address open request. just guessing.

i am setting the Completion routine like this in my code!!
// some precessing if i need to set completion routine

if (cr)

{
IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp, cr, ctx, TRUE, TRUE, TRUE);
return IoCallDriver(dx->dev_lower, irp);
}
else
{
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(dx->dev_lower, irp);
}

i googled for it also and found that if we do not have a enough stack location then
we may create a new IRP with enough stack location and pass it down to the lower level driver and in its completion routine complete the original IRP.

is it also a solution besides the change in load order?

regards
deep

Run your driver under driver verifier (verifier.exe) and you will see that
in BSODs everywhere. If it does not, write a stress tool which is doing
manipulations with SMB shares, so that you will be able to repro the issue.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello Volodymyr,
>
> thanks for the quick response. i will to implement it.
> but why was this driver working prior to vista. as i am not doing any
> change in the load order.
>
> is it because i have added a TDI_CONNECT handler? since the same thing was
> working for Address open request. just guessing.
>
> i am setting the Completion routine like this in my code!!
> // some precessing if i need to set completion routine
>
> if (cr)
>
> {
> IoCopyCurrentIrpStackLocationToNext(irp);
> IoSetCompletionRoutine(irp, cr, ctx, TRUE, TRUE, TRUE);
> return IoCallDriver(dx->dev_lower, irp);
> }
> else
> {
> IoSkipCurrentIrpStackLocation(irp);
> return IoCallDriver(dx->dev_lower, irp);
> }
>
> i googled for it also and found that if we do not have a enough stack
> location then
> we may create a new IRP with enough stack location and pass it down to the
> lower level driver and in its completion routine complete the original
> IRP.
>
> is it also a solution besides the change in load order?
>
> regards
> deep
>
>
>
>
>
>
>
>
>
>
>
>
>

If still it does not happen, then I would suggest you to create a small
sample which compiles and output it here (the key word is *small*!, so that
everyone, including me, can take a look at the whole picture, and compile
it. This will speed up the process, believe me.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
“Volodymyr M. Shcherbyna” wrote in message
news:xxxxx@ntdev…
> Run your driver under driver verifier (verifier.exe) and you will see that
> in BSODs everywhere. If it does not, write a stress tool which is doing
> manipulations with SMB shares, so that you will be able to repro the
> issue.
>
> –
> Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
> (This posting is provided “AS IS” with no warranties, and confers no
> rights)
> wrote in message news:xxxxx@ntdev…
>> hello Volodymyr,
>>
>> thanks for the quick response. i will to implement it.
>> but why was this driver working prior to vista. as i am not doing any
>> change in the load order.
>>
>> is it because i have added a TDI_CONNECT handler? since the same thing
>> was working for Address open request. just guessing.
>>
>> i am setting the Completion routine like this in my code!!
>> // some precessing if i need to set completion routine
>>
>> if (cr)
>>
>> {
>> IoCopyCurrentIrpStackLocationToNext(irp);
>> IoSetCompletionRoutine(irp, cr, ctx, TRUE, TRUE, TRUE);
>> return IoCallDriver(dx->dev_lower, irp);
>> }
>> else
>> {
>> IoSkipCurrentIrpStackLocation(irp);
>> return IoCallDriver(dx->dev_lower, irp);
>> }
>>
>> i googled for it also and found that if we do not have a enough stack
>> location then
>> we may create a new IRP with enough stack location and pass it down to
>> the lower level driver and in its completion routine complete the
>> original IRP.
>>
>> is it also a solution besides the change in load order?
>>
>> regards
>> deep
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>
>
>

hello Volodymyr,

i believe you. you must be right. i am porting it to vista+. i do not even know if someone had tested it on 2k3 server. but sure we did not get any BSOD otherwise i must be informed.

as you are much more experienced in it, i trust you i have to test it with driver varifier.
sure i will paste the working code for 2k3 if it does not BSOD.

between: should i go for the allocating a new IRP with enough stack location
or load order will be the safest way?

regards
deep

>but why was this driver working prior to vista. as i am not doing any change in the load order.

Which version of Vista are you using? Despite on fact that TDI is supported in Vista there are some changes in loading TCPIP.sys. Prior Vista SP1 TCPIP loaded as Start=1, but since Vista SP1 this driver has been loaded as Start = 0 or other words as a bootable driver. This situation could affect other stuff which use not only TDI but networking in general.

Igor Sharovar
Hewlett-Packard

hello Igor,

i am testing it in Widows 2008 Server.

yes i do see start type as “0” for it. it is in the group of PNP_TDI.

and as Volodymyr has pointed i need to add a tag value, and need to modify the GroupOrderList Key.
so that it gets loaded before the netbt.sys.

i also saw one more solution for this problem i.e allocating the new IRP in the dispatch routine if stack locations are not enough. but i am not sure, if it will work for me.

regards
deep

Hello,

I forgot to mention this article at OSR:
http://www.osronline.com/article.cfm?article=337 it explains the basics of
what happened. Regarding your question, the sad thing is that Microsoft has
not published any recomendations on what to do in this case in TDI stack.
You should make sure your driver is properly loaded (after tcp, before
netbt), and if you encounter any situations when Irp-(CurrentLocation <= 1)
you:

  1. should skip current location using IoSkipCurrentIrpStackLocation and
    report error so that you will be able to analyze situation in more details

or

  1. allocate another irp with suffucuent stack locations and pass it down;
    after it finishes, you should finish original irp and adjust it’s status.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello Volodymyr,
>
> i believe you. you must be right. i am porting it to vista+. i do not even
> know if someone had tested it on 2k3 server. but sure we did not get any
> BSOD otherwise i must be informed.
>
> as you are much more experienced in it, i trust you i have to test it
> with driver varifier.
> sure i will paste the working code for 2k3 if it does not BSOD.
>
> between: should i go for the allocating a new IRP with enough stack
> location
> or load order will be the safest way?
>
> regards
> deep
>

Basing from the stack trace of your BSOD:

86537c38 818d201f nt!KeBugCheckEx+0x1e
86537c5c 95f21a3d nt!IofCallDriver+0x30
86537c88 95f218f1 tdidrv!snoopDispatch+0xcd [c:\driver\main.c @ 70] ; your
dispatch is called, so IRP stack count should be 2
86537cb8 818d2053 tdidrv!dispatch+0xa1 [c:\driver\main.c @ 142]
86537cd0 88b84e82 nt!IofCallDriver+0x63
86537ce8 88b81642 smb!SmbAsyncConnect+0x15e ; I
bet here the IRP is created with stack count 1
86537d1c 88b8166f smb!SmbStartTcpSession+0x23e
86537d30 81a3223b smb!SmbDelayedStartTcpSession+0x21
86537d44 8184e41d nt!IopProcessWorkItem+0x23
86537d7c 819eba1c nt!ExpWorkerThread+0xfd
86537dc0 81844a3e nt!PspSystemThreadStartup+0x9d
00000000 00000000 nt!KiThreadStartup+0x16

The problem is clearly because netbt is sending IRP to TDI with stack
location count equal to 1, while at has to be at least 2, since your driver
is in the stack. So, adjusting driver load order should solve this problem,
in this case, when netbt.sys loads and attaches to stack, it gets proper
stack count which it uses to send IRPs.


Volodymyr M. Shcherbyna, blog: http://www.shcherbyna.com/
(This posting is provided “AS IS” with no warranties, and confers no
rights)
wrote in message news:xxxxx@ntdev…
> hello Igor,
>
> i am testing it in Widows 2008 Server.
>
> yes i do see start type as “0” for it. it is in the group of PNP_TDI.
>
> and as Volodymyr has pointed i need to add a tag value, and need to modify
> the GroupOrderList Key.
> so that it gets loaded before the netbt.sys.
>
> i also saw one more solution for this problem i.e allocating the new IRP
> in the dispatch routine if stack locations are not enough. but i am not
> sure, if it will work for me.
>
> regards
> deep
>

hello Volodymyr,

i did as you asked me to do. it worked !! after i set the tag values.
thank you very much for you consistent support.

basically i generated the tag value while create the service and then accordingly
modified the GroupOrderList to load my driver right after the tdx.sys NOT after tcpip.sys.
i guess you know it.
thanks to Mr. “Anton bassov” as in some other news group he pointed out that “tcpip” and “udp” names are exported by tdx.sys not by tcpip .sys.

P.S. Although it is working.but is it a good idea that i should set the dependency of netbt.sys to my TDI driver, so that it always gets loaded after my TDI driver!

regards
Deep