天天看點

WDF基本對象和句柄定義

1          對象和句柄定義

1.1         struct FX_OBJECT_INFO數組FxObjectsInfo:

Fxobjectinfokm.cpp中定義了一個結構體FX_OBJECT_INFO數組FxObjectsInfo[],WDF自定義的對象,如WDFDRIVER、WDFDEVICE等都在該數組中登記對應的資訊。

typedef struct _FX_OBJECT_INFO {
    const CHAR* Name;  //WDF對象名
    const CHAR* HandleName; 
    USHORT Size; //對象大小
    USHORT ObjectType; //對象類型,enum類型值
} FX_OBJECT_INFO, *PFX_OBJECT_INFO;      

         WDF使用分别使用宏FX_INTERNAL_OBJECT_INFO_ENTRY和宏FX_INTERNAL_OBJECT_INFO_ENTRY初始化結構體FX_OBJECT_INFO數組FxObjectsInfo。

FX_OBJECT_INFO FxObjectsInfo[] = {
   FX_INTERNAL_OBJECT_INFO_ENTRY(FxObject, FX_TYPE_OBJECT),
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDriver,FX_TYPE_DRIVER, WDFDRIVER),
};      

用于初始化FxObjectsInfo數組的宏,其定義如下:

#define FX_INTERNAL_OBJECT_INFO_ENTRY(_obj,_type)  \
{ #_obj, NULL, sizeof(_obj), _type, }
 
#define FX_EXTERNAL_OBJECT_INFO_ENTRY(_obj,_type, _handletype) \
    {#_obj,                                                   \
     (const CHAR*) (_handletype) #_handletype,                 \
     sizeof(_obj),                                             \
     _type,                                                   \
}      

我們知道,##在宏定義中有連接配接兩個操作符的作用,#在宏定義中起到将操作符字元化的作用,例如:

#define example(instr) printf("theinput string is:\t%s\n",#instr)
#define example1(instr) #instr      

當使用該宏定義時:

example(abc);  在編譯時将會展開成:printf("theinput string is:\t%s\n","abc");
string str=example1(abc);  将會展成:stringstr="abc";      

參照上面的例子,将上面宏運算FX_INTERNAL_OBJECT_INFO_ENTRY(FxObject,FX_TYPE_OBJECT)展開,得到如下結果:

FX_OBJECT_INFOFxObjectsInfo[] = {
{ “FxObject”,NULL,sizeof(FxObject),FX_TYPE_OBJECT },
…
};
         最終,FxObjectsInfo[0].Name指向”FxObject”, FxObjectsInfo[0].HandleName為空,
FxObjectsInfo[0].Size=4 FxObjectsInfo[0].ObjectType=枚舉值FX_TYPE_OBJECT。
         在繼續展開FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDriver,FX_TYPE_DRIVER, WDFDRIVER)宏之前,先看下WDFDRIVER的定義。
 
#ifdef STRICT
typedef void *HANDLE;
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) structname##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) structname##__{int unused;}; typedef struct name##__ *name
#endif
 
Windows首先聲明HANDLE為void*指針類型,然後,通過宏DECLARE_HANDLE定義了WDFDRIVER__結構體:
Struct WDFDRIVER__
{
         Intunused;
};      

緊接着,聲明了WDFDRIVER為WDFDRIVER__*指針類型,對于指針而言,HANDLE和WDFDRIVER是等價的(可以互相轉換)。這有點類似于MFC,它定義了各種句柄類型,如:

DECLARE_HANDLE(HMODULE); 

DECLARE_HANDLE(HINSTANCE); 

DECLARE_HANDLE(HGLOBAL); 

DECLARE_HANDLE(HDC); 

DECLARE_HANDLE(HWND); 

DECLARE_HANDLE(HMENU); 

在實際編碼過程中,可能以以下形式

HWND hWnd

上面這段代碼等價于:

struct HWND* hWnd = FindWindow(…);

如果做一個簡單的轉換,可以将struct HWND*以不損失精度為代價,直接轉換為void*(即HANDLE)。是以,就本質而言,DECLARE_HANDLE宏僅僅為void*類型新建立一個類型名。

1.2         WDF對象和WDM對象的對應關系

雖然用WDF架構開發驅動,但隐約能看到背後WDM的影子。WDF對象亦是如此,就像我們會不自覺的把WDFDRIVER對象和DRIVER_OBJECT對象互相關聯起來。證明兩者之間确實存在某種關聯性,我們還是需要從: FX_INTERNAL_OBJECT_INFO_ENTRY/FX_EXTERNAL_OBJECT_INFO_ENTRY兩個宏入手。

         在這兩個宏中都有一段計算結構體大小的代碼:

#define FX_EXTERNAL_OBJECT_INFO_ENTRY(_obj,_type, _handletype) \
    {#_obj,                                                   \
     (const CHAR*) (_handletype) #_handletype,                 \
     sizeof(_obj),                                             \
     _type,                                                   \
}
 
#define FX_INTERNAL_OBJECT_INFO_ENTRY(_obj,_type)  \
{ #_obj, NULL, sizeof(_obj),_type, }      

他們都計算第一個宏參數_obj的大小。對于其他宏參數,不外乎是enum類型和HANDLE類型,是以,我們可以确定,第一個宏參數一定是WDF定義的各種對象類型,即FxObject、FxDriver才是真正的WDF對象。

         FxObject是WDF自定義的對象類型,沒有對應的WDM對象,是以先來尋找FxDriver的定義以及對應的WDM對象。

class FxDriver : public FxNonPagedObject,public IFxHasCallbacks
{
friend class FxDevice;
friend class FxPackage;
friend class FxWmiIrpHandler;
 
private:
 
    MxDriverObjectm_DriverObject;
UNICODE_STRING m_RegistryPath;
….
};      

WDF定義了一個FxDriver類,類成員變量    MxDriverObject m_DriverObject和UNICODE_STRINGm_RegistryPath的名字很容易讓我們聯想到WDM中傳給驅動入口函數DriverEntry的兩個參數類型DRIVER_OBJECT和UNICODE_STRING。再跟進MxDriverObject的定義,它依然是一個WDF類:

class MxDriverObject
{
private:
MdDriverObjectm_DriverObject;
…
};