最近換了工作, 新的工作任務是維護一個IM系統,由於一些原因還沒有拿到IM的源碼,所以這段時間就研究一下開源的IM客戶端miranda,初步瞭解一下,就感覺miranda是一個很優秀的系統,靈活的插件結構,使的miranda系統非常的靈活,也方便世界各地的程序員實現各種不同的功能,以後我會陸續把自己分析的筆記貼出來,同時也歡迎分析過這個系統的朋友一起來參與討論,指出我理解的不正確的地方.
0 概述
miranda系統中預定義了一些事件,例如:
ME_SYSTEM_SHUTDOWN,
ME_SYSTEM_PRESHUTDOWN,
ME_SYSTEM_MODULESLOADED,
ME_SYSTEM_OKTOEXIT
全局靜態變量*hook中維護了這些事件的數組,數組中每一項都對應一個事件,
每種事件不同的功能模塊可能要做不同的處理,所以一個事件可能有多個處理函數,
因此用*subscriber來保存這些處理函數的指針和參數,在需要的情況下用NotifyEventHooks
觸發一個事件,就會依次調用該事件所有的處理函數,這些操作實際上還是同步調用的,而且是
開發人員主動調用的,所以這裏的Event與window裏的事件含義是不同的.
SERVICE也不是windows service或web service的概念.廣義上的意思是一樣的,都是提供了一些服務供用戶調用,
miranda裏的service按照這個思想實現了自己的一套機制,這個套路和HOOK的套路是一樣的,都是維護一個一維數組,將所有的功能都登記在冊,每一項服務都有一個名字和一個hash code,然後掛接一個函數指針,及函數參數,通過CallService可以調用一個服務,與HOOK不同的是每一項服務只對應一個函數
1 主要數據結構及變量
1.1 HOOK
typedef struct {
MIRANDAHOOK pfnHook;//回調函數指針
HINSTANCE hOwner; //回調函數所在模塊的句柄
HWND hwnd;
UINT message;
} THookSubscriber;
typedef struct {
char name[MAXMODULELABELLENGTH];//一個hook的名稱,最大64個字符
DWORD hookHash; //該hook的hash碼
int subscriberCount; //記錄有多少個處理函數
THookSubscriber *subscriber; //一個事件可以掛接有多個方法,比如ME_SYSTEM_SHUTDOWN的時候,
//不同的模塊需要做不同的處理,就可以通過掛接自己的方法上去即可
MIRANDAHOOK pfnHook; //這個好像沒有用到,估計是最初設計的時候考慮一個事件對應一個處理函數,
//實際開發的時候發現一個事件需要有多個處理函數,這些函數的參數又都不同,
//所以僅僅靠這一個函數指針保存不了這麼多信息,所以催生出了THookSubscriber *subscriber
//這些僅僅是猜測
} THookList;
typedef struct {
int hookId;
HANDLE hDoneEvent;
WPARAM wParam;
LPARAM lParam;
int result;
} THookToMainThreadItem;
static THookList *hook;
static CRITICAL_SECTION csHooks;
static int hookCount;
1.2 SERVICE
typedef struct {
char name[MAXMODULELABELLENGTH];//服務的名字
DWORD nameHash; //服務的hash碼
HINSTANCE hOwner; //模塊句柄
MIRANDASERVICE pfnService; //回調函數指針
} TServiceList;
typedef struct {
HANDLE hDoneEvent;
WPARAM wParam;
LPARAM lParam;
int result;
const char *name;
} TServiceToMainThreadItem;
static TServiceList *service;
static int serviceCount;
static CRITICAL_SECTION csServices;
2 主要函數說明
2.1 NameHashFunction(name);
根據名字計算出hash碼
2.2 CreateHookableEvent(ME_SYSTEM_SHUTDOWN);
在THookList *hook裏登記一項,並返回一個handle,實際是該項在hook數組裏的位置
NotifyEventHooks將通過這個句柄來調用這個函數
2.3 HookEvent(ME_SYSTEM_SHUTDOWN,SystemShutdownProc);
將一個hook與一個回調函數指針綁定在一起
2.4 NotifyEventHooks(hModulesLoadedEvent,0,0);
觸發一個事件,hModulesLoadedEvent實際是該事件在hook裏的位置,該函數調用CallHookSubscribers
2.5 CallHookSubscribers(hEvent,wParam,lParam)
調用一個hook函數,hEvent實際是該事件在hook裏的位置,
該函數根據hook[hookId].subscriberCount循環調用每一個掛接的函數
2.6 CreateServiceFunction(MS_SYSTEM_FORK_THREAD,ForkThreadService);
在static TServiceList *service裏動態加入一項,並與指定 的毀掉函數指針綁定
2.7 int CallService(const char *name,WPARAM wParam,LPARAM lParam);
根據名字調用TServiceList *service裏的一個方法