iniwf

风是温柔的,雨是伤心的,云是快乐的,月是多情的,爱是迷失的,恋是醉人的,情是难忘的,天是长久的,地是永恒的

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

转自http://hi.baidu.com/combojiang/blog/item/60b25710f7c7a004213f2ec4.html

接上

步骤2:打开连接上下文

第二步是打开连接上下文。在你建立的连接中,执行后续的操作会用到这个句柄。这也是由ZwCreateFile完成,也是在相同的设备
"\Device\Tcp"上执行。实际上这个设备允许你打开三个不同的句柄。这三个句柄是传输句柄,连接上下文句柄和控制句柄。需要注意一个常犯的错误的是,一个句柄打开成功,但实际上确是一个错误打开的句柄。这是由于他们是由"Extended Attributes"来决定打开哪个句柄的。显然,如果驱动程序不能识别EA("Extended Attributes")的值,那么它就会打开一个默认的句柄类型,控制句柄。这是MSDN中关于创建部分的文档描述的。


下面的代码演示了打开一个连接上下文。注意你需要制定一个
"CONNECTION_CONTEXT"类型的指针,使用这个指针指向用户定义的数据。后面你会注意到一些事件回调会提供这个指针给你。这也是你可以使用这个上下文值的本质。


NTSTATUS TdiFuncs_OpenConnection(PHANDLE pTdiHandle, PFILE_OBJECT 
*pFileObject) 



    NTSTATUS NtStatus 
= STATUS_INSUFFICIENT_RESOURCES; 

    UNICODE_STRING usTdiDriverNameString; 

    OBJECT_ATTRIBUTES oaTdiDriverNameAttributes; 

    IO_STATUS_BLOCK IoStatusBlock; 

    
char DataBlob[sizeof(FILE_FULL_EA_INFORMATION) + 

              TDI_CONNECTION_CONTEXT_LENGTH 
+ 300= {0}

    PFILE_FULL_EA_INFORMATION pExtendedAttributesInformation 
= 

                    (PFILE_FULL_EA_INFORMATION)
&DataBlob; 

    UINT dwEASize 
= 0

         

    
/* 

     * Initialize the name of the device to be opened. ZwCreateFile 

     * takes an OBJECT_ATTRIBUTES structure as the name of the device 

     * to open. This is then a two step process. 

     * 

     * 1 - Create a UNICODE_STRING data structure from a unicode string. 

     * 2 - Create a OBJECT_ATTRIBUTES data structure from a UNICODE_STRING. 

     * 

     
*/
 


    RtlInitUnicodeString(
&usTdiDriverNameString, L"\\Device\\Tcp"); 

    InitializeObjectAttributes(
&oaTdiDriverNameAttributes, 

            
&usTdiDriverNameString, 

            OBJ_CASE_INSENSITIVE 
| OBJ_KERNEL_HANDLE, 

            NULL, NULL); 


    
/* 

     * The second step is to initialize the Extended Attributes data structure. 

     * 

     * EaName    = TdiConnectionContext, 0, Your User Defined Context Data 

     *                                              (Actually a pointer to it) 

     * EaNameLength = Length of TdiConnectionContext 

     * EaValueLength = Entire Length 

     
*/
 

     RtlCopyMemory(
&pExtendedAttributesInformation->EaName, 

                        TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH); 


     pExtendedAttributesInformation
->EaNameLength = 

                                          TDI_CONNECTION_CONTEXT_LENGTH; 

     pExtendedAttributesInformation
->EaValueLength = 

                                       TDI_CONNECTION_CONTEXT_LENGTH; 

              
/* Must be at least TDI_CONNECTION_CONTEXT_LENGTH */ 


     dwEASize 
= sizeof(DataBlob); 


     NtStatus 
= ZwCreateFile(pTdiHandle, 

         FILE_READ_EA 
| FILE_WRITE_EA, &oaTdiDriverNameAttributes, 

         
&IoStatusBlock, NULL, 

         FILE_ATTRIBUTE_NORMAL, 
0, FILE_OPEN_IF, 0

         pExtendedAttributesInformation, dwEASize); 


     
if(NT_SUCCESS(NtStatus)) 

     


          NtStatus 
= ObReferenceObjectByHandle(*pTdiHandle, 

                          GENERIC_READ 
| GENERIC_WRITE, 

                          NULL, KernelMode, 

                         (PVOID 
*)pFileObject, NULL);       


          
if(!NT_SUCCESS(NtStatus)) 

          


              ZwClose(
*pTdiHandle); 

          }
 

     }
 


     
return NtStatus; 

}
 


步骤3:关联传输地址和连接上下文

在你执行任何操作之前,你需要关联这两个句柄,传输句柄和连接上下文句柄。这个通过给设备发送一个IOCTL来完成。是否你还记得先前我们是怎样发送IOCTL的?我们需要分配一个IRP,设置参数和发送它到设备。由于TDI头文件提供了宏和其他的函数可以帮助我们简化这个步骤。TdiBuildInternalDeviceControlIrp实际是一个宏,它内部调用了IoBuildDeviceIoControlRequest. 给这个宏的一些参数实际被忽略了,但是对于注释来讲还是有用的(就像提供的IOCTL一样)。这个API很简单,我们为了演示目的使用它。然而使用其它机制来创建IRP,就像IoAllocateIrp,有一些优点,这个将在后面叙述。其他的宏被用于给底层的驱动简单的设置IO_STACK_LOCATION的参数。


这里有一件事情你需要注意,这里跟我们上次谈到的有些不同的是
"STATUS_PENDING"。本篇后面将会讨论这个。

下面的代码演示如何使用它。

NTSTATUS TdiFuncs_AssociateTransportAndConnection(HANDLE hTransportAddress, 

                                     PFILE_OBJECT pfoConnection) 



    NTSTATUS NtStatus 
= STATUS_INSUFFICIENT_RESOURCES; 

    PIRP pIrp; 

    IO_STATUS_BLOCK IoStatusBlock 
= {0}

    PDEVICE_OBJECT pTdiDevice; 

    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); 

     

    
/* 

     * 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. 

     * 

    * 
http://msdn.microsoft.com/library/en-us/network/hh/network/ 

     *        34bldmac_f430860a-9ae2-4379-bffc-6b0a81092e7c.xml.asp?frame=true 

     
*/
 

    pIrp 
= TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, 

          pTdiDevice, pfoConnection, 
&TdiCompletionContext.kCompleteEvent, 

          
&IoStatusBlock); 


    
if(pIrp) 

    


        
/* 

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

         
*/
 

        TdiBuildAssociateAddress(pIrp, pTdiDevice, 

                            pfoConnection, NULL, NULL, hTransportAddress); 


        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 thread, we are a synchronous call so we want    

         * to wait until it has completed. The EVENT that we provided will 

        * be set when the IRP completes. 

         
*/
 


        
if(NtStatus == STATUS_PENDING) 

        


            KeWaitForSingleObject(
&TdiCompletionContext.kCompleteEvent, 

                                   Executive, KernelMode, FALSE, NULL); 

            
/* 

             * Find the Status of the completed IRP 

             
*/
 


            NtStatus 
= IoStatusBlock.Status; 

        }
 


    }
 


    
return NtStatus; 

}
 

posted on 2009-03-23 22:05 iniwf 阅读(372) 评论(0)  编辑 收藏 引用 所属分类: 驱动


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿(2)

随笔分类

随笔档案

收藏夹

IT技术

积分与排名

最新评论

阅读排行榜

评论排行榜