发点TDI通信的东东

本文档详细介绍了TDI通信的过程,包括创建上下文句柄、建立连接终端、创建传输句柄、地址绑定、连接远程节点以及发送和断开连接。通过示例代码展示了如何使用TDI函数进行内核模式下的TCP通信操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/***************************************************************************/
/*创建上下文句柄....RtlCopyMemory(Ea->EaName, TdiConnectionContext, Ea->EaNameLength + 1);
/*CHAR Buffer[sizeof (FILE_FULL_EA_INFORMATION) + TDI_CONNECTION_CONTEXT_LENGTH];
/*这个函数是创建连接终端...(connection endpoint )
/*A kernel-mode client must open both a connection endpoint and an address with successful calls to
/*ZwCreateFile before it calls TdiBuildAssociateAddress
/***************************************************************************/
NTSTATUS CreateConnection(PHANDLE Handle, PFILE_OBJECT *FileObject)
{
 IO_STATUS_BLOCK IoStatus;
 NTSTATUS Status;
 UNICODE_STRING Name;
 OBJECT_ATTRIBUTES Attr;
 char Buffer[sizeof(FILE_FULL_EA_INFORMATION) + TDI_CONNECTION_CONTEXT_LENGTH + 300] = {0};
 PFILE_FULL_EA_INFORMATION Ea ;

 // DbgPrint("hi in createconnection/n");
 RtlInitUnicodeString(&Name, L"//Device//Tcp");
 InitializeObjectAttributes(&Attr, &Name, OBJ_CASE_INSENSITIVE, 0, 0);

 Ea = (PFILE_FULL_EA_INFORMATION)&Buffer;
 RtlCopyMemory(Ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH);
 Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
 Ea->EaValueLength =TDI_CONNECTION_CONTEXT_LENGTH;


 Status= ZwCreateFile(Handle,
  GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  &Attr,
  &IoStatus,
  0,
  FILE_ATTRIBUTE_NORMAL,
  FILE_SHARE_READ,
  FILE_OPEN,
  0,
  Ea,
  sizeof(Buffer));
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("ZwCreateFile return failed!!/n");
  return Status;
 }

 return ObReferenceObjectByHandle(*Handle, GENERIC_READ | GENERIC_WRITE, 0, KernelMode, (PVOID *)FileObject, 0);

}

/************************************************************************/
/* 创建传输句柄...
/* CHAR Buffer[sizeof (FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof (TA_IP_ADDRESS)];
/* RtlCopyMemory(Ea->EaName, TdiTransportAddress, Ea->EaNameLength + 1);
/*一般是0.0.0.0                                                                 *
/************************************************************************/
NTSTATUS CreateAddress(PHANDLE Handle, PFILE_OBJECT *FileObject)
{
 UNICODE_STRING Name;
 OBJECT_ATTRIBUTES Attr;
 CHAR Buffer[sizeof (FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof (TA_IP_ADDRESS)];
 PFILE_FULL_EA_INFORMATION Ea;
 IO_STATUS_BLOCK IoStatus;
 NTSTATUS Status ;
 PTA_IP_ADDRESS Sin;
 // DbgPrint(" hi in cretaaddress/n");
 RtlInitUnicodeString(&Name, L"//Device//Tcp");
 InitializeObjectAttributes(&Attr, &Name, OBJ_CASE_INSENSITIVE, 0, 0);

 Ea = (PFILE_FULL_EA_INFORMATION)Buffer;
 Ea->NextEntryOffset = 0;
 Ea->Flags = 0;
 Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
 Ea->EaValueLength = sizeof (TA_IP_ADDRESS);
 RtlCopyMemory(Ea->EaName, TdiTransportAddress, Ea->EaNameLength + 1);

 Sin = (PTA_IP_ADDRESS)(Ea->EaName + Ea->EaNameLength + 1);
 Sin->TAAddressCount = 1;
 Sin->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
 Sin->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
 Sin->Address[0].Address[0].sin_port = 0;
 Sin->Address[0].Address[0].in_addr = 0;
 RtlZeroMemory(Sin->Address[0].Address[0].sin_zero, sizeof(Sin->Address[0].Address[0].sin_zero));

 Status = ZwCreateFile(Handle,
  0,
  &Attr,
  &IoStatus,
  0,
  FILE_ATTRIBUTE_NORMAL,
  0,
  FILE_OPEN,
  0,
  Ea,
  sizeof(Buffer));
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("CreateAddress->ZwCreateFile return failed!!/n");
  return Status;
 }

 return ObReferenceObjectByHandle(*Handle, GENERIC_READ | GENERIC_WRITE, 0, KernelMode, (PVOID *)FileObject, 0);

}

