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

http://hi.baidu.com/combojiang/item/07a100ef4662a0225a2d640e

步骤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;

}

posted @ 2013-01-15 11:08  himessage  阅读(551)  评论(0编辑  收藏  举报