最近换了工作, 新的工作任务是维护一个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里的一个方法