TDI (传输驱动接口 Transport Driver Interface) 详细分析

TDI (传输驱动接口 Transport Driver Interface) 详细分析

目录

  1. 概述
  2. 整体架构
  3. [TDI 文件对象模型](#TDI 文件对象模型)
  4. [TDI 数据结构](#TDI 数据结构)
  5. [TDI 操作 (Request Codes)](#TDI 操作 (Request Codes))
  6. [TDI 事件模型](#TDI 事件模型)
  7. [TDI IRP 构建机制 (TdiBuild*)](#TDI IRP 构建机制 (TdiBuild*))
  8. [tdihelpers 库](#tdihelpers 库)
  9. [TDI 信息查询](#TDI 信息查询)
  10. 工作流程图
  11. 数据流图
  12. 关键定义索引

1. 概述

TDI (Transport Driver Interface,传输驱动接口) 是 Windows 定义的内核态网络接口标准,位于内核的网络客户端(如 AFD.sys、NetBIOS)与传输驱动(如 tcpip.sys)之间。它定义了传输层驱动必须实现的统一接口,使上层的网络客户端无需关心底层使用的是 TCP/IP、IPX 还是其他协议。

ReactOS 的 TDI 定义位于 d:\reactos\sdk\include\ddk\tdikrnl.h(内核模式)和 d:\reactos\sdk\include\psdk\tdi.h(用户模式)。

1.1 架构定位

复制代码
┌─────────────────────────────────────────────┐
│ 内核态网络客户端 (TDI Clients)               │
│  ├─ AFD.sys (Winsock 内核实现)              │
│  ├─ NetBIOS 驱动                             │
│  └─ 其他 TDI 客户端                          │
└──────────────────┬──────────────────────────┘
                   │ TDI 调用 (IRP_MJ_INTERNAL_DEVICE_CONTROL)
                   │ TdiBuild* 宏构建 IRP → IoCallDriver
┌──────────────────▼──────────────────────────┐
│ TDI 层 ← ★ 本文分析对象                      │
│                                             │
│  文件对象 (File Object)                     │
│   ├─ 地址文件 (TransportAddress)            │
│   ├─ 连接端点 (ConnectionContext)           │
│   └─ 控制通道 (ControlChannel)              │
│                                             │
│  操作 (MinorFunction)                       │
│   ├─ TDI_CONNECT / TDI_LISTEN / TDI_ACCEPT │
│   ├─ TDI_SEND / TDI_RECEIVE                │
│   ├─ TDI_SEND_DATAGRAM / TDI_RECEIVE_DATAGRAM
│   ├─ TDI_SET_EVENT_HANDLER                  │
│   └─ TDI_QUERY/SET_INFORMATION              │
│                                             │
│  事件回调 (Event Handlers)                  │
│   ├─ TDI_EVENT_CONNECT / DISCONNECT         │
│   ├─ TDI_EVENT_RECEIVE / RECEIVE_DATAGRAM   │
│   └─ TDI_EVENT_ERROR / SEND_POSSIBLE        │
└──────────────────┬──────────────────────────┘
                   │ TDI 操作由传输驱动处理
┌──────────────────▼──────────────────────────┐
│ 传输驱动 (TDI Providers)                    │
│  └─ tcpip.sys (TCP/UDP/IP)                 │
└──────────────────┬──────────────────────────┘
                   │ NDIS
                   ▼
            ndis.sys → 网卡驱动

1.2 TDI 的本质

TDI 不是 一个独立的模块或 DLL,而是一组接口规范,通过以下方式实现:

  1. 头文件定义tdikrnl.h 定义请求结构、宏和事件回调原型
  2. 文件对象语义 :传输驱动通过 \Device\Tcp 等设备对象暴露,客户端用 ZwCreateFile 打开
  3. IRP 分发 :TDI 操作通过 IRP_MJ_INTERNAL_DEVICE_CONTROLMinorFunction 字段区分
  4. 事件回调:客户端注册事件处理器,传输驱动在数据到达时回调

1.3 与 NDIS 的区别

维度 TDI NDIS
位置 传输层与网络客户端之间 协议栈与网卡驱动之间
使用者 AFD.sys、NetBIOS 等 tcpip.sys 自身
数据单元 TSDU (传输服务数据单元) 帧/包
对象 文件对象 (地址/连接/控制) 适配器/协议绑定
IRP 类型 IRP_MJ_INTERNAL_DEVICE_CONTROL 无直接 IRP 接口
事件 TDI_EVENT_* 回调 NDIS Status 回调

2. 整体架构

2.1 TDI 客户端与服务提供者

复制代码
TDI 客户端 (Client)                    TDI 提供者 (Provider)
┌──────────────┐                     ┌──────────────┐
│ AFD.sys      │─── TDI 请求 ────────▶│ tcpip.sys    │
│              │                      │              │
│ 1. 打开文件  │── ZwCreateFile ─────▶│ \Device\Tcp  │
│ 2. 设置事件  │── TDI_SET_EVENT_HANDLER ─▶│ 注册回调 │
│ 3. 发起操作  │── TDI_CONNECT 等 ───▶│ 处理请求     │
│ 4. 接收通知  │◀── 事件回调 ─────────│ 数据到达     │
└──────────────┘                     └──────────────┘

2.2 头文件层次

头文件 位置 内容
tdikrnl.h sdk/include/ddk/tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h) 内核模式 TDI 定义(请求结构、TdiBuild 宏、事件原型)
tdi.h sdk/include/psdk/tdi.h(file:///d:/reactos/sdk/include/psdk/tdi.h) 用户模式 TDI 定义(TDI_REQUEST、连接信息、地址结构)
tdistat.h sdk/include/ddk/tdistat.h(file:///d:/reactos/sdk/include/ddk/tdistat.h) TDI 状态码
tdiinfo.h sdk/include/psdk/tdiinfo.h(file:///d:/reactos/sdk/include/psdk/tdiinfo.h) TDI 信息类定义
ntddtdi.h sdk/include/psdk/ntddtdi.h(file:///d:/reactos/sdk/include/psdk/ntddtdi.h) TDI IOCTL 定义

2.3 tdihelpers 库

ReactOS 提供了一个 tdihelpers 辅助库(d:\reactos\drivers\network\tdihelpers\),封装了 TDI 的常用操作,被 AFD.sys 和 NETIO 使用:

复制代码
tdihelpers/
├── tdi.c          # TdiOpenDevice/TdiOpenAddressFile/TdiOpenConnectionEndpointFile
│                  # TdiAssociateAddressFile/TdiDisassociateAddressFile
│                  # TdiListen/TdiAccept/TdiSetEventHandler/TdiQueryDeviceControl
├── tdiconn.c      # TdiConnect/TdiBuildConnectionInfo 等连接辅助
└── include/
    ├── tdi.h      # tdihelpers 头文件
    └── tdiconn.h  # 连接辅助声明

3. TDI 文件对象模型

TDI 定义了三种文件对象,通过 ZwCreateFile 在传输设备的命名空间下创建。

3.1 文件对象类型

类型 FsContext2 值 创建方式 (EA) 用途
地址文件 TDI_TRANSPORT_ADDRESS_FILE (1) CREATE + TransportAddress EA 绑定本地地址,用于无连接通信
连接端点 TDI_CONNECTION_FILE (2) CREATE + ConnectionContext EA 面向连接通信(TCP)
控制通道 TDI_CONTROL_CHANNEL_FILE (3) CREATE(无 EA) 管理/信息查询
c 复制代码
#define TdiTransportAddress  "TransportAddress"
#define TdiConnectionContext "ConnectionContext"
#define TDI_TRANSPORT_ADDRESS_LENGTH  (sizeof(TdiTransportAddress) - 1)
#define TDI_CONNECTION_CONTEXT_LENGTH (sizeof(TdiConnectionContext) - 1)

3.2 地址文件创建 (带 EA)

客户端通过 FILE_FULL_EA_INFORMATION 传递 EA 参数:

复制代码
ZwCreateFile(..., EaBuffer)
   │
   ▼
EaBuffer:
┌─────────────────────────────────────────────┐
│ FILE_FULL_EA_INFORMATION                    │
│   EaNameLength = 17 ("TransportAddress")    │
│   EaName       = "TransportAddress"         │
│   EaValueLength = sizeof(TA_IP_ADDRESS)     │
├─────────────────────────────────────────────┤
│ TA_IP_ADDRESS (EA 值)                       │
│   TAAddressCount = 1                        │
│   Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP
│   Address[0].AddressType   = TDI_ADDRESS_TYPE_IP
│   Address[0].Address[0]    = { sin_port, in_addr, sin_zero }
└─────────────────────────────────────────────┘

3.3 连接端点创建 (带 EA)

复制代码
ZwCreateFile(..., EaBuffer)
   │
   ▼
EaBuffer:
┌─────────────────────────────────────────────┐
│ FILE_FULL_EA_INFORMATION                    │
│   EaNameLength = 16 ("ConnectionContext")   │
│   EaName       = "ConnectionContext"        │
│   EaValueLength = sizeof(PVOID)             │
├─────────────────────────────────────────────┤
│ PVOID ContextArea (连接上下文指针)           │
└─────────────────────────────────────────────┘

3.4 文件对象的关系

复制代码
                    ┌──────────────────────┐
                    │  传输设备对象          │
                    │  \Device\Tcp          │
                    └──────────┬───────────┘
                               │
                 ┌─────────────┼─────────────┐
                 │             │             │
          ┌──────▼─────┐ ┌─────▼──────┐ ┌────▼────────┐
          │ 地址文件     │ │ 连接端点    │ │ 控制通道     │
          │ (AddressFile)│ │ (Connection)│ │ (Control)   │
          └──────┬─────┘ └─────┬──────┘ └─────────────┘
                 │             │
                 │  TDI_ASSOCIATE_ADDRESS
                 │  (通过 AddressHandle 关联)
                 └────────────►

关联操作 :连接端点创建后,必须通过 TDI_ASSOCIATE_ADDRESS 操作关联一个地址文件,才能发起连接。


4. TDI 数据结构

4.1 TDI_CONNECTION_INFORMATION --- 连接信息

定义在 tdi.h(file:///d:/reactos/sdk/include/psdk/tdi.h#L39-L46):

c 复制代码
typedef struct _TDI_CONNECTION_INFORMATION {
  LONG  UserDataLength;       // 用户数据长度 (连接时传递)
  PVOID UserData;             // 用户数据指针
  LONG  OptionsLength;        // 选项长度
  PVOID Options;              // 选项指针
  LONG  RemoteAddressLength;  // 远端地址长度
  PVOID RemoteAddress;        // 远端地址 (TRANSPORT_ADDRESS)
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;

用于 TDI_CONNECTTDI_LISTENTDI_ACCEPTTDI_SEND_DATAGRAM 等操作。

4.2 TRANSPORT_ADDRESS --- 传输地址

c 复制代码
typedef struct _TRANSPORT_ADDRESS {
  LONG  TAAddressCount;       // 地址个数
  TA_ADDRESS  Address[1];     // 地址数组
} TRANSPORT_ADDRESS, *PTRANSPORT_ADDRESS;

typedef struct _TA_ADDRESS {
  USHORT  AddressLength;      // 地址长度
  USHORT  AddressType;        // 地址类型 (TDI_ADDRESS_TYPE_*)
  UCHAR  Address[1];          // 地址数据
} TA_ADDRESS, *PTA_ADDRESS;

4.3 TDI_ADDRESS_IP --- IPv4 地址

c 复制代码
typedef struct _TDI_ADDRESS_IP {
  USHORT  sin_port;           // 端口 (网络字节序)
  ULONG  in_addr;             // IP 地址 (网络字节序)
  UCHAR  sin_zero[8];         // 填充
} TDI_ADDRESS_IP, *PTDI_ADDRESS_IP;

IPv4 地址组合(TA_IP_ADDRESS):

c 复制代码
typedef struct _TA_IP_ADDRESS {
  LONG  TAAddressCount;       // = 1
  struct {
    USHORT AddressLength;     // = sizeof(TDI_ADDRESS_IP) = 14
    USHORT AddressType;       // = TDI_ADDRESS_TYPE_IP = 2
    TDI_ADDRESS_IP Address[1]; // 实际 IP 地址
  } Address[1];
} TA_IP_ADDRESS, *PTA_IP_ADDRESS;

4.4 地址类型常量

c 复制代码
#define TDI_ADDRESS_TYPE_UNSPEC     0    // 未指定
#define TDI_ADDRESS_TYPE_IP         2    // IPv4
#define TDI_ADDRESS_TYPE_IPX        6    // IPX
#define TDI_ADDRESS_TYPE_NETBIOS    17   // NetBIOS
#define TDI_ADDRESS_TYPE_IP6        23   // IPv6
#define TDI_ADDRESS_TYPE_NETBIOS_EX 22   // NetBIOS 扩展

4.5 TDI_REQUEST --- 请求基结构 (用户模式)

c 复制代码
typedef struct _TDI_REQUEST {
  union {
    HANDLE  AddressHandle;          // 地址文件句柄
    CONNECTION_CONTEXT  ConnectionContext;  // 连接上下文
    HANDLE  ControlChannel;         // 控制通道
  } Handle;
  PVOID  RequestNotifyObject;       // 完成通知对象
  PVOID  RequestContext;            // 请求上下文
  TDI_STATUS  TdiStatus;            // 状态
} TDI_REQUEST, *PTDI_REQUEST;

4.6 TDI_REQUEST_KERNEL --- 内核请求基结构

定义在 tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h#L39-L44):

c 复制代码
typedef struct _TDI_REQUEST_KERNEL {
  ULONG RequestFlags;                        // 请求标志
  PTDI_CONNECTION_INFORMATION RequestConnectionInformation;  // 请求连接信息
  PTDI_CONNECTION_INFORMATION ReturnConnectionInformation;   // 返回连接信息
  PVOID RequestSpecific;                     // 请求特定参数 (如超时)
} TDI_REQUEST_KERNEL, *PTDI_REQUEST_KERNEL;

4.7 各类请求的参数结构

请求 结构 附加参数
TDI_ASSOCIATE_ADDRESS TDI_REQUEST_KERNEL_ASSOCIATE AddressHandle
TDI_CONNECT TDI_REQUEST_KERNEL RequestSpecific = 超时指针
TDI_LISTEN TDI_REQUEST_KERNEL RequestFlags
TDI_ACCEPT TDI_REQUEST_KERNEL_ACCEPT Request/Return ConnectionInfo
TDI_DISCONNECT TDI_REQUEST_KERNEL RequestFlags + RequestSpecific(超时)
TDI_SEND TDI_REQUEST_KERNEL_SEND SendLength + SendFlags
TDI_RECEIVE TDI_REQUEST_KERNEL_RECEIVE ReceiveLength + ReceiveFlags
TDI_SEND_DATAGRAM TDI_REQUEST_KERNEL_SENDDG SendLength + SendDatagramInformation
TDI_RECEIVE_DATAGRAM TDI_REQUEST_KERNEL_RECEIVEDG ReceiveLength + DatagramInfo + Flags
TDI_SET_EVENT_HANDLER TDI_REQUEST_KERNEL_SET_EVENT EventType + EventHandler + EventContext
TDI_QUERY_INFORMATION TDI_REQUEST_KERNEL_QUERY_INFORMATION QueryType
TDI_SET_INFORMATION TDI_REQUEST_KERNEL_SET_INFORMATION SetType

5. TDI 操作 (Request Codes)

5.1 操作码定义

定义在 tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h#L47-L63):

c 复制代码
/* Request codes */
#define TDI_ASSOCIATE_ADDRESS             0x01   // 关联地址文件
#define TDI_DISASSOCIATE_ADDRESS          0x02   // 解除地址关联
#define TDI_CONNECT                       0x03   // 连接
#define TDI_LISTEN                        0x04   // 监听
#define TDI_ACCEPT                        0x05   // 接受
#define TDI_DISCONNECT                    0x06   // 断开
#define TDI_SEND                          0x07   // 发送
#define TDI_RECEIVE                       0x08   // 接收
#define TDI_SEND_DATAGRAM                 0x09   // 发送数据报
#define TDI_RECEIVE_DATAGRAM              0x0A   // 接收数据报
#define TDI_SET_EVENT_HANDLER             0x0B   // 设置事件处理器
#define TDI_QUERY_INFORMATION             0x0C   // 查询信息
#define TDI_SET_INFORMATION               0x0D   // 设置信息
#define TDI_ACTION                        0x0E   // 动作

/* Direct-call operations */
#define TDI_DIRECT_SEND                   0x27   // 直接发送 (快速路径)
#define TDI_DIRECT_SEND_DATAGRAM          0x29   // 直接发送数据报

5.2 IRP 结构

TDI 操作以 IRP_MJ_INTERNAL_DEVICE_CONTROL IRP 发送,MinorFunction 字段存放操作码:

复制代码
IRP
├── MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL
├── MinorFunction = TDI_CONNECT (0x03) 等
├── Parameters (union)
│   ├── TDI_REQUEST_KERNEL (通过 _IrpSp->Parameters 访问)
│   │   ├── RequestFlags
│   │   ├── RequestConnectionInformation
│   │   ├── ReturnConnectionInformation
│   │   └── RequestSpecific
│   └── 各请求特有参数
├── MdlAddress (数据缓冲, 用于 SEND/RECEIVE)
├── FileObject (目标文件对象: 连接端点/地址文件)
└── DeviceObject (传输设备对象)

5.3 各操作语义

TDI_CONNECT (0x03)
复制代码
客户端 → 传输驱动:
  RequestConnectionInformation->RemoteAddress = 远端地址 (TRANSPORT_ADDRESS)
  RequestSpecific = 超时 (LARGE_INTEGER*)
传输驱动 → 客户端:
  成功: ReturnConnectionInformation->RemoteAddress 填实际连接地址
  状态: STATUS_SUCCESS / STATUS_PENDING (异步)
TDI_LISTEN (0x04)
复制代码
客户端 → 传输驱动:
  RequestFlags = TDI_QUERY_ACCEPT (表示查询可接受的连接)
  RequestConnectionInformation = 监听限制信息
传输驱动 → 客户端:
  新连接到达时: 通过 TDI_EVENT_CONNECT 事件通知
  完成: ReturnConnectionInformation 包含连接信息
TDI_SEND (0x07)
复制代码
客户端 → 传输驱动:
  SendLength = 发送字节数
  SendFlags  = TDI_SEND_EXPEDITED / TDI_SEND_PARTIAL / TDI_SEND_NON_BLOCKING
  Irp->MdlAddress = 数据缓冲 (MDL 链)
传输驱动 → 客户端:
  IOSB.Information = 实际发送字节数

发送标志

c 复制代码
#define TDI_SEND_EXPEDITED            0x0020   // 紧急数据 (MSG_OOB)
#define TDI_SEND_PARTIAL              0x0040   // 部分发送
#define TDI_SEND_NO_RESPONSE_EXPECTED 0x0080   // 无需响应
#define TDI_SEND_NON_BLOCKING         0x0100   // 非阻塞
#define TDI_SEND_AND_DISCONNECT       0x0200   // 发送后断开
TDI_RECEIVE (0x08)
复制代码
客户端 → 传输驱动:
  ReceiveLength = 接收缓冲长度
  ReceiveFlags  = TDI_RECEIVE_NORMAL / PEEK / EXPEDITED 等
  Irp->MdlAddress = 接收缓冲 (MDL)
传输驱动 → 客户端:
  IOSB.Information = 实际接收字节数

接收标志

c 复制代码
#define TDI_RECEIVE_BROADCAST        0x00000004  // 广播
#define TDI_RECEIVE_MULTICAST        0x00000008  // 多播
#define TDI_RECEIVE_PARTIAL          0x00000010  // 部分接收
#define TDI_RECEIVE_NORMAL           0x00000020  // 正常
#define TDI_RECEIVE_EXPEDITED        0x00000040  // 紧急
#define TDI_RECEIVE_PEEK             0x00000080  // 偷看 (不移除)
#define TDI_RECEIVE_COPY_LOOKAHEAD   0x00000200  // 复制前瞻数据
#define TDI_RECEIVE_ENTIRE_MESSAGE   0x00000400  // 完整消息
TDI_DISCONNECT (0x06)
c 复制代码
#define TDI_DISCONNECT_WAIT          0x0001   // 等待完成
#define TDI_DISCONNECT_ABORT         0x0002   // 立即中止 (RST)
#define TDI_DISCONNECT_RELEASE       0x0004   // 释放
TDI_SET_EVENT_HANDLER (0x0B)
复制代码
客户端 → 传输驱动:
  EventType    = TDI_EVENT_* 事件类型
  EventHandler = 回调函数指针
  EventContext = 回调上下文 (通常是客户端对象指针)
传输驱动:
  保存回调, 事件发生时调用 EventHandler(EventContext, ...)
  传 NULL Handler 表示注销事件处理器

6. TDI 事件模型

6.1 事件类型

定义在 tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h#L146-L156):

c 复制代码
#define TDI_EVENT_CONNECT                   0    // 连接请求到达 (监听 socket)
#define TDI_EVENT_DISCONNECT                1    // 连接断开
#define TDI_EVENT_ERROR                     2    // 错误
#define TDI_EVENT_RECEIVE                   3    // 数据到达
#define TDI_EVENT_RECEIVE_DATAGRAM          4    // 数据报到达
#define TDI_EVENT_RECEIVE_EXPEDITED         5    // 紧急数据到达
#define TDI_EVENT_SEND_POSSIBLE             6    // 可以发送
#define TDI_EVENT_CHAINED_RECEIVE           7    // 链式接收 (MDL 直接)
#define TDI_EVENT_CHAINED_RECEIVE_DATAGRAM  8    // 链式数据报接收
#define TDI_EVENT_CHAINED_RECEIVE_EXPEDITED 9    // 链式紧急接收
#define TDI_EVENT_ERROR_EX                  10   // 扩展错误

6.2 事件回调原型

PTDI_IND_RECEIVE --- 数据到达
c 复制代码
typedef NTSTATUS (NTAPI *PTDI_IND_RECEIVE)(
    _In_opt_ PVOID TdiEventContext,      // 注册时的上下文 (如 AFD_FCB)
    _In_opt_ CONNECTION_CONTEXT ConnectionContext,
    _In_ ULONG ReceiveFlags,             // TDI_RECEIVE_* 标志
    _In_ ULONG BytesIndicated,           // 当前指示的字节数
    _In_ ULONG BytesAvailable,           // 总可用字节数
    _Out_ ULONG *BytesTaken,             // 客户端取走的字节数
    _In_ PVOID Tsdu,                     // 数据指针
    _Out_opt_ PIRP *IoRequestPacket);    // 可选: 客户端提供的接收 IRP
PTDI_IND_CONNECT --- 连接请求
c 复制代码
typedef NTSTATUS (NTAPI *PTDI_IND_CONNECT)(
    _In_opt_ 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);              // 输出接受 IRP
PTDI_IND_DISCONNECT --- 断开
c 复制代码
typedef NTSTATUS (NTAPI *PTDI_IND_DISCONNECT)(
    _In_opt_ PVOID TdiEventContext,
    _In_opt_ CONNECTION_CONTEXT ConnectionContext,
    _In_ LONG DisconnectDataLength,
    _In_ PVOID DisconnectData,
    _In_ LONG DisconnectInformationLength,
    _In_ PVOID DisconnectInformation,
    _In_ ULONG DisconnectFlags);         // TDI_DISCONNECT_*

6.3 事件处理流程(数据到达为例)

复制代码
传输驱动 (tcpip.sys)
  │
  │ 收到数据 → 查找连接端点的事件处理器
  ▼
调用 TDI_EVENT_RECEIVE 处理器
  │
  ├─ 客户端在回调中:
  │     ├─ 复制 Tsdu 数据到自己的缓冲
  │     ├─ 设置 *BytesTaken = 实际取走的字节数
  │     └─ 返回 STATUS_SUCCESS
  │
  ├─ 返回 STATUS_MORE_PROCESSING_REQUIRED 表示保留数据
  │
  └─ 客户端可以选择提供 IoRequestPacket (自己的接收 IRP)
        └─ 传输驱动用该 IRP 完成剩余数据的传输

6.4 默认处理器

tdikrnl.h 导出了默认事件处理器(供客户端继承后调用):

默认处理器 对应事件
TdiDefaultConnectHandler TDI_EVENT_CONNECT
TdiDefaultDisconnectHandler TDI_EVENT_DISCONNECT
TdiDefaultErrorHandler TDI_EVENT_ERROR
TdiDefaultReceiveHandler TDI_EVENT_RECEIVE
TdiDefaultRcvDatagramHandler TDI_EVENT_RECEIVE_DATAGRAM
TdiDefaultRcvExpeditedHandler TDI_EVENT_RECEIVE_EXPEDITED
TdiDefaultChainedReceiveHandler TDI_EVENT_CHAINED_RECEIVE
TdiDefaultChainedRcvDatagramHandler TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
TdiDefaultChainedRcvExpeditedHandler TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
TdiDefaultSendPossibleHandler TDI_EVENT_SEND_POSSIBLE

7. TDI IRP 构建机制 (TdiBuild*)

7.1 TdiBuildBaseIrp --- 基础构建宏

定义在 tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h#L391-L404):

c 复制代码
#define TdiBuildBaseIrp(bIrp, bDevObj, bFileObj, bCompRoutine, bContxt, bIrpSp, bMinor) \
{                                                                         \
  bIrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;                 \
  bIrpSp->MinorFunction = (bMinor);                                       \
  bIrpSp->DeviceObject  = (bDevObj);                                      \
  bIrpSp->FileObject    = (bFileObj);                                     \
  if (bCompRoutine)                                                       \
    IoSetCompletionRoutine(bIrp, bCompRoutine, bContxt, TRUE, TRUE, TRUE);\
  else                                                                    \
    IoSetCompletionRoutine(bIrp, NULL, NULL, FALSE, FALSE, FALSE);        \
}

7.2 TdiBuildInternalDeviceControlIrp --- 分配 IRP

c 复制代码
#define TdiBuildInternalDeviceControlIrp(IrpSubFunction, DeviceObject,   \
  FileObject, Event, IoStatusBlock)                                      \
  IoBuildDeviceIoControlRequest(                                         \
        IrpSubFunction,      // 传给 IoControlCode → 实际作为 MinorFunction
        DeviceObject,        // 目标设备
        NULL, 0, NULL, 0,    // 无输入输出缓冲
        TRUE,                // InternalDeviceIoControl = TRUE
        Event,               // 完成事件
        IoStatusBlock)       // IO 状态块

7.3 各操作构建宏汇总

功能
TdiBuildAccept 构建 TDI_ACCEPT 请求
TdiBuildAction 构建 TDI_ACTION 请求
TdiBuildAssociateAddress 构建 TDI_ASSOCIATE_ADDRESS
TdiBuildConnect 构建 TDI_CONNECT
TdiBuildDisassociateAddress 构建 TDI_DISASSOCIATE_ADDRESS
TdiBuildDisconnect 构建 TDI_DISCONNECT
TdiBuildListen 构建 TDI_LISTEN
TdiBuildQueryInformation 构建 TDI_QUERY_INFORMATION
TdiBuildReceive 构建 TDI_RECEIVE
TdiBuildReceiveDatagram 构建 TDI_RECEIVE_DATAGRAM
TdiBuildSend 构建 TDI_SEND
TdiBuildSendDatagram 构建 TDI_SEND_DATAGRAM
TdiBuildSetEventHandler 构建 TDI_SET_EVENT_HANDLER
TdiBuildSetInformation 构建 TDI_SET_INFORMATION

7.4 TdiBuildSend 示例

c 复制代码
#define TdiBuildSend(Irp, DevObj, FileObj, CompRoutine, Contxt,        \
                     MdlAddr, InFlags, SendLen)                        \
{                                                                      \
  PTDI_REQUEST_KERNEL_SEND _Request;                                   \
  PIO_STACK_LOCATION _IrpSp;                                           \
                                                                       \
  _IrpSp = IoGetNextIrpStackLocation(Irp);                             \
  TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine,                   \
                  Contxt, _IrpSp, TDI_SEND);                           \
  _Request = (PTDI_REQUEST_KERNEL_SEND)&_IrpSp->Parameters;            \
  _Request->SendFlags  = (InFlags);                                    \
  _Request->SendLength = (SendLen);                                    \
  (Irp)->MdlAddress    = (MdlAddr);   /* 数据缓冲 MDL */               \
}

7.5 TdiCompleteRequest --- 完成 TDI 请求

c 复制代码
#define TdiCompleteRequest(Irp, Status)           \
{                                                 \
  (Irp)->IoStatus.Status = (Status);              \
  IoCompleteRequest((Irp), IO_NETWORK_INCREMENT); \
}

7.6 数据复制辅助

c 复制代码
TdiCopyBufferToMdl(...)        // 缓冲区 → MDL 链
TdiCopyMdlToBuffer(...)        // MDL 链 → 缓冲区
TdiCopyMdlChainToMdlChain(...) // MDL 链 → MDL 链
TdiCopyLookaheadData(...)      // 前瞻数据复制 (= RtlCopyMemory)
TdiMapBuffer(...) / TdiUnmapBuffer(...)  // MDL 映射

8. tdihelpers 库

ReactOS 的 tdihelpers 库封装了 TDI 操作,供 AFD.sys 使用。

8.1 TdiCall --- 调用传输驱动

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L26-L65):

复制代码
TdiCall(Irp, DeviceObject, Event, Iosb)
   │
   ├─ IoCallDriver(DeviceObject, Irp)
   │     └─ 传输驱动的 MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]
   │
   ├─ STATUS_PENDING 且 Event != NULL:
   │     └─ KeWaitForSingleObject(Event)   // 同步等待
   │           └─ 完成后读取 Iosb->Status
   │
   └─ 返回最终状态

8.2 TdiOpenDevice --- 打开设备

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L68-L146):

复制代码
TdiOpenDevice(DeviceName, EaLength, EaInfo, ShareType, Handle, Object)
   │
   ├─ InitializeObjectAttributes(DeviceName)
   ├─ ZwCreateFile(Handle, GENERIC_READ|WRITE|SYNCHRONIZE,
   │               &Attr, &Iosb, 0, FILE_ATTRIBUTE_NORMAL,
   │               ShareAccess, FILE_OPEN_IF, 0, EaInfo, EaLength)
   ├─ ObReferenceObjectByHandle(*Handle, ..., *IoFileObjectType,
   │                            ..., (PVOID*)Object)
   └─ 返回句柄 + 文件对象指针

8.3 TdiOpenAddressFile --- 打开地址文件

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L148-L201):

复制代码
TdiOpenAddressFile(DeviceName, Name, ShareType, AddressHandle, AddressObject)
   │
   ├─ 构造 EA:
   │     EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH
   │     EaName       = "TransportAddress"
   │     EaValueLength = sizeof(TA_IP_ADDRESS)
   │     EaValue      = Name (TA_IP_ADDRESS)
   │
   ├─ TdiOpenDevice(DeviceName, EaLength, EaInfo, ShareType, ...)
   │
   └─ 返回地址文件句柄 + 对象

8.4 TdiOpenConnectionEndpointFile --- 打开连接端点

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L258-L308):

复制代码
TdiOpenConnectionEndpointFile(DeviceName, ConnectionHandle, ConnectionObject)
   │
   ├─ 构造 EA:
   │     EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH
   │     EaName       = "ConnectionContext"
   │     EaValueLength = sizeof(PVOID)
   │     EaValue      = ContextArea (上下文指针)
   │
   ├─ TdiOpenDevice(DeviceName, ..., AFD_SHARE_UNIQUE, ...)
   │
   └─ 返回连接端点句柄 + 对象

8.5 TdiAssociateAddressFile --- 关联地址

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L370-L411):

复制代码
TdiAssociateAddressFile(AddressHandle, ConnectionObject)
   │
   ├─ TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, ...)
   ├─ TdiBuildAssociateAddress(Irp, DevObj, ConnObj, NULL, NULL, AddressHandle)
   └─ TdiCall(Irp, DeviceObject, &Event, &Iosb)

8.6 TdiConnect --- 连接

实现在 tdiconn.c(file:///d:/reactos/drivers/network/tdihelpers/tdiconn.c) 和 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L311-L380):

复制代码
TdiConnect(Irp, ConnectionObject, ConnectionCallInfo, ConnectionReturnInfo,
           CompletionRoutine, CompletionContext)
   │
   ├─ TdiBuildInternalDeviceControlIrp(TDI_CONNECT, ...)
   ├─ TdiBuildConnect(Irp, DevObj, ConnObj, CompletionRoutine,
   │                  CompletionContext, Time, CallInfo, ReturnInfo)
   └─ IoCallDriver (异步, 返回 STATUS_PENDING)

8.7 TdiSetEventHandler --- 设置事件处理器

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L568-L626):

复制代码
TdiSetEventHandler(FileObject, EventType, Handler, Context)
   │
   ├─ TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, ...)
   ├─ TdiBuildSetEventHandler(Irp, DevObj, FileObj, NULL, NULL,
   │                          EventType, Handler, Context)
   └─ TdiCall(Irp, DeviceObject, &Event, &Iosb)

8.8 TdiQueryDeviceControl --- 设备控制查询

实现在 tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L629-L700):

