关闭

Miranda插件分析

2316人阅读 评论(0) 收藏 举报
 
1.   概述
Miranda 提供了一套非常灵活的插件机制, 使得用户可以很方便的通过增减插件来添加或去除一些扩展功能. 源码里有一个testplug project, 演示了实现一个Miranda插件的基本方法,下面就通过对testplug project的分析, 来学习Miranda的插件技术.
2.   Miranda插件分类
 基本插件: srmm.dll,clist_modern.dll,dbx_3x.dll
 协议插件: jabber,msn,qq等
 辅助插件: png2dib等
3.   一个插件需要实现的基本接口与变量
3.1.基本变量
 这个通过分析testplug project可以很清楚的看到,一个插件有三个基本全局变量:
 HINSTANCE hInst;        //记录该插件的模块句柄
 PLUGINLINK *pluginLink; //用来登记通用的操作插件的函数指针
 PLUGININFO pluginInfo; //该插件的描述信息
3.2.基本接口
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
       hInst=hinstDLL;
       return TRUE;
}
 
//这是一个菜单命令的响应函数
static int PluginMenuCommand(WPARAM wParam,LPARAM lParam)
{
       MessageBox(NULL,"Just groovy, baby!","Plugin-o-rama",MB_OK);
       return 0;
}
 
__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
{
       return &pluginInfo;
}
 
int __declspec(dllexport) Load(PLUGINLINK *link)
{    
pluginLink=link;
   
//下面这段代码在主菜单里插入菜单项 "&Test Plugin..."
//当单击该菜单项时PluginMenuCommand将被调用
       CLISTMENUITEM mi;
       CreateServiceFunction("TestPlug/MenuCommand",PluginMenuCommand);
       ZeroMemory(&mi,sizeof(mi));
       mi.cbSize=sizeof(mi);
       mi.position=-0x7FFFFFFF;
       mi.flags=0;
       mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
       mi.pszName="&Test Plugin...";
       mi.pszService="TestPlug/MenuCommand";
       CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
 
       return 0;
}
 
int __declspec(dllexport) Unload(void)
{
       return 0;
}
 
3.3.插件如何添加并响应自己的菜单命令
参考3.2 基本接口 中Load函数中加载菜单项 "&Test Plugin..."的方法.
 
4.   主要数据结构:
4.1.PLUGINLINK
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)
} PLUGINLINK;
 
 
extern PLUGINLINK *pluginLink;
#define CreateHookableEvent(a)               pluginLink->CreateHookableEvent(a)
#define DestroyHookableEvent(a)              pluginLink->DestroyHookableEvent(a)
#define NotifyEventHooks(a,b,c)              pluginLink->NotifyEventHooks(a,b,c)
#define HookEventMessage(a,b,c)              pluginLink->HookEventMessage(a,b,c)
#define HookEvent(a,b)                       pluginLink->HookEvent(a,b)
#define UnhookEvent(a)                       pluginLink->UnhookEvent(a)
#define CreateServiceFunction(a,b)           pluginLink->CreateServiceFunction(a,b)
#define CreateTransientServiceFunction(a,b) pluginLink->CreateTransientServiceFunction(a,b)
#define DestroyServiceFunction(a)            pluginLink->DestroyServiceFunction(a)
#define CallService(a,b,c)                   pluginLink->CallService(a,b,c)
#define ServiceExists(a)                     pluginLink->ServiceExists(a)
#define CallServiceSync(a,b,c)               pluginLink->CallServiceSync(a,b,c)
#define CallFunctionAsync(a,b)                         pluginLink->CallFunctionAsync(a,b)
#define SetHookDefaultForHookableEvent(a,b) pluginLink->SetHookDefaultForHookableEvent(a,b)
 
 
4.2.pluginEntry
typedef struct pluginEntry {
       char pluginname[64]; //插件的名称
       unsigned int pclass; // PCLASS_*
       BASIC_PLUGIN_INFO bpi;
       struct pluginEntry * nextclass;
} pluginEntry;
 
4.3.PLUGININFO
typedef struct {
       int cbSize;
       char *shortName;
       DWORD version;
       char *description;
       char *author;
       char *authorEmail;
       char *copyright;
       char *homepage;
       BYTE isTransient;    //leave this as 0 for now
       int replacesDefaultModule;              //one of the DEFMOD_ constants in m_plugins.h or zero
                //if non-zero, this will supress the loading of the specified built-in module
                      //with the implication that this plugin provides back-end-compatible features
} PLUGININFO;
 
4.4.BASIC_PLUGIN_INFO
typedef struct { // can all be NULL
       HINSTANCE hInst;                    
       Miranda_Plugin_Load Load;
       Miranda_Plugin_Unload Unload;
       Miranda_Plugin_Info Info;
       Database_Plugin_Info DbInfo;
       CList_Initialise clistlink;
       PLUGININFO * pluginInfo; // must be freed if hInst==NULL then its a copy
       DATABASELINK * dblink;           // only valid during module being in memory     
} BASIC_PLUGIN_INFO;
 
5.   主要全局变量:
SortedList pluginList = { 0 },
pluginListAddr = { 0 };
PLUGINLINK pluginCoreLink;
char   mirandabootini[MAX_PATH];
static DWORD mirandaVersion;
static pluginEntry * pluginListDb;
static pluginEntry * pluginListUI;
static pluginEntry * pluginList_png2dib = NULL;
static HANDLE hPluginListHeap = NULL;//插件用到的堆
static pluginEntry * pluginDefModList[DEFMOD_HIGHEST+1]; // do not free this memory
static int askAboutIgnoredPlugins;
 
6.   辅助函数:
3.1 HINSTANCE GetInstByAddress( void* codePtr )
    根据一个函数的地址返回函数所在的模块的句柄
   
3.2 enumPlugins(scanPluginsDir, 0, 0);
    枚举所有的插件
   
3.3 checkAPI
    动态加载一个插件,并检查该插件的API函数
    Load,Unload,MirandaPluginInfo 三个基本的API函数
   
 
 
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:330522次
    • 积分:4224
    • 等级:
    • 排名:第7255名
    • 原创:73篇
    • 转载:110篇
    • 译文:0篇
    • 评论:57条
    文章分类