WDF驱动中,当我们写下WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XXX, YYY)到底发生了什么?

来源:互联网 发布:python 自然语言 编辑:程序博客网 时间:2024/04/28 14:36
WDF驱动中,当我们写下WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DATA, FdoGetData)
到底发生了什么?
看下wdfobject.h文件中的WDF_DECLARE_CONTEXT_TYPE_WITH_NAME的宏定义:
#define WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(_contexttype, _castingfunction) \WDF_DECLARE_TYPE_AND_GLOBALS(                                              \    _contexttype,                                                          \    WDF_GET_CONTEXT_TYPE_INFO(_contexttype),                               \    NULL,                                                                  \    WDF_TYPE_DEFAULT_SECTION_NAME)                                         \WDF_DECLARE_CASTING_FUNCTION(_contexttype, _castingfunction)
有点眼花,其中又调用了2个宏,所以继续看这2个宏定义:
#define WDF_DECLARE_TYPE_AND_GLOBALS(_contexttype, _UniqueType, _GetUniqueType, _section)\typedef _contexttype* WDF_TYPE_NAME_POINTER_TYPE(_contexttype);         \WDF_EXTERN_C __declspec(allocate( _section )) __declspec(selectany) extern const WDF_OBJECT_CONTEXT_TYPE_INFO WDF_TYPE_NAME_TO_TYPE_INFO(_contexttype) =  \{                                                                       \    sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO),                               \    #_contexttype,                                                      \    sizeof(_contexttype),                                               \    _UniqueType,                                                        \    _GetUniqueType,                                                     \};                                        

其中还有宏定义,挨个看看:
1 typedef _contexttype* WDF_TYPE_NAME_POINTER_TYPE(_contexttype);这一句
  变换:
  typedef FDO_DATA* WDF_TYPE_NAME_POINTER_TYPE(_contexttype);这一句
  再变换:
  typedef FDO_DATA * WDF_POINTER_TYPE_FDO_DATA
  注意:#define WDF_TYPE_NAME_POINTER_TYPE(_contexttype) WDF_POINTER_TYPE_ ## _contexttype
        #define WDF_TYPE_NAME_TO_TYPE_INFO(_contexttype) _WDF_ ## _contexttype ## _TYPE_INFO
  就是个字符串连接
2 看下面那个定义,从编译符看是个结构体类型
  其中 #define WDF_EXTERN_C       extern "C"
  而__declspec(allocate( _section ))编译器指令,是要求编译器分配一个段名_section
  而__declspec(selectany)编译器指令,是告诉编译器程序要在头文件里初始化
  那么初始化什么呢?去掉编译指令,替换参数后:

 大概意思是,初始化了一个结构体,用变量_WDF_FDO_DATA_TYPE_INFO代表这个结构体
 以下是这个结构体的定义:
typedef struct _WDF_OBJECT_CONTEXT_TYPE_INFO {    ULONG Size;    PCHAR ContextName;    size_t ContextSize;    PCWDF_OBJECT_CONTEXT_TYPE_INFO UniqueType;    PFN_GET_UNIQUE_CONTEXT_TYPE EvtDriverGetUniqueContextType;} WDF_OBJECT_CONTEXT_TYPE_INFO, *PWDF_OBJECT_CONTEXT_TYPE_INFO;
 
 已经有点迷失了,先看最初的第二个宏定义:
wdfobject.h文件中:
 WDF_DECLARE_CASTING_FUNCTION(_contexttype, _castingfunction) #define WDF_DECLARE_CASTING_FUNCTION(_contexttype, _castingfunction)    \ __drv_aliasesMem                                                        \ WDF_EXTERN_C                                                            \ WDF_TYPE_NAME_POINTER_TYPE(_contexttype)                                \ FORCEINLINE                                                             \ _castingfunction(                                                       \   __in WDFOBJECT Handle                                                     \ )                                                                    \{                                                                       \    return (WDF_TYPE_NAME_POINTER_TYPE(_contexttype))                   \        WdfObjectGetTypedContextWorker(                                 \            Handle,                                                     \            WDF_GET_CONTEXT_TYPE_INFO(_contexttype)->UniqueType         \            );                                                          \}

 也不简单。
 __drv_aliasesMem 意思是说返回值是分配好的一块内存,这个内存是在函数内部分配的
 看WDF_GET_CONTEXT_TYPE_INFO(_contexttype)->UniqueType,拆成2句
 WDF_GET_CONTEXT_TYPE_INFO(_contexttype) 这个宏定义如下:
 #define WDF_GET_CONTEXT_TYPE_INFO(_contexttype) \
    (&WDF_TYPE_NAME_TO_TYPE_INFO(_contexttype))
 就是_WDF_FDO_DATA_TYPE_INFO(这个在上面被初始化了)的引用
 再一句,就是取得这个结构体的成员UniqueType,这个成员在前面被初始化为NULL
 
 过滤掉那些显而易见的编译指令,替换宏后:
 WDF_POINTER_TYPE_FDO_DATA FdoGetData(WDFOBJECT Handle) {  return (WDF_POINTER_TYPE_FDO_DATA)WdfObjectGetTypedContextWorker(Handle, NULL); }

 这里有遇到了障碍,WdfObjectGetTypedContextWorker是什么?
 打开帮助,明确说明是内部使用的。
 随便找个用wdf写的驱动文件,用ida打开后,
.text:00010D60 WdfObjectGetTypedContextWorker proc near ; CODE XREF: FdoGetData+Fp.text:00010D60.text:00010D60 arg_0           = dword ptr  8.text:00010D60 arg_4           = dword ptr  0Ch.text:00010D60.text:00010D60                 mov     edi, edi.text:00010D62                 push    ebp.text:00010D63                 mov     ebp, esp.text:00010D65                 mov     eax, [ebp+arg_4].text:00010D68                 push    eax.text:00010D69                 mov     edx, [ebp+arg_0].text:00010D6C                 mov     ecx, WdfDriverGlobals.text:00010D72                 call    dword_16540.text:00010D78                 pop     ebp.text:00010D79                 retn    8.text:00010D79 WdfObjectGetTypedContextWorker endp
 哦,调用了一个dword_16540,ecx寄存器传递:WdfDriverGlobals,edx寄存器传递:Handle,栈传递:NULL
 使用ecx和edx传递参数,应该是fastcall调用方式
 而dword_16540地址处却是一大片的0,应该是运行时会变化的。