miranda分析报告

 

【文章标题】miranda分析报告

【文章作者】曾健生

【作者邮箱】[email protected]

【作者QQ190678908

【作者博客】http://blog.csdn.net/newjueqi

【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注明文章的出处。

 

*******************************************************************************

前言:

Miranda IM是一款支持多协议的即时通讯客户端,非常简单和小巧,占用很少内存。Miranda IM是基于插件的,强大的插件系统使得Miranda IM非常的灵活。本人就针对Miranda的插件体系作一个简单的分析。

 

(1)   插件管理器

Miranda中,插件是以service的形式存在的。插件可以在插件管理器内部注册服务,其中的几个关键函数说明如下:

1.      HANDLE CreateServiceFunction(const char *name,MIRANDASERVICE serviceProc)

这个函数创建一个新的服务函数,返回值是指向这个服务函数的句柄。其中name参数指向服务名称的字符串,但必须注意了,由于name参数是自己指定的,所以必须保证服务名称的不重复性,不然创建服务会失败,serviceProc是被定义为int ServiceProc(WPARAM wParam,LPARAM lParam)。这个服务函数的句柄在退出时会自动销毁。

服务的保存是以以下结构体的形式保存的,

       typedef struct

{

              DWORD nameHash;    //名称的Hash

              HINSTANCE hOwner;     //模块句柄

              MIRANDASERVICE pfnService;    //回调函数指针

              int isParam;

              LPARAM lParam;

              char name[1];       //服务名称

} TService;

      

       另外管理器内部用结构体维护着一个服务链表

struct

{

       TService** items;

       int count, limit, increment;

       FSortFunc sortFunc;

}static services;

保存着所有被登记的服务

 

 

2.      int DestroyServiceFunction(HANDLE hService)

销毁由CreateServiceFunction创建的服务。

3.      int CallService(const char *name,WPARAM wParam,LPARAM lParam)

调用已经注册的服务。

 

 

(2)   事件机制

1.      HANDLE CreateHookableEvent(const char *name)

创建一个事件,但这个事件名称不一定只能是本插件使用,其它插件也可以用到,这个事件就可用于通讯。返回值是这个事件的句柄。但必须注意了,由于name参数是自己指定的,所以必须保证事件名称的不重复性,不然创建事件会失败。这个事件的句柄在退出时会自动销毁。

事件是保存是以以下结构体的形式保存的

typedef struct

{

char name[ MAXMODULELABELLENGTH ];  //事件名称

int  id; //事件ID

int  subscriberCount;       //事件的回调函数的个数

THookSubscriber* subscriber; //事件的回调函数链表,指向所有相应这个事件的函数

MIRANDAHOOK pfnHook; //事件的默认回调函数

}THook;

 

事件的回调函数链的结构的如下

typedef struct

{

MIRANDAHOOK pfnHook;

HINSTANCE hOwner;

HWND hwnd;

UINT message;

}THookSubscriber;

 

另外管理器内部用结构体维护着一个事件链表,管理着所有事件

struct

{

THook** items;

int count, limit, increment;

FSortFunc sortFunc;

}static hooks;

 

 

2.      HANDLE HookEvent(const char *name,MIRANDAHOOK hookProc)

       将一个事件与一个回调函数指针绑定在一起

 

. int DestroyHookableEvent(HANDLE hEvent)

    销毁由CreateHookableEvent函数创建的事件。

. int NotifyEventHooks(HANDLE hEvent,WPARAM wParam,LPARAM lParam)

    产生特定的事件并调用函数来实现事件回调。其内部实现是进一步调用int CallHookSubscribers( HANDLE hEvent, WPARAM wParam, LPARAM lParam )函数的。

 

. CallHookSubscribers( HANDLE hEvent, WPARAM wParam, LPARAM lParam )

       调用THookSubscriber* subscriber里的函数。

 

3)插件本身

插件里暴露了以下几个接口:

1.   int __declspec(dllexport) Load(PLUGINLINK *link)

插件管理器装载插件时调用的接口。其中,PLUGINLINK *link指向的结构体如下:

typedef struct {

       HANDLE (*CreateHookableEvent)(const char *);

       int (*DestroyHookableEvent)(HANDLE);

       int (*NotifyEventHooks)(HANDLE,WPARAM,LPARAM);

       HANDLE (*HookEvent)(const char *,MIRANDAHOOK);

       HANDLE (*HookEventMessage)(const char *,HWND,UINT);

       int (*UnhookEvent)(HANDLE);

       HANDLE (*CreateServiceFunction)(const char *,MIRANDASERVICE);

       HANDLE (*CreateTransientServiceFunction)(const char *,MIRANDASERVICE);

       int (*DestroyServiceFunction)(HANDLE);

       int (*CallService)(const char *,WPARAM,LPARAM);

       int (*ServiceExists)(const char *);                //v0.1.0.1+

       int (*CallServiceSync)(const char *,WPARAM,LPARAM);            //v0.3.3+

       int (*CallFunctionAsync) (void (__stdcall *)(void *), void *);   //v0.3.4+

       int (*SetHookDefaultForHookableEvent) (HANDLE, MIRANDAHOOK); // v0.3.4 (2004/09/15)

       HANDLE (*CreateServiceFunctionParam)(const char *,MIRANDASERVICEPARAM,LPARAM); // v0.7+ (2007/04/24)

       int (*NotifyEventHooksDirect)(HANDLE,WPARAM,LPARAM); // v0.7+

} PLUGINLINK;

 

       由此可知,插件可以很方便的在插件管理器里注册服务和注册事件。

 

2.   int __declspec(dllexport) Unload(void)

插件管理器卸载插件时调用的函数。

3.   __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)

   获取插件的信息,指向的结构体如下:

typedef struct {

       int cbSize;   //

       char *shortName; //插件名称

       DWORD version; //版本

       char *description; //描述

       char *author; //作者

       char *authorEmail; //EMAILL

       char *copyright; // 版权声明

       char *homepage; //主页

       BYTE flags;         // right now the only flag, UNICODE_AWARE, is recognized here

    int replacesDefaultModule;     //one of the DEFMOD_ constants in m_plugins.h or zero

     /***********  WILL BE DEPRECATED in 0.8 * *************/

    MUUID uuid; // 0.8.版本才用到

} PLUGININFOEX;

 

 

4.   __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)

插件的接口描述,其中Miranda内部已经自定义一系列的接口

 

 

结语

    Miranda是通过插件管理器,事件机制,插件本身这三者构建出一个庞大的插件体系,通过这个开放式的框架,吸引了无数的开发人员投入了Miranda的阵营,开发出500多款插件,造就了Miranda的强大。从Miranda的例子可以说明开放式框架的魅力。

 

 

 

你可能感兴趣的:(框架,struct,service,deprecated,通讯,Constants)