/*************************************************************************************************
/*The client must make the associate-address request before it makes a connection to the remote node
/*把FileObject,Address关联...
/* Associate endpoint with address
/*************************************************************************************************/
NTSTATUS Bind(PFILE_OBJECT FileObject, HANDLE Address)
{
 KEVENT Event;
 PDEVICE_OBJECT DeviceObject;
 IO_STATUS_BLOCK IoStatus;
 PIRP Irp ;
 NTSTATUS Status;
 // Define a completion event

 KeInitializeEvent(&Event, NotificationEvent, FALSE);
 DeviceObject = IoGetRelatedDeviceObject(FileObject);
 Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, DeviceObject, FileObject, &Event, &IoStatus);
 /*
 TdiBuildAssociateAddress sets IRP_MJ_INTERNAL_DEVICE_CONTROL as the MajorFunction and TDI_ASSOCIATE_ADDRESS
 as the MinorFunction codes in the transport's I/O stack location of the given IRP.*/
 if (Irp == 0)
  return STATUS_INSUFFICIENT_RESOURCES;
 TdiBuildAssociateAddress(Irp, DeviceObject, FileObject, 0, 0, Address);
 Status = IoCallDriver(DeviceObject, Irp);
 if (Status == STATUS_PENDING)
  Status = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0);
 return Status == STATUS_SUCCESS ? IoStatus.Status : Status;
}

/*********************************************************************************/
/*创建连接
/*Connect to the remote controller
/*
/*********************************************************************************/

NTSTATUS Connect(PFILE_OBJECT FileObject, ULONG Addr, USHORT Port)
{
 KEVENT Event;
 PDEVICE_OBJECT DeviceObject;
 IO_STATUS_BLOCK IoStatus;
 PIRP Irp;
 TA_IP_ADDRESS RemoteAddr;
 TDI_CONNECTION_INFORMATION RequestInfo;
 PTDI_ADDRESS_IP pTdiAddressIp;
 NTSTATUS Status;


 KeInitializeEvent(&Event, NotificationEvent, FALSE);
 DeviceObject = IoGetRelatedDeviceObject(FileObject);
 //// build connection packet
 Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, DeviceObject, FileObject, &Event, &IoStatus);
 if (Irp == 0)
  return STATUS_INSUFFICIENT_RESOURCES;

 // Initialize controller data
 RemoteAddr.TAAddressCount=1;
 RemoteAddr.Address[0].AddressLength=TDI_ADDRESS_LENGTH_IP;
 RemoteAddr.Address[0].AddressType=TDI_ADDRESS_TYPE_IP;
 /* pTdiAddressIp = (TDI_ADDRESS_IP *)RemoteAddr.Address[0].Address;
 pTdiAddressIp->sin_port=Port;
 pTdiAddressIp->in_addr=Addr;*/
 RemoteAddr.Address[0].Address[0].sin_port =Port;
 RemoteAddr.Address[0].Address[0].in_addr =Addr;

 RequestInfo.Options=0;
 RequestInfo.OptionsLength=0;
 RequestInfo.UserData=0;
 RequestInfo.UserDataLength=0;
 RequestInfo.RemoteAddress=&RemoteAddr;
 RequestInfo.RemoteAddressLength=sizeof(RemoteAddr);

 TdiBuildConnect(Irp, DeviceObject, FileObject, 0, 0, 0, &RequestInfo, 0);
 Status = IoCallDriver(DeviceObject, Irp);
 if (Status == STATUS_PENDING)
  Status = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0);

 return Status == STATUS_SUCCESS ? IoStatus.Status : Status;

}


