From 3936ebbc665c9653d9f62527c1e136944d52e2ca Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 18 Apr 2018 19:19:56 +0300 Subject: ability to dynamically load / unload protocol plugins --- src/mir_app/src/miranda.h | 4 +++- src/mir_app/src/newplugins.cpp | 1 + src/mir_app/src/pluginopts.cpp | 10 ++++++++++ src/mir_app/src/proto_accs.cpp | 43 ++++++++++++++++++++++++++++++++++-------- src/mir_app/src/proto_opts.cpp | 18 +++--------------- src/mir_app/src/protocols.cpp | 16 ++++++++++++---- 6 files changed, 64 insertions(+), 28 deletions(-) (limited to 'src/mir_app') diff --git a/src/mir_app/src/miranda.h b/src/mir_app/src/miranda.h index 6eeeaffa46..81360cc8fb 100644 --- a/src/mir_app/src/miranda.h +++ b/src/mir_app/src/miranda.h @@ -157,7 +157,7 @@ PROTOACCOUNT* __fastcall Proto_GetAccount(MCONTACT hContact); PROTO_INTERFACE* AddDefaultAccount(const char *szProtoName); int FreeDefaultAccount(PROTO_INTERFACE* ppi); -bool ActivateAccount(PROTOACCOUNT *pa); +bool ActivateAccount(PROTOACCOUNT *pa, bool bIsDynamic); void EraseAccount(const char *pszProtoName); void DeactivateAccount(PROTOACCOUNT *pa, bool bIsDynamic, bool bErase); void UnloadAccount(PROTOACCOUNT *pa, bool bIsDynamic, bool bErase); @@ -166,6 +166,8 @@ void OpenAccountOptions(PROTOACCOUNT *pa); void LoadDbAccounts(void); void WriteDbAccounts(void); +void KillModuleAccounts(HINSTANCE); + INT_PTR CallProtoServiceInt(MCONTACT hContact, const char* szModule, const char* szService, WPARAM wParam, LPARAM lParam); INT_PTR stubChainRecv(WPARAM, LPARAM); diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp index 4497d195bd..cfeca33159 100644 --- a/src/mir_app/src/newplugins.cpp +++ b/src/mir_app/src/newplugins.cpp @@ -349,6 +349,7 @@ int Plugin_UnloadDyn(pluginEntry *p) if (CallPluginEventHook(p->bpi.hInst, hOkToExitEvent, 0, 0) != 0) return FALSE; + KillModuleAccounts(p->bpi.hInst); KillModuleSubclassing(p->bpi.hInst); CallPluginEventHook(p->bpi.hInst, hPreShutdownEvent, 0, 0); diff --git a/src/mir_app/src/pluginopts.cpp b/src/mir_app/src/pluginopts.cpp index 9ce4923e2a..df8868bc34 100644 --- a/src/mir_app/src/pluginopts.cpp +++ b/src/mir_app/src/pluginopts.cpp @@ -184,6 +184,16 @@ static bool LoadPluginDynamically(PluginListItemData *dat) if (CallPluginEventHook(pPlug->bpi.hInst, hModulesLoadedEvent, 0, 0) != 0) goto LBL_Error; + // if dynamically loaded plugin contains protocols, initialize the corresponding accounts + for (auto &pd : g_arProtos) { + if (pd->hInst != pPlug->bpi.hInst) + continue; + + for (auto &pa : accounts) + if (pa->ppro == nullptr && !mir_strcmp(pa->szProtoName, pd->szName)) + ActivateAccount(pa, true); + } + dat->hInst = pPlug->bpi.hInst; NotifyFastHook(hevLoadModule, (WPARAM)pPlug->bpi.pluginInfo, (LPARAM)pPlug->bpi.hInst); return true; diff --git a/src/mir_app/src/proto_accs.cpp b/src/mir_app/src/proto_accs.cpp index 8343314e05..8e05ba2c48 100644 --- a/src/mir_app/src/proto_accs.cpp +++ b/src/mir_app/src/proto_accs.cpp @@ -266,7 +266,7 @@ int LoadAccountsModule(void) if (!pa->IsEnabled()) continue; - if (!ActivateAccount(pa)) + if (!ActivateAccount(pa, false)) pa->bDynDisabled = true; } @@ -286,7 +286,7 @@ static HANDLE CreateProtoServiceEx(const char* szModule, const char* szService, return CreateServiceFunctionObj(tmp, pFunc, param); } -bool ActivateAccount(PROTOACCOUNT *pa) +bool ActivateAccount(PROTOACCOUNT *pa, bool bIsDynamic) { PROTOCOLDESCRIPTOR* ppd = Proto_IsProtocolLoaded(pa->szProtoName); if (ppd == nullptr) @@ -303,6 +303,14 @@ bool ActivateAccount(PROTOACCOUNT *pa) if (ppi->m_hProtoIcon == nullptr) ppi->m_hProtoIcon = IcoLib_IsManaged(Skin_LoadProtoIcon(pa->szModuleName, ID_STATUS_ONLINE)); ppi->m_iDesiredStatus = ppi->m_iStatus = ID_STATUS_OFFLINE; + + if (bIsDynamic) { + if (bModulesLoadedFired) + pa->ppro->OnEvent(EV_PROTO_ONLOAD, 0, 0); + if (!db_get_b(0, "CList", "MoveProtoMenus", true)) + pa->ppro->OnEvent(EV_PROTO_ONMENU, 0, 0); + pa->bDynDisabled = false; + } return true; } @@ -374,18 +382,20 @@ static int DeactivationThread(DeactivationThreadParam* param) void DeactivateAccount(PROTOACCOUNT *pa, bool bIsDynamic, bool bErase) { - if (pa->ppro == nullptr) { - if (bErase) - EraseAccount(pa->szModuleName); - return; - } - if (pa->hwndAccMgrUI) { DestroyWindow(pa->hwndAccMgrUI); pa->hwndAccMgrUI = nullptr; pa->bAccMgrUIChanged = FALSE; } + pa->iIconBase = -1; + + if (pa->ppro == nullptr) { + if (bErase) + EraseAccount(pa->szModuleName); + return; + } + DeactivationThreadParam *param = new DeactivationThreadParam; param->ppro = pa->ppro; param->fnUninit = GetProtocolDestructor(pa->szProtoName); @@ -400,6 +410,23 @@ void DeactivateAccount(PROTOACCOUNT *pa, bool bIsDynamic, bool bErase) ///////////////////////////////////////////////////////////////////////////////////////// +void KillModuleAccounts(HINSTANCE hInst) +{ + for (auto &pd : g_arProtos.rev_iter()) { + if (pd->hInst != hInst) + continue; + + for (auto &pa : accounts.rev_iter()) { + if (!mir_strcmp(pa->szProtoName, pd->szName)) { + DeactivateAccount(pa, false, false); + pa->bDynDisabled = true; + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + void EraseAccount(const char *pszModuleName) { // remove protocol contacts first diff --git a/src/mir_app/src/proto_opts.cpp b/src/mir_app/src/proto_opts.cpp index 239de7fbeb..70fdd82876 100644 --- a/src/mir_app/src/proto_opts.cpp +++ b/src/mir_app/src/proto_opts.cpp @@ -82,13 +82,7 @@ MIR_APP_DLL(PROTOACCOUNT*) Proto_CreateAccount(const char *pszInternal, const ch db_set_s(0, pa->szModuleName, "AM_BaseProto", pszBaseProto); accounts.insert(pa); - if (ActivateAccount(pa)) { - if (bModulesLoadedFired) - pa->ppro->OnEvent(EV_PROTO_ONLOAD, 0, 0); - if (!db_get_b(0, "CList", "MoveProtoMenus", true)) - pa->ppro->OnEvent(EV_PROTO_ONMENU, 0, 0); - } - + ActivateAccount(pa, true); WriteDbAccounts(); NotifyEventHooks(hAccListChanged, PRAC_ADDED, (LPARAM)pa); return pa; @@ -457,14 +451,8 @@ public: return; pa->bIsEnabled = !pa->bIsEnabled; - if (pa->bIsEnabled) { - if (ActivateAccount(pa)) { - if (bModulesLoadedFired) - pa->ppro->OnEvent(EV_PROTO_ONLOAD, 0, 0); - if (!db_get_b(0, "CList", "MoveProtoMenus", TRUE)) - pa->ppro->OnEvent(EV_PROTO_ONMENU, 0, 0); - } - } + if (pa->bIsEnabled) + ActivateAccount(pa, true); else { if (pa->iRealStatus >= ID_STATUS_ONLINE) { wchar_t buf[200]; diff --git a/src/mir_app/src/protocols.cpp b/src/mir_app/src/protocols.cpp index 3384bef71d..7e0b49cdfc 100644 --- a/src/mir_app/src/protocols.cpp +++ b/src/mir_app/src/protocols.cpp @@ -106,16 +106,24 @@ MIR_APP_DLL(int) Proto_RegisterModule(PROTOCOLDESCRIPTOR *pd) if (pd->cbSize != sizeof(PROTOCOLDESCRIPTOR) && pd->cbSize != PROTOCOLDESCRIPTOR_V3_SIZE) return 1; - MBaseProto *p = (MBaseProto*)mir_calloc(sizeof(MBaseProto)); - p->cbSize = pd->cbSize; - p->szName = mir_strdup(pd->szName); + bool bTryActivate = false; + MBaseProto tmp; + tmp.szName = (char*)pd->szName; + MBaseProto *p = g_arProtos.find(&tmp); + if (p == nullptr) { + p = (MBaseProto*)mir_calloc(sizeof(MBaseProto)); + p->cbSize = pd->cbSize; + p->szName = mir_strdup(pd->szName); + g_arProtos.insert(p); + } + else bTryActivate = true; + p->type = pd->type; p->hInst = pd->hInst; if (pd->cbSize == sizeof(PROTOCOLDESCRIPTOR)) { p->fnInit = pd->fnInit; p->fnUninit = pd->fnUninit; } - g_arProtos.insert(p); if (p->fnInit == nullptr && (p->type == PROTOTYPE_PROTOCOL || p->type == PROTOTYPE_VIRTUAL)) { // let's create a new container -- cgit v1.2.3