驱动开发之五 --- TDI之五【译文】

本文介绍使用TDI(Transport Driver Interface)进行数据发送的方法。通过创建TDI_SENDIOCTL并将其传递给传输设备实现数据发送。文章详细展示了构建IRP(I/O Request Packet)、设置参数及等待操作完成的过程。

驱动开发之五 --- TDI之五【译文】

步骤5:发送和接收数据

为了发送数据,你只需创建一个TDI_SEND IOCTL,然后把它传送给传输设备。下面的代码实现了数据发送。

NTSTATUS TdiFuncs_Send(PFILE_OBJECT pfoConnection, PVOID pData,

                                UINT uiSendLength, UINT *pDataSent)

{

    NTSTATUS NtStatus = STATUS_INSUFFICIENT_RESOURCES;

    PIRP pIrp;

    IO_STATUS_BLOCK IoStatusBlock = {0};

    PDEVICE_OBJECT pTdiDevice;

    PMDL pSendMdl;

    TDI_COMPLETION_CONTEXT TdiCompletionContext;

    KeInitializeEvent(&TdiCompletionContext.kCompleteEvent,

                                             NotificationEvent, FALSE);

    /*

     * The TDI Device Object is required to

     *               send these requests to the TDI Driver.

     */

    pTdiDevice = IoGetRelatedDeviceObject(pfoConnection);

    *pDataSent = 0;

    /*

     * The send requires an MDL which is what you may remember from DIRECT_IO.  

     * However, instead of using an MDL we need to create one.

     */

    pSendMdl = IoAllocateMdl((PCHAR )pData, uiSendLength, FALSE, FALSE, NULL);

    if(pSendMdl)

    {

        __try {

            MmProbeAndLockPages(pSendMdl, KernelMode, IoModifyAccess);

        } __except (EXCEPTION_EXECUTE_HANDLER) {

                IoFreeMdl(pSendMdl);

                pSendMdl = NULL;

        };

        if(pSendMdl)

        {

    

            /*

             * Step 1: Build the IRP. TDI defines several macros and functions

             *         that can quickly create IRP's, etc. for variuos purposes.  

             *         While this can be done manually it's easiest to use

             *         the macros.

             */

            pIrp = TdiBuildInternalDeviceControlIrp(TDI_SEND,

                     pTdiDevice, pfoConnection,

                     &TdiCompletionContext.kCompleteEvent,

                     &IoStatusBlock);

        

            if(pIrp)

            {

                /*

                 * Step 2: Add the correct parameters into the IRP.

                 */

        

         

                TdiBuildSend(pIrp, pTdiDevice, pfoConnection, NULL,

                                       NULL, pSendMdl, 0, uiSendLength);

        

                NtStatus = IoCallDriver(pTdiDevice, pIrp);

        

                /*

                 * 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(NtStatus == STATUS_PENDING)

                {

                    KeWaitForSingleObject(&TdiCompletionContext.kCompleteEvent,

                                           Executive, KernelMode, FALSE, NULL);

        

                }

                NtStatus   = IoStatusBlock.Status;

                *pDataSent = (UINT)IoStatusBlock.Information;

    

               /*

                * I/O Manager will free the MDL

                *

                if(pSendMdl)

                {

                    MmUnlockPages(pSendMdl);

                    IoFreeMdl(pSendMdl);

                } */

            }

        }

    }

    return NtStatus;

}

基于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、付费专栏及课程。

余额充值