Miranda插件分析

 
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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值