复制代码
TdiQueryDeviceControl(FileObject, IoControlCode, ...)
   │
   ├─ IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, ...)
   └─ IoCallDriver

9. TDI 信息查询

9.1 通用查询类型

定义在 tdi.h(file:///d:/reactos/sdk/include/psdk/tdi.h#L179-L192):

c 复制代码
#define TDI_QUERY_BROADCAST_ADDRESS     0x00000001   // 广播地址
#define TDI_QUERY_PROVIDER_INFO         0x00000002   // 提供者信息
#define TDI_QUERY_ADDRESS_INFO          0x00000003   // 地址信息
#define TDI_QUERY_CONNECTION_INFO       0x00000004   // 连接信息
#define TDI_QUERY_PROVIDER_STATISTICS   0x00000005   // 提供者统计
#define TDI_QUERY_DATAGRAM_INFO         0x00000006   // 数据报信息
#define TDI_QUERY_DATA_LINK_ADDRESS     0x00000007   // 链路层地址
#define TDI_QUERY_NETWORK_ADDRESS       0x00000008   // 网络地址
#define TDI_QUERY_MAX_DATAGRAM_INFO     0x00000009   // 最大数据报

9.2 结果结构

TDI_PROVIDER_INFO --- 提供者能力:

c 复制代码
typedef struct _TDI_PROVIDER_INFO {
  ULONG  Version;              // TDI 版本
  ULONG  MaxSendSize;          // 最大发送大小
  ULONG  MaxConnectionUserData;// 最大连接用户数据
  ULONG  MaxDatagramSize;      // 最大数据报大小
  ULONG  ServiceFlags;         // 服务标志 (TDI_SERVICE_*)
  ULONG  MinimumLookaheadData; // 最小前瞻数据
  ULONG  MaximumLookaheadData; // 最大前瞻数据
  ULONG  NumberOfResources;
  LARGE_INTEGER  StartTime;
} TDI_PROVIDER_INFO, *PTDI_PROVIDER_INFO;

服务标志(部分):

c 复制代码
#define TDI_SERVICE_CONNECTION_MODE     0x00000001   // 面向连接
#define TDI_SERVICE_ORDERLY_RELEASE     0x00000002   // 有序释放
#define TDI_SERVICE_CONNECTIONLESS_MODE 0x00000004   // 无连接
#define TDI_SERVICE_ERROR_FREE_DELIVERY 0x00000008   // 无错投递
#define TDI_SERVICE_BROADCAST_SUPPORTED 0x00000020   // 支持广播
#define TDI_SERVICE_MULTICAST_SUPPORTED 0x00000040   // 支持多播
#define TDI_SERVICE_EXPEDITED_DATA      0x00000100   // 紧急数据
#define TDI_SERVICE_INTERNAL_BUFFERING  0x00000200   // 内部缓冲

TDI_CONNECTION_INFO --- 连接状态:

c 复制代码
typedef struct _TDI_CONNECTION_INFO {
  ULONG  State;                // 连接状态
  ULONG  Event;
  ULONG  TransmittedTsdus;     // 已发送 TSDU 数
  ULONG  ReceivedTsdus;        // 已接收 TSDU 数
  ULONG  TransmissionErrors;
  ULONG  ReceiveErrors;
  LARGE_INTEGER  Throughput;   // 吞吐量
  LARGE_INTEGER  Delay;        // 延迟
  ULONG  SendBufferSize;       // 发送缓冲大小
  ULONG  ReceiveBufferSize;    // 接收缓冲大小
  BOOLEAN  Unreliable;
} TDI_CONNECTION_INFO, *PTDI_CONNECTION_INFO;

TDI_MAX_DATAGRAM_INFO --- 最大数据报:

c 复制代码
typedef struct _TDI_MAX_DATAGRAM_INFO {
  ULONG  MaxDatagramSize;
} TDI_MAX_DATAGRAM_INFO, *PTDI_MAX_DATAGRAM_INFO;

9.3 在 tcpip.sys 中的实现

tcpip.sys 的 DispTdiQueryInformation 处理 TDI 查询:

查询类型 处理
TDI_QUERY_ADDRESS_INFO 返回地址文件的 IP 和端口
TDI_QUERY_CONNECTION_INFO 返回连接信息
TDI_QUERY_MAX_DATAGRAM_INFO 返回 0xFFFF (65535)

10. 工作流程图

10.1 地址文件打开流程

#mermaid-svg-dDO7itxYuplS7JOi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dDO7itxYuplS7JOi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dDO7itxYuplS7JOi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dDO7itxYuplS7JOi .error-icon{fill:#552222;}#mermaid-svg-dDO7itxYuplS7JOi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dDO7itxYuplS7JOi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dDO7itxYuplS7JOi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dDO7itxYuplS7JOi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dDO7itxYuplS7JOi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dDO7itxYuplS7JOi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dDO7itxYuplS7JOi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dDO7itxYuplS7JOi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dDO7itxYuplS7JOi .marker.cross{stroke:#333333;}#mermaid-svg-dDO7itxYuplS7JOi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dDO7itxYuplS7JOi p{margin:0;}#mermaid-svg-dDO7itxYuplS7JOi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dDO7itxYuplS7JOi .cluster-label text{fill:#333;}#mermaid-svg-dDO7itxYuplS7JOi .cluster-label span{color:#333;}#mermaid-svg-dDO7itxYuplS7JOi .cluster-label span p{background-color:transparent;}#mermaid-svg-dDO7itxYuplS7JOi .label text,#mermaid-svg-dDO7itxYuplS7JOi span{fill:#333;color:#333;}#mermaid-svg-dDO7itxYuplS7JOi .node rect,#mermaid-svg-dDO7itxYuplS7JOi .node circle,#mermaid-svg-dDO7itxYuplS7JOi .node ellipse,#mermaid-svg-dDO7itxYuplS7JOi .node polygon,#mermaid-svg-dDO7itxYuplS7JOi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dDO7itxYuplS7JOi .rough-node .label text,#mermaid-svg-dDO7itxYuplS7JOi .node .label text,#mermaid-svg-dDO7itxYuplS7JOi .image-shape .label,#mermaid-svg-dDO7itxYuplS7JOi .icon-shape .label{text-anchor:middle;}#mermaid-svg-dDO7itxYuplS7JOi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dDO7itxYuplS7JOi .rough-node .label,#mermaid-svg-dDO7itxYuplS7JOi .node .label,#mermaid-svg-dDO7itxYuplS7JOi .image-shape .label,#mermaid-svg-dDO7itxYuplS7JOi .icon-shape .label{text-align:center;}#mermaid-svg-dDO7itxYuplS7JOi .node.clickable{cursor:pointer;}#mermaid-svg-dDO7itxYuplS7JOi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dDO7itxYuplS7JOi .arrowheadPath{fill:#333333;}#mermaid-svg-dDO7itxYuplS7JOi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dDO7itxYuplS7JOi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dDO7itxYuplS7JOi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dDO7itxYuplS7JOi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dDO7itxYuplS7JOi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dDO7itxYuplS7JOi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dDO7itxYuplS7JOi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dDO7itxYuplS7JOi .cluster text{fill:#333;}#mermaid-svg-dDO7itxYuplS7JOi .cluster span{color:#333;}#mermaid-svg-dDO7itxYuplS7JOi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dDO7itxYuplS7JOi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dDO7itxYuplS7JOi rect.text{fill:none;stroke-width:0;}#mermaid-svg-dDO7itxYuplS7JOi .icon-shape,#mermaid-svg-dDO7itxYuplS7JOi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dDO7itxYuplS7JOi .icon-shape p,#mermaid-svg-dDO7itxYuplS7JOi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dDO7itxYuplS7JOi .icon-shape .label rect,#mermaid-svg-dDO7itxYuplS7JOi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dDO7itxYuplS7JOi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dDO7itxYuplS7JOi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dDO7itxYuplS7JOi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
客户端需要绑定地址
TdiOpenAddressFile
构造 FILE_FULL_EA_INFORMATION
EaName = TransportAddress
EaValue = TA_IP_ADDRESS
ZwCreateFile \\Device\\Tcp
IRP_MJ_CREATE → tcpip.sys
TiCreateFileObject
EA 是 TransportAddress?
解析 TA_IP_ADDRESS
FileOpenAddress
创建 ADDRESS_FILE
分配端口
FsContext2 = TDI_TRANSPORT_ADDRESS_FILE
返回地址文件句柄

10.2 连接建立流程

#mermaid-svg-MLVKkQej1sgy1rl4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MLVKkQej1sgy1rl4 .error-icon{fill:#552222;}#mermaid-svg-MLVKkQej1sgy1rl4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MLVKkQej1sgy1rl4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MLVKkQej1sgy1rl4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MLVKkQej1sgy1rl4 .marker.cross{stroke:#333333;}#mermaid-svg-MLVKkQej1sgy1rl4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MLVKkQej1sgy1rl4 p{margin:0;}#mermaid-svg-MLVKkQej1sgy1rl4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster-label text{fill:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster-label span{color:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster-label span p{background-color:transparent;}#mermaid-svg-MLVKkQej1sgy1rl4 .label text,#mermaid-svg-MLVKkQej1sgy1rl4 span{fill:#333;color:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 .node rect,#mermaid-svg-MLVKkQej1sgy1rl4 .node circle,#mermaid-svg-MLVKkQej1sgy1rl4 .node ellipse,#mermaid-svg-MLVKkQej1sgy1rl4 .node polygon,#mermaid-svg-MLVKkQej1sgy1rl4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MLVKkQej1sgy1rl4 .rough-node .label text,#mermaid-svg-MLVKkQej1sgy1rl4 .node .label text,#mermaid-svg-MLVKkQej1sgy1rl4 .image-shape .label,#mermaid-svg-MLVKkQej1sgy1rl4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-MLVKkQej1sgy1rl4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MLVKkQej1sgy1rl4 .rough-node .label,#mermaid-svg-MLVKkQej1sgy1rl4 .node .label,#mermaid-svg-MLVKkQej1sgy1rl4 .image-shape .label,#mermaid-svg-MLVKkQej1sgy1rl4 .icon-shape .label{text-align:center;}#mermaid-svg-MLVKkQej1sgy1rl4 .node.clickable{cursor:pointer;}#mermaid-svg-MLVKkQej1sgy1rl4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MLVKkQej1sgy1rl4 .arrowheadPath{fill:#333333;}#mermaid-svg-MLVKkQej1sgy1rl4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MLVKkQej1sgy1rl4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MLVKkQej1sgy1rl4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MLVKkQej1sgy1rl4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MLVKkQej1sgy1rl4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MLVKkQej1sgy1rl4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster text{fill:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 .cluster span{color:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MLVKkQej1sgy1rl4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MLVKkQej1sgy1rl4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-MLVKkQej1sgy1rl4 .icon-shape,#mermaid-svg-MLVKkQej1sgy1rl4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MLVKkQej1sgy1rl4 .icon-shape p,#mermaid-svg-MLVKkQej1sgy1rl4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MLVKkQej1sgy1rl4 .icon-shape .label rect,#mermaid-svg-MLVKkQej1sgy1rl4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MLVKkQej1sgy1rl4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MLVKkQej1sgy1rl4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MLVKkQej1sgy1rl4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端发起连接
TdiOpenConnectionEndpointFile
ZwCreateFile + ConnectionContext EA
tcpip.sys 创建连接端点
TdiAssociateAddressFile
TDI_ASSOCIATE_ADDRESS IRP
关联地址文件与连接
TdiSetEventHandler 注册事件
TDI_SET_EVENT_HANDLER
保存回调函数
TdiConnect
TdiBuildConnect TDI_CONNECT
IoCallDriver
tcpip.sys DispTdiConnect
TCPConnect 发送 SYN
等待 SYN+ACK
ESTABLISHED
完成 TDI IRP
客户端连接成功

10.3 数据发送流程

#mermaid-svg-xWVwbrqbFVDT2FtS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xWVwbrqbFVDT2FtS .error-icon{fill:#552222;}#mermaid-svg-xWVwbrqbFVDT2FtS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xWVwbrqbFVDT2FtS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xWVwbrqbFVDT2FtS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xWVwbrqbFVDT2FtS .marker.cross{stroke:#333333;}#mermaid-svg-xWVwbrqbFVDT2FtS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xWVwbrqbFVDT2FtS p{margin:0;}#mermaid-svg-xWVwbrqbFVDT2FtS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster-label text{fill:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster-label span{color:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster-label span p{background-color:transparent;}#mermaid-svg-xWVwbrqbFVDT2FtS .label text,#mermaid-svg-xWVwbrqbFVDT2FtS span{fill:#333;color:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS .node rect,#mermaid-svg-xWVwbrqbFVDT2FtS .node circle,#mermaid-svg-xWVwbrqbFVDT2FtS .node ellipse,#mermaid-svg-xWVwbrqbFVDT2FtS .node polygon,#mermaid-svg-xWVwbrqbFVDT2FtS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xWVwbrqbFVDT2FtS .rough-node .label text,#mermaid-svg-xWVwbrqbFVDT2FtS .node .label text,#mermaid-svg-xWVwbrqbFVDT2FtS .image-shape .label,#mermaid-svg-xWVwbrqbFVDT2FtS .icon-shape .label{text-anchor:middle;}#mermaid-svg-xWVwbrqbFVDT2FtS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xWVwbrqbFVDT2FtS .rough-node .label,#mermaid-svg-xWVwbrqbFVDT2FtS .node .label,#mermaid-svg-xWVwbrqbFVDT2FtS .image-shape .label,#mermaid-svg-xWVwbrqbFVDT2FtS .icon-shape .label{text-align:center;}#mermaid-svg-xWVwbrqbFVDT2FtS .node.clickable{cursor:pointer;}#mermaid-svg-xWVwbrqbFVDT2FtS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xWVwbrqbFVDT2FtS .arrowheadPath{fill:#333333;}#mermaid-svg-xWVwbrqbFVDT2FtS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xWVwbrqbFVDT2FtS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xWVwbrqbFVDT2FtS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xWVwbrqbFVDT2FtS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xWVwbrqbFVDT2FtS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xWVwbrqbFVDT2FtS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster text{fill:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS .cluster span{color:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xWVwbrqbFVDT2FtS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xWVwbrqbFVDT2FtS rect.text{fill:none;stroke-width:0;}#mermaid-svg-xWVwbrqbFVDT2FtS .icon-shape,#mermaid-svg-xWVwbrqbFVDT2FtS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xWVwbrqbFVDT2FtS .icon-shape p,#mermaid-svg-xWVwbrqbFVDT2FtS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xWVwbrqbFVDT2FtS .icon-shape .label rect,#mermaid-svg-xWVwbrqbFVDT2FtS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xWVwbrqbFVDT2FtS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xWVwbrqbFVDT2FtS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xWVwbrqbFVDT2FtS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端发送数据
构造数据 MDL
TdiBuildSend TDI_SEND
Irp->MdlAddress = 数据缓冲
IoCallDriver
tcpip.sys DispTdiSend
TCPSendData
TCP 分段 → IP → LAN → NdisSend
发送完成
IoCompleteRequest
客户端完成回调

10.4 数据接收事件流程

#mermaid-svg-ydpd1LqyzhHvpCnm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ydpd1LqyzhHvpCnm .error-icon{fill:#552222;}#mermaid-svg-ydpd1LqyzhHvpCnm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ydpd1LqyzhHvpCnm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ydpd1LqyzhHvpCnm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ydpd1LqyzhHvpCnm .marker.cross{stroke:#333333;}#mermaid-svg-ydpd1LqyzhHvpCnm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ydpd1LqyzhHvpCnm p{margin:0;}#mermaid-svg-ydpd1LqyzhHvpCnm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster-label text{fill:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster-label span{color:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster-label span p{background-color:transparent;}#mermaid-svg-ydpd1LqyzhHvpCnm .label text,#mermaid-svg-ydpd1LqyzhHvpCnm span{fill:#333;color:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm .node rect,#mermaid-svg-ydpd1LqyzhHvpCnm .node circle,#mermaid-svg-ydpd1LqyzhHvpCnm .node ellipse,#mermaid-svg-ydpd1LqyzhHvpCnm .node polygon,#mermaid-svg-ydpd1LqyzhHvpCnm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ydpd1LqyzhHvpCnm .rough-node .label text,#mermaid-svg-ydpd1LqyzhHvpCnm .node .label text,#mermaid-svg-ydpd1LqyzhHvpCnm .image-shape .label,#mermaid-svg-ydpd1LqyzhHvpCnm .icon-shape .label{text-anchor:middle;}#mermaid-svg-ydpd1LqyzhHvpCnm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ydpd1LqyzhHvpCnm .rough-node .label,#mermaid-svg-ydpd1LqyzhHvpCnm .node .label,#mermaid-svg-ydpd1LqyzhHvpCnm .image-shape .label,#mermaid-svg-ydpd1LqyzhHvpCnm .icon-shape .label{text-align:center;}#mermaid-svg-ydpd1LqyzhHvpCnm .node.clickable{cursor:pointer;}#mermaid-svg-ydpd1LqyzhHvpCnm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ydpd1LqyzhHvpCnm .arrowheadPath{fill:#333333;}#mermaid-svg-ydpd1LqyzhHvpCnm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ydpd1LqyzhHvpCnm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ydpd1LqyzhHvpCnm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ydpd1LqyzhHvpCnm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ydpd1LqyzhHvpCnm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ydpd1LqyzhHvpCnm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster text{fill:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm .cluster span{color:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ydpd1LqyzhHvpCnm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ydpd1LqyzhHvpCnm rect.text{fill:none;stroke-width:0;}#mermaid-svg-ydpd1LqyzhHvpCnm .icon-shape,#mermaid-svg-ydpd1LqyzhHvpCnm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ydpd1LqyzhHvpCnm .icon-shape p,#mermaid-svg-ydpd1LqyzhHvpCnm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ydpd1LqyzhHvpCnm .icon-shape .label rect,#mermaid-svg-ydpd1LqyzhHvpCnm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ydpd1LqyzhHvpCnm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ydpd1LqyzhHvpCnm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ydpd1LqyzhHvpCnm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

数据到达
tcpip.sys TCPReceive
查找连接端点
已注册 TDI_EVENT_RECEIVE?
调用客户端 ReceiveHandler
客户端复制 Tsdu 数据
设置 BytesTaken
返回 STATUS_SUCCESS
数据留在接收队列
tcpip.sys 确认数据已取走


11. 数据流图

11.1 TDI 完整调用链

复制代码
TDI 客户端 (AFD.sys)
  │
  │ 1. ZwCreateFile(\Device\Tcp, EA=TransportAddress)
  │    ── IRP_MJ_CREATE ──▶ tcpip.sys: TiCreateFileObject
  │                           └─ FileOpenAddress → ADDRESS_FILE
  │
  │ 2. ZwCreateFile(\Device\Tcp, EA=ConnectionContext)
  │    ── IRP_MJ_CREATE ──▶ tcpip.sys: FileOpenConnection
  │                           └─ CONNECTION_ENDPOINT
  │
  │ 3. TdiAssociateAddressFile
  │    ── IRP_MJ_INTERNAL_DEVICE_CONTROL (TDI_ASSOCIATE_ADDRESS)
  │    ──▶ tcpip.sys: DispTdiAssociateAddress
  │
  │ 4. TdiSetEventHandler(TDI_EVENT_RECEIVE, ...)
  │    ── TDI_SET_EVENT_HANDLER ──▶ tcpip.sys: DispTdiSetEventHandler
  │
  │ 5. TdiConnect
  │    ── TDI_CONNECT ──▶ tcpip.sys: DispTdiConnect → TCPConnect
  │
  │ 6. TdiSend (数据+MDL)
  │    ── TDI_SEND ──▶ tcpip.sys: DispTdiSend → TCPSendData
  │
  │ 7. 数据到达
  │    ◀── TDI_EVENT_RECEIVE ── tcpip.sys 回调 AFD 的处理器
  │
  │ 8. TdiReceive (接收 MDL)
  │    ── TDI_RECEIVE ──▶ tcpip.sys: DispTdiReceive → TCPReceiveData
  │
  │ 9. TdiDisconnect
  │    ── TDI_DISCONNECT ──▶ tcpip.sys: DispTdiDisconnect → TCPDisconnect

11.2 TDI_SEND 请求结构

复制代码
IRP (TDI_SEND)
├── MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL
├── MinorFunction = 0x07 (TDI_SEND)
├── MdlAddress = 数据缓冲 (MDL 链)
├── FileObject = 连接端点文件对象
├── DeviceObject = \Device\Tcp 设备
└── IrpSp->Parameters:
    └── TDI_REQUEST_KERNEL_SEND
        ├── SendLength = 待发送字节数
        └── SendFlags  = TDI_SEND_* 标志

11.3 TDI 事件注册与触发

复制代码
注册阶段:
客户端 ── TDI_SET_EVENT_HANDLER ──▶ tcpip.sys
    { EventType: TDI_EVENT_RECEIVE }
    { EventHandler: AfdEventReceive }
    { EventContext: AFD_FCB }
                        │
                        ▼
              ADDRESS_FILE 保存
              { RegisteredReceiveHandler = TRUE
                ReceiveHandler = AfdEventReceive
                ReceiveHandlerContext = FCB }

触发阶段:
数据到达
    │
    ▼
tcpip.sys 查找 ADDRESS_FILE 的 ReceiveHandler
    │
    ▼
调用 AfdEventReceive(FCB, ConnContext, Flags,
                     BytesIndicated, BytesAvailable,
                     &BytesTaken, Tsdu, &Irp)
    │
    ├─ 复制数据到 FCB 缓冲
    ├─ *BytesTaken = BytesAvailable
    └─ 返回 STATUS_SUCCESS

12. 关键定义索引

12.1 头文件

头文件 路径 内容
tdikrnl.h sdk/include/ddk/tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h) 内核 TDI:请求码、TdiBuild 宏、事件原型
tdi.h sdk/include/psdk/tdi.h(file:///d:/reactos/sdk/include/psdk/tdi.h) TDI 结构:连接信息、传输地址、查询类型
tdistat.h sdk/include/ddk/tdistat.h(file:///d:/reactos/sdk/include/ddk/tdistat.h) TDI 状态码
ntddtdi.h sdk/include/psdk/ntddtdi.h(file:///d:/reactos/sdk/include/psdk/ntddtdi.h) TDI IOCTL 定义
tdiinfo.h sdk/include/psdk/tdiinfo.h(file:///d:/reactos/sdk/include/psdk/tdiinfo.h) TDI 信息类

12.2 tdihelpers 函数

函数 位置 说明
TdiCall tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L26-L65) IoCallDriver + 事件等待
TdiOpenDevice tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L68-L146) 打开 TDI 设备
TdiOpenAddressFile tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L148-L201) 打开地址文件 (EA)
TdiQueryMaxDatagramLength tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L203-L256) 查询最大数据报
TdiOpenConnectionEndpointFile tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L258-L308) 打开连接端点 (EA)
TdiConnect tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L311-L380) TDI_CONNECT
TdiAssociateAddressFile tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L370-L411) TDI_ASSOCIATE_ADDRESS
TdiDisassociateAddressFile tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L413-L458) TDI_DISASSOCIATE_ADDRESS
TdiListen tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L460-L512) TDI_LISTEN
TdiAccept tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L514-L565) TDI_ACCEPT
TdiSetEventHandler tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L568-L626) TDI_SET_EVENT_HANDLER
TdiQueryDeviceControl tdi.c(file:///d:/reactos/drivers/network/tdihelpers/tdi.c#L629-L700) 设备控制查询

12.3 tcpip.sys 中的 TDI 处理

TDI 操作 tcpip.sys 处理函数
TDI_CONNECT DispTdiConnectTCPConnect
TDI_LISTEN DispTdiListenTCPListen + TCPAccept
TDI_ACCEPT DispTdiAccept
TDI_DISCONNECT DispTdiDisconnectTCPDisconnect
TDI_SEND DispTdiSendTCPSendData
TDI_RECEIVE DispTdiReceiveTCPReceiveData
TDI_SEND_DATAGRAM DispTdiSendDatagram
TDI_RECEIVE_DATAGRAM DispTdiReceiveDatagramDGReceiveDatagram
TDI_SET_EVENT_HANDLER DispTdiSetEventHandler
TDI_QUERY_INFORMATION DispTdiQueryInformation
TDI_ASSOCIATE_ADDRESS DispTdiAssociateAddress
TDI_DISASSOCIATE_ADDRESS DispTdiDisassociateAddress

12.4 参考文档

  • TCPIP 驱动分析(file:///d:/reactos/doc/TCPIP_驱动分析.md) --- tcpip.sys 中的 TDI 分发处理
  • AFD辅助功能驱动分析(file:///d:/reactos/doc/AFD辅助功能驱动分析.md) --- AFD.sys 作为 TDI 客户端
  • WSP服务提供者AFD_Provider分析(file:///d:/reactos/doc/WSP服务提供者AFD_Provider分析.md) --- msafd.dll
  • TCP/IP协议驱动分析_1.md(file:///d:/reactos/doc/TCP/IP协议驱动分析_1.md) --- 完整调用链
相关推荐
shengnan_wsn5 小时前
【协议】【TCP】
网络·网络协议·tcp/ip
消失的旧时光-19436 小时前
第 3 篇:机器人 TCP 长连接如何稳定运行?心跳、掉线检测与自动重连
网络协议·tcp/ip·机器人
不弃君7 小时前
在 Windows 上用 MinGW 搭建 lwIP 调试环境:方法与踩坑实录
windows·网络协议·tcp/ip·嵌入式·mingw·lwip
NeilYuen9 小时前
实现TCP发送HTTP请求
网络协议·tcp/ip·http
ARoger_miu5712 小时前
opsf笔记
网络·网络协议
caimouse12 小时前
tcpip.sys 网络层 (IP) 详细分析
网络·网络协议·tcp/ip
wuhuhuan13 小时前
Day17:HTTP 接口测试与链式调用 — sendRequest 从入门到实战
网络·网络协议·http
m0_5474866613 小时前
《网络协议安全》全套PPT课件(太原理工大学)
网络协议·安全·网络安全
caimouse13 小时前
tcpip.sys 传输层 (TCP) 详细分析
网络·网络协议·tcp/ip