WDF对象上下文1

    其实竹林蹊径中已经详述了WDF_DECLARE_CONTEXT_TYPE_WITH_NAME宏定义,写这篇博文的目的无非是为后文做个引子。toaster中如此使用该宏:

typedef struct _FDO_DATA
{
    WDFWMIINSTANCE WmiDeviceArrivalEvent;
    BOOLEAN     WmiPowerDeviceEnableRegistered;
    TOASTER_INTERFACE_STANDARD BusInterface;
}  FDO_DATA, *PFDO_DATA;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DATA, ToasterFdoGetData)

[1]

其定义如下:

#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]

a).WDF_GET_CONTEXT_TYPE_INFO用来为自定义的结构名生成一个WDF开头的新结构名

#define WDF_GET_CONTEXT_TYPE_INFO(_contexttype) \
    (&WDF_TYPE_NAME_TO_TYPE_INFO(_contexttype))

#define WDF_TYPE_NAME_TO_TYPE_INFO(_contexttype) \
      _WDF_ ## _contexttype ## _TYPE_INFO

[3]

"##"是连接符,连接参数前后,作用和胶水差不多,最终,WDF_GET_CONTEXT_TYPE_INFO(_contexttype)变为:

&_WDF_FDO_DATA_TYPE_INFO

[4]

顺带一提,"#"用于将宏参数变成字符串,后面马上会看到它的应用。

b).WDF_TYPE_DEFAULT_SECTION_NAME也是个简单的宏:
#define WDF_TYPE_DEFAULT_SECTION_NAME ".data"

[5]

初步展开WDF_DECLARE_CONTEXT_TYPE_WITH_NAME,得到这样的中间结果:

WDF_DECLARE_TYPE_AND_GLOBALS(                                           
    FDO_DATA,                                                       
    &_WDF_FDO_DATA_TYPE_INFO,                            
    NULL,                                                               
    ".data")                                      
                                                                        
WDF_DECLARE_CASTING_FUNCTION(FDO_DATA, ToasterFdoGetData)
[6]
这个中间结果还是含有2个宏,还不是最终结果,就像做除法时余数大于除数一样----有待进一步处理。
首先展开WDF_DECLARE_TYPE_AND_GLOBALS:
#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,                                                     \
};                                                                      \

[7]

它做了两件事,1).申明新的类型;2).借助编译器指令__desclspec(allocate(".data")),在".data"节中定义变量。根据反汇编经验,局部变量定义在栈上,定义在".data"节的变量属于全局变量。所以,这个宏顺带着定义并初始化一个结构体全局变量。至于这个结构体的成员,通过source insight来揭示:

typedef struct _WDF_OBJECT_CONTEXT_TYPE_INFO {
    ULONG Size; //结构体大小
    PCHAR ContextName; //上下文的名字字符串,其形式如"DEGVICE_CONTEXT"
    size_t ContextSize;
    PCWDF_OBJECT_CONTEXT_TYPE_INFO UniqueType; //如果该域非空,其值代表上下文的ID
    PFN_GET_UNIQUE_CONTEXT_TYPE EvtDriverGetUniqueContextType;
} WDF_OBJECT_CONTEXT_TYPE_INFO, *PWDF_OBJECT_CONTEXT_TYPE_INFO;

[8]

宏WDF_TYPE_NAME_TO_TYPE_INFO在前文中已经出现过了,算是老熟人了,不再介绍,见[3];至于宏WDF_TYPE_NAME_POINTER_TYPE,其定义是:

#define WDF_TYPE_NAME_POINTER_TYPE(_contexttype) \
    WDF_POINTER_TYPE_ ## _contexttype  

[9]

这段宏的作用是将程序员自定义的上下文结构体单独声明为新的类型。

综上所述,这段宏

WDF_DECLARE_TYPE_AND_GLOBALS(                                           
    FDO_DATA,                                                       
    &_WDF_FDO_DATA_TYPE_INFO,                            
    NULL,                                                               
    ".data") 

[10]

编译后,终于拨云见日般得到如下结果:

typedef FDO_DATA* WDF_POINTER_TYPE_FDO_DATA;
                                                                        
WDF_EXTERN_C                                                            
__declspec(allocate( ".data" ))                                       
__declspec(selectany)
extern const WDF_OBJECT_CONTEXT_TYPE_INFO _WDF_FDO_DATA_TYPE_INFO =
{
    sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO), 
    "FDO_DATA",
    sizeof(FDO_DATA),
    &_WDF_FDO_DATA_TYPE_INFO,
    NULL,
}; 

[11]

嗯,现在还剩下宏:

WDF_DECLARE_CASTING_FUNCTION(FDO_DATA, ToasterFdoGetData)

[12]

尚未展开,这个宏复杂度不高,还请耐心的看下去。其原型如下:

#define WDF_DECLARE_CASTING_FUNCTION(_contexttype, _castingfunction)    \
                                                                        \
WDF_EXTERN_C                                                            \
__drv_aliasesMem                                                        \
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         \
            );                                                          \
}

[13]

上面这段宏中又引用了其他2个宏:WDF_TYPE_NAME_POINTER_TYPE及WDF_GET_CONTEXT_TYPE_INFO,他们初次定义在[3]处;至于WDF_POINTER_TYPE_FDO_DATA,它的定义在[11]处。最终展开后,得到下列结果:

WDF_EXTERN_C                                                            
__drv_aliasesMem                                                        
FDO_DATA*                                
FORCEINLINE                                                             
ToasterFdoGetData(                                                       
   _In_ WDFOBJECT Handle                                                
   )                                                                    
{                                                                       
    return (FDO_DATA*)                  
        WdfObjectGetTypedContextWorker(                                 
            Handle,                                                     
            _WDF_FDO_DATA_TYPE_INFO->UniqueType         
            );                                                          
}

[14]

前面说过_WDF_FDO_DATA_TYPE_INFO是个全局变量,当我们在驱动中如此申明上下文:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DATA, ToasterFdoGetData)
并使用ToastFdoGetData时,实际会调用WdfObjectGetTypedContextWorker。如果想搞清楚这个函数的来龙去脉,请移步下一篇博文: WDF对象上下文2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值