wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
阅读:2831回复:12

TDI_LISTEN成功后,为什么不会产生一个新的连接对象

楼主#
更多 发布于:2007-04-12 17:28
  KeInitializeEvent(&event, NotificationEvent, FALSE);
pirp=TdiBuildInternalDeviceControlIrp(TDI_LISTEN,tcpdevice,pconn_point,&event,&iostatus);
TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,0,0,0);
status=IoCallDriver(tcpdevice,pirp);
if(status==STATUS_PENDING)
{
    status=KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, 0);//在这里阻断,直到有连接过来.
}

执行成功后,利用pconn_point就可以跟远程连接点进行通信.

但我有一个疑问,在应用态利用SOCKET编程, 侦听的SOCKET对象一直都处在侦听状态.当有连接过来时,

就会产生一个新的SOCKET对象,利用新产生的SOCKET对象跟客户端进行通信.为什么TDI不产生一个新

的连接对象.如果这样,那接收到一个连接后,不又要重复前面的操作(打开地址,打开连接,建立联系,开始侦

听).

高手能不能解释一下呀,初学TDI
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-04-13 09:24
自己顶
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
板凳#
发布于:2007-04-13 14:29
应该是accept产生新的对象??!!!!!!
走走看看开源好 Solaris vs Linux
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-04-13 16:23
引用第2楼cyliu2007-04-13 14:29发表的“”:
应该是accept产生新的对象??!!!!!!



谢谢版主的回答,修改后的代码如下:
TDI_CONNECTION_INFORMATION in_conn_info,out_conn_info;



    KeInitializeEvent(&event, NotificationEvent, FALSE);
    pirp=TdiBuildInternalDeviceControlIrp(TDI_LISTEN,tcpdevice,pconn_point,&event,&iostatus);
    in_conn_info.UserData=NULL;
    in_conn_info.UserDataLength=0;
    in_conn_info.Options=(PVOID)TDI_QUERY_ACCEPT;
    in_conn_info.OptionsLength=sizeof(ULONG);
    in_conn_info.RemoteAddress=NULL;
    in_conn_info.RemoteAddressLength=0;
    TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,TDI_QUERY_ACCEPT,0,0);
/*
如果将上面一句改成:
TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,TDI_QUERY_ACCEPT,i&n_conn_info,&out_conn_info);
就会蓝屏 错误为0xD1,
*/
    status=IoCallDriver(tcpdevice,pirp);
    if(status==STATUS_PENDING)
    {
        status=KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, 0);
    }
///////////////accept

    KeInitializeEvent(&event, NotificationEvent, FALSE);
    pirp=TdiBuildInternalDeviceControlIrp(TDI_ACCEPT,tcpdevice,pconn_point,&event,&iostatus);
    TdiBuildAccept(pirp,tcpdevice,pconn_point,0,0,0,0);
    status=IoCallDriver(tcpdevice,pirp);
    if(status==STATUS_PENDING)
    {
        status=KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, 0);
    }    


但我不知道那个参数是用于接收新的连接对象的。上面代码可以执行,但发送数据还是用pconn_point.

请版主明示,谢谢!
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
地下室#
发布于:2007-04-16 13:41
TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,TDI_QUERY_ACCEPT,i&n_conn_info,&out_conn_info);倒数第二个参数什么意思?
走走看看开源好 Solaris vs Linux
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-04-16 14:43
引用第4楼cyliu2007-04-16 13:41发表的“”:
TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,TDI_QUERY_ACCEPT,i&n_conn_info,&out_conn_info);倒数第二个参数什么意思?


写错了,应该是:

TdiBuildListen(pirp,tcpdevice,pconn_point,0,0,TDI_QUERY_ACCEPT,&in_conn_info,&out_conn_info);

in_conn_info 用于接收指定的地址连接,如果为NULL,接收所有地址的连接。
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
6楼#
发布于:2007-04-17 10:09
有没有跟踪过TdiBuildListen?

获取新的连接对象应该在完成例程里面获取到。现在我没有办法去验证
走走看看开源好 Solaris vs Linux
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-04-17 10:49
谢谢楼主的热情,完成例程代码如下:

NTSTATUS KSocketComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    PMDL mdl = NULL;
    PMDL nextMdl = NULL;
    PIO_STACK_LOCATION IrpSp;
    IrpSp=IoGetCurrentIrpStackLocation(Irp);
    if (Irp->MdlAddress != NULL)
    {
        for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl)
        {
            nextMdl = mdl->Next;
            MmUnlockPages(mdl);
            IoFreeMdl(mdl);
        }
        Irp->MdlAddress = NULL;
    }
        
    return STATUS_SUCCESS;
}

在完成列程中有可能包含连接的对象只有IrpSp->FileObject,

但我追踪到完成列程中后,发现IrpSp->FileObject的值为0

这个问题搞了好久了,没搞定,希望版主帮我多看看,谢谢了
monkeyy
驱动中牛
驱动中牛
  • 注册日期2001-12-06
  • 最后登录2010-10-10
  • 粉丝0
  • 关注0
  • 积分315分
  • 威望84点
  • 贡献值0点
  • 好评度32点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-04-17 14:35
如果是Listen,对端进行主动连接的流程是:TdiEventConnect被触发,然后Windows系统在TdiEventConnect函数中会打开一个连接对象,并使用TDI_ASSOCIATE_ADDRESS将新创建的连接对象与本地的传输地址相关联,最后创建一个ACCEPT的IRP,并将这个IRP放到TdiEventConnect函数的最后一个参数中。你如果截获了TdiEventConnect函数,那么你就在原始的TdiEventConnect执行完之后,从它传回的ACCEPT IRP中获取连接对象就是了。
听说老虎会吃人,所以从没想过去摸老虎的屁股。:( :(
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-04-20 08:45
谢谢楼上的回答,按照大侠的提示,我试验了好几天,还是没搞定,请大侠指点迷经,现在代码如下:

我注册了ClientEventConnect:
    accepirp=TdiBuildInternalDeviceControlIrp(TDI_ACCEPT,tcpdevice,pconn_point,&event,&iostatus);
    TdiBuildAccept(accepirp,tcpdevice,pconn_point,0,0,0,0);
/////////////////setevevnthandle
    KeInitializeEvent(&event, NotificationEvent, FALSE);
    pirp=TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER,tcpdevice,ptrans_addr,&event,&iostatus);
    TdiBuildSetEventHandler(pirp,tcpdevice,ptrans_addr,0,0,TDI_EVENT_CONNECT,ClientConnectEvent,(PVOID)accepirp);
    status=IoCallDriver(tcpdevice,pirp);
    if(status==STATUS_PENDING)
    {
        status=KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, 0);
    }    

ClientConnectEvent函数如下:

NTSTATUS
  ClientConnectEvent(
    IN PVOID  TdiEventContext,
    IN LONG  RemoteAddressLength,
    IN PVOID  RemoteAddress,
    IN LONG  UserDataLength,
    IN PVOID  UserData,
    IN LONG  OptionsLength,
    IN PVOID  Options,
    OUT CONNECTION_CONTEXT  *ConnectionContext,
    OUT PIRP  *AcceptIrp
    )
{
    
    return STATUS_MORE_PROCESSING_REQUIRED;
}
现在我不知道如何处理ConnectionContext,DDK上的说明如下:

To accept an offered endpoint-to-endpoint connection, ClientEventConnect must set up the buffer at ConnectionContext, together with a TDI_ACCEPT request, and, then, return STATUS_MORE_PROCESSING_REQUIRED. The local-node transport notifies the remote node of the acceptance, transmitting any connect data that its client supplied in the accept IRP, and completes the TDI_ACCEPT request normally.

我不知道TDI_ACCEPT request是什么东东,设置成什么才能接受连接。

2。按大侠的提义,要截获TdiEventConnect,请问如何截获,是不是我第一步做的那样?



请大侠指点,请版主帮忙呀,急死人了
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-04-23 07:08
自己顶一下
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-04-24 14:15
继续顶
wujiabao
驱动牛犊
驱动牛犊
  • 注册日期2006-05-16
  • 最后登录2009-05-08
  • 粉丝0
  • 关注0
  • 积分150分
  • 威望16点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-04-25 10:27
各位老救救我呀
游客

返回顶部