NTSTATUS Disconnect(PFILE_OBJECT FileObject)
{
 KEVENT Event;
 NTSTATUS Status;
 PDEVICE_OBJECT DeviceObject;
 IO_STATUS_BLOCK IoStatus;
 PIRP Irp;

 KeInitializeEvent(&Event, NotificationEvent, FALSE);
 DeviceObject = IoGetRelatedDeviceObject(FileObject);
 Irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, DeviceObject, FileObject, &Event, &IoStatus);
 if (Irp == 0)
  return STATUS_INSUFFICIENT_RESOURCES;
 TdiBuildDisconnect(Irp, DeviceObject, FileObject, 0, 0, 0, TDI_DISCONNECT_RELEASE, 0, 0);
 Status = IoCallDriver(DeviceObject, Irp);
 if (Status == STATUS_PENDING)
  Status = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0);

 return Status == STATUS_SUCCESS ? IoStatus.Status : Status;
}


NTSTATUS Send(PFILE_OBJECT FileObject, PVOID Data, ULONG Length)
{
 KEVENT Event;
 PDEVICE_OBJECT DeviceObject ;
 IO_STATUS_BLOCK IoStatus;
 PIRP Irp;
 PMDL Mdl;
 NTSTATUS Status;

 KeInitializeEvent(&Event, NotificationEvent, FALSE);
 //The TDI Device Object is required to send these requests to the TDI Driver.

 DeviceObject = IoGetRelatedDeviceObject(FileObject);
 Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND, DeviceObject, FileObject, &Event, &IoStatus);
 if (Irp == 0)
  return STATUS_INSUFFICIENT_RESOURCES;

 Mdl = IoAllocateMdl(Data, Length, FALSE, FALSE, Irp);
 if (Mdl == 0)
  return STATUS_INSUFFICIENT_RESOURCES;
 __try
 {
  MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
 }__except (EXCEPTION_EXECUTE_HANDLER)
 {
  IoFreeMdl(Mdl);
  Mdl = NULL;
 }


 TdiBuildSend(Irp, DeviceObject, FileObject, 0, 0, Mdl, 0, Length);
 Status = IoCallDriver(DeviceObject, Irp);
 /* If the status returned is STATUS_PENDING this means that the IRP will not be completed synchronously
 and the driver has queued the IRP for later processing. This is fine but we do not want to return this
 not want to return this not want to return this to wait until it has completed. The EVENT that we
 providedwill be set when the IRP completes. */
 if (Status == STATUS_PENDING)
  Status = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0);

 return Status == STATUS_SUCCESS ? IoStatus.Status : Status;
}


NTSTATUS SendDataToRemote(PVOID Data,ULONG RemoteAddress,ULONG RemotePort)
{
 PFILE_OBJECT ConnectionFileObject, AddressFileObject;
 HANDLE AddressHandle, ConnectionHandle;
 NTSTATUS Status;
 IO_STATUS_BLOCK IoStatus;
 KEVENT Event;

 //CreateAddress,创建传输地址,该地址是指本机地址
 Status = CreateAddress(&AddressHandle, &AddressFileObject);
 if (!NT_SUCCESS(Status))
 {  
  DbgPrint("createaddress return failed!!/n");
  return Status;
 }
 DbgPrint(" createaddress return OK!/n");

 //CreateConnection-->>创建一个连接终端
 Status = CreateConnection(&ConnectionHandle, &ConnectionFileObject);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("createconnection return failed!!/n");
  return Status;
 }


 Status = Bind(ConnectionFileObject, AddressHandle);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("Bind() return failed!!/n");
  return Status;
 }

 Status = Connect(ConnectionFileObject, RemoteAddress, RemotePort);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("Connect() return failed!!/n");
  return Status;
 }
 Status = Send(ConnectionFileObject, Data, strlen(Data));
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("Send() return failed!!/n");
  return Status;
 }
 Status = Disconnect(ConnectionFileObject);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("Disconnect() return failed!!/n");
  return Status;
 }


 ObDereferenceObject(ConnectionFileObject);
 ObDereferenceObject(AddressFileObject);
 ZwClose(ConnectionHandle);
 ZwClose(AddressHandle);
 return Status;
}


//自己调用SendDataToRemote(PVOID Data,ULONG RemoteAddress,ULONG RemotePort)
//就行
//
//eg SendDataToRemote(&Data,0x0100007F,0x0007) ;

基于TDI 的 TCP数据传输 1.上位机 上位机包括tcp和tcp.cpp 1.1 对外函数说明 HANDLE TdiTcpOpen(); TdiTcpOpen用于打开设备,成功返回有效的句柄,失败返回INVALID_HANDLE_VALUE. BOOL TdiTcpClose(HANDLE hDevice); TdiTcpClose用于关闭设备,成功返回TRUE,失败返回FALSE; hDevice为TdiTcpOpen返回的句柄 BOOL TdiTcpConnect(HANDLE hDevice,const PCHAR pIpAddres,USHORT uPort); TdiTcpConnect用于与服务器建链,pIpAddres为服务器IP地址,uPort为服务器端口地址。 hDevice为TdiTcpOpen返回的句柄 pIpAddres为IP地址,如”10.0.0.20” uPort为端口地址 BOOL TdiTcpSend(HANDLE hDevice,PVOID pBuff,ULONG nLen,PULONG pRtn); TdiTcpSend用于给服务器发送数据. hDevice为TdiTcpOpen返回的句柄 pBuff接向发送数据的指针 nLen发送数据长度 pRtn发送成功长度 BOOL TdiTcpRcv(HANDLE hDevice,PVOID pBuff,ULONG nLen,PULONG pRtn); TdiTcpRcv用于从服务器接收数据 hDevice为TdiTcpOpen返回的句柄 pBuff接收数据缓冲区 nLen接收数据缓冲区长度 pRtn实际接收数据长度指针 BOOL TdiTcpSetRcvTimeOut(HANDLE hDevice,ULONG ulSecond); TdiTcpSetRcvTimeOut用于设置接收数据超时时间,默认为3秒。 hDevice为TdiTcpOpen返回的句柄 ulSecond为超时时间 2.下位机 下位机包括D1603.h D1603.cpp和Tdifun.cpp TdiFun.h 2.1 关键数据结构 驱动与应用连接服务器结构体 typedef struct _CONNECT_STRUCT { ULONG ip; //服务器IP地址 USHORT port; //服务器端口 }CONNECT_STRUCT,*PCONNECT_STRUCT; //设备展结构体 typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pDeviceObject; //设备指针 UNICODE_STRING wstrDeviceName ; //设备名 UNICODE_STRING wstrSymbolicLinkName;//设备链接名 }DEVICE_EXTENSION,*PDEVICE_EXTENSION; 读数据链接 typedef struct _RCV_IPR_LIST { PIRP pIrp; //指向读IPR LIST_ENTRY ListEntry; //链表 }RCV_IPR_LIST,*PRCV_IPR_LIST; 当前链接上下文 typedef struct _SOCKET_CONTEXT { HANDLE TransportAddressHandle; //传输地址句柄 FILE_OBJECT* pTrasnportAddressFile;//传输地址指针 HANDLE ConnectionHandle;//连接地址句柄 FILE_OBJECT* pConnectionFile;//连接地址指针 LIST_ENTRY RcvHead; //接收IRP链表头 KEVENT event; //接收数据同步事件 ULONG uTimeOut; // 接收数据超时 }SOCKET_CONTEXT,*PSOCKET_CONTEXT; 2.2 外函数说明 驱动装载主入口函数 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath); 驱动卸载函数 VOID D1603Unload(PDRIVER_OBJECT DriverObject); 默认IRP回调函数 NTSTATUS D1603Dispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp); TdiTcpOpen对应的IPR函数 NTSTATUS D1603Create(PDEVICE_OBJECT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值