summaryrefslogtreecommitdiff
path: root/src/core/modules.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/modules.cpp')
-rw-r--r--src/core/modules.cpp632
1 files changed, 2 insertions, 630 deletions
diff --git a/src/core/modules.cpp b/src/core/modules.cpp
index ba846d0fd4..11e93f1354 100644
--- a/src/core/modules.cpp
+++ b/src/core/modules.cpp
@@ -2,7 +2,7 @@
Miranda IM: the free IM client for Microsoft* Windows*
-Copyright 2000-2009 Miranda ICQ/IM project,
+Copyright 2000-2009 Miranda ICQ/IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
@@ -11,7 +11,7 @@ modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
-This program is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
@@ -23,66 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "commonheaders.h"
#include <m_plugins.h>
-// list of hooks
-
-static int compareHooks(const THook* p1, const THook* p2)
-{
- return strcmp(p1->name, p2->name);
-}
-
-static LIST<THook> hooks(50, compareHooks);
-
-struct THookToMainThreadItem
-{
- THook* hook;
- HANDLE hDoneEvent;
- WPARAM wParam;
- LPARAM lParam;
- int result;
-};
-
-// list of services
-
-struct TService
-{
- DWORD nameHash;
- HINSTANCE hOwner;
- union {
- MIRANDASERVICE pfnService;
- MIRANDASERVICEPARAM pfnServiceParam;
- MIRANDASERVICEOBJ pfnServiceObj;
- MIRANDASERVICEOBJPARAM pfnServiceObjParam;
- };
- int flags;
- LPARAM lParam;
- void* object;
- char name[1];
-};
-
-LIST<TService> services(100, NumericKeySortT);
-
-typedef struct
-{
- HANDLE hDoneEvent;
- WPARAM wParam;
- LPARAM lParam;
- int result;
- const char *name;
-}
- TServiceToMainThreadItem;
-
// other static variables
static BOOL bServiceMode = FALSE;
-static CRITICAL_SECTION csHooks, csServices;
static DWORD mainThreadId;
-static int hookId = 1;
static HANDLE hMainThread;
static HANDLE hMissingService;
-static THook *pLastHook = NULL;
-
-HINSTANCE GetInstByAddress(void* codePtr);
-
-void LangPackDropUnusedItems(void);
void ParseCommandLine(); // core: IDD_WAITRESTART
int LoadSystemModule(void); // core: m_system.h services
@@ -134,7 +79,6 @@ void UnloadClcModule(void);
void UnloadContactListModule(void);
void UnloadEventsModule(void);
void UnloadIdleModule(void);
-void UnloadLangPackModule(void);
void UnloadSslModule(void);
void UnloadNetlibModule(void);
void UnloadNewPlugins(void);
@@ -236,576 +180,4 @@ void UnloadDefaultModules(void)
UnloadUpdateNotifyModule();
UnloadNetlibModule();
UnloadSslModule();
- UnloadLangPackModule();
-}
-
-int InitialiseModularEngine(void)
-{
- InitializeCriticalSection(&csHooks);
- InitializeCriticalSection(&csServices);
-
- mainThreadId=GetCurrentThreadId();
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
-
- hMissingService = CreateHookableEvent(ME_SYSTEM_MISSINGSERVICE);
- return 0;
-}
-
-void DestroyModularEngine(void)
-{
- int i;
- THook* p;
- EnterCriticalSection(&csHooks);
- for (i=0; i < hooks.getCount(); i++) {
- p = hooks[i];
- if (p->subscriberCount)
- mir_free(p->subscriber);
- DeleteCriticalSection(&p->csHook);
- mir_free(p);
- }
- hooks.destroy();
- LeaveCriticalSection(&csHooks);
- DeleteCriticalSection(&csHooks);
-
- EnterCriticalSection(&csServices);
- for (i=0; i < services.getCount(); i++)
- mir_free(services[i]);
-
- services.destroy();
- LeaveCriticalSection(&csServices);
- DeleteCriticalSection(&csServices);
- CloseHandle(hMainThread);
-}
-
-///////////////////////////////HOOKS
-
-HANDLE CreateHookableEvent(const char *name)
-{
- THook* ret;
- int idx;
-
- if (name == NULL)
- return NULL;
-
- EnterCriticalSection(&csHooks);
- if ((idx = hooks.getIndex((THook*)name)) != -1) {
- LeaveCriticalSection(&csHooks);
- return NULL;
- }
-
- ret = (THook*)mir_alloc(sizeof(THook));
- strncpy(ret->name, name, sizeof(ret->name)); ret->name[ MAXMODULELABELLENGTH-1 ] = 0;
- ret->id = hookId++;
- ret->subscriberCount = 0;
- ret->subscriber = NULL;
- ret->pfnHook = NULL;
- InitializeCriticalSection(&ret->csHook);
- hooks.insert(ret);
-
- LeaveCriticalSection(&csHooks);
- return (HANDLE)ret;
-}
-
-int DestroyHookableEvent(HANDLE hEvent)
-{
- int idx;
- THook* p;
-
- EnterCriticalSection(&csHooks);
- if (pLastHook == (THook*)hEvent)
- pLastHook = NULL;
-
- if ((idx = hooks.getIndex((THook*)hEvent)) == -1) {
- LeaveCriticalSection(&csHooks);
- return 1;
- }
- p = hooks[idx];
- if (p->subscriberCount) {
- mir_free(p->subscriber);
- p->subscriber = NULL;
- p->subscriberCount = 0;
- }
- hooks.remove(idx);
- DeleteCriticalSection(&p->csHook);
- mir_free(p);
-
- LeaveCriticalSection(&csHooks);
- return 0;
-}
-
-int SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook)
-{
- THook* p = (THook*)hEvent;
-
- EnterCriticalSection(&csHooks);
- if (hooks.getIndex(p) != -1)
- p->pfnHook = pfnHook;
- LeaveCriticalSection(&csHooks);
- return 0;
-}
-
-int CallPluginEventHook(HINSTANCE hInst, HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- int returnVal = 0;
- THook* p = (THook*)hEvent;
- if (p == NULL)
- return -1;
-
- EnterCriticalSection(&p->csHook);
- for (int i = 0; i < p->subscriberCount; i++) {
- THookSubscriber* s = &p->subscriber[i];
- if (s->hOwner != hInst)
- continue;
-
- switch (s->type) {
- case 1: returnVal = s->pfnHook(wParam, lParam); break;
- case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
- case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
- case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
- case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
- default: continue;
- }
- if (returnVal)
- break;
- }
-
- if (p->subscriberCount == 0 && p->pfnHook != 0)
- returnVal = p->pfnHook(wParam, lParam);
-
- LeaveCriticalSection(&p->csHook);
- return returnVal;
-}
-
-int CallHookSubscribers(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- int returnVal = 0;
- THook* p = (THook*)hEvent;
- if (p == NULL)
- return -1;
-
- EnterCriticalSection(&p->csHook);
-
- // NOTE: We've got the critical section while all this lot are called. That's mostly safe, though.
- for (int i = 0; i < p->subscriberCount; i++) {
- THookSubscriber* s = &p->subscriber[i];
- switch (s->type) {
- case 1: returnVal = s->pfnHook(wParam, lParam); break;
- case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
- case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
- case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
- case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
- default: continue;
- }
- if (returnVal)
- break;
- }
-
- // check for no hooks and call the default hook if any
- if (p->subscriberCount == 0 && p->pfnHook != 0)
- returnVal = p->pfnHook(wParam, lParam);
-
- LeaveCriticalSection(&p->csHook);
- return returnVal;
-}
-
-static int checkHook(HANDLE hHook)
-{
- if (hHook == NULL)
- return -1;
-
- EnterCriticalSection(&csHooks);
- if (pLastHook != hHook || !pLastHook) {
- if (hooks.getIndex((THook*)hHook) == -1) {
- LeaveCriticalSection(&csHooks);
- return -1;
- }
- pLastHook = (THook*)hHook;
- }
- LeaveCriticalSection(&csHooks);
- return 0;
-}
-
-static void CALLBACK HookToMainAPCFunc(ULONG_PTR dwParam)
-{
- THookToMainThreadItem* item = (THookToMainThreadItem*)dwParam;
-
- if (checkHook(item->hook) == -1)
- item->result = -1;
- else
- item->result = CallHookSubscribers(item->hook, item->wParam, item->lParam);
- SetEvent(item->hDoneEvent);
-}
-
-int NotifyEventHooks(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- extern HWND hAPCWindow;
-
- if ( GetCurrentThreadId() != mainThreadId) {
- THookToMainThreadItem item;
-
- item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- item.hook = (THook*)hEvent;
- item.wParam = wParam;
- item.lParam = lParam;
-
- QueueUserAPC(HookToMainAPCFunc, hMainThread, (ULONG_PTR)&item);
- PostMessage(hAPCWindow, WM_NULL, 0, 0); // let it process APC even if we're in a common dialog
- WaitForSingleObject(item.hDoneEvent, INFINITE);
- CloseHandle(item.hDoneEvent);
- return item.result;
- }
-
- return (checkHook(hEvent) == -1) ? -1 : CallHookSubscribers(hEvent, wParam, lParam);
-}
-
-static HANDLE HookEventInt(int type, const char* name, MIRANDAHOOK hookProc, void* object, LPARAM lParam)
-{
- int idx;
- THook* p;
- HANDLE ret;
-
- EnterCriticalSection(&csHooks);
- if ((idx = hooks.getIndex((THook*)name)) == -1) {
- #ifdef _DEBUG
- OutputDebugStringA("Attempt to hook: \t");
- OutputDebugStringA(name);
- OutputDebugStringA("\n");
- #endif
- LeaveCriticalSection(&csHooks);
- return NULL;
- }
-
- p = hooks[ idx ];
- p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount+1));
- p->subscriber[ p->subscriberCount ].type = type;
- p->subscriber[ p->subscriberCount ].pfnHook = hookProc;
- p->subscriber[ p->subscriberCount ].object = object;
- p->subscriber[ p->subscriberCount ].lParam = lParam;
- p->subscriber[ p->subscriberCount ].hOwner = GetInstByAddress(hookProc);
- p->subscriberCount++;
-
- ret = (HANDLE)((p->id << 16) | p->subscriberCount);
- LeaveCriticalSection(&csHooks);
- return ret;
-}
-
-HANDLE HookEvent(const char* name, MIRANDAHOOK hookProc)
-{
- return HookEventInt(1, name, hookProc, 0, 0);
-}
-
-HANDLE HookEventParam(const char* name, MIRANDAHOOKPARAM hookProc, LPARAM lParam)
-{
- return HookEventInt(2, name, (MIRANDAHOOK)hookProc, 0, lParam);
-}
-
-HANDLE HookEventObj(const char* name, MIRANDAHOOKOBJ hookProc, void* object)
-{
- return HookEventInt(3, name, (MIRANDAHOOK)hookProc, object, 0);
-}
-
-HANDLE HookEventObjParam(const char* name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam)
-{
- return HookEventInt(4, name, (MIRANDAHOOK)hookProc, object, lParam);
-}
-
-HANDLE HookEventMessage(const char* name, HWND hwnd, UINT message)
-{
- int idx;
- THook* p;
- HANDLE ret;
-
- EnterCriticalSection(&csHooks);
- if ((idx = hooks.getIndex((THook*)name)) == -1) {
- #ifdef _DEBUG
- MessageBoxA(NULL, "Attempt to hook non-existant event", name, MB_OK);
- #endif
- LeaveCriticalSection(&csHooks);
- return NULL;
- }
-
- p = hooks[ idx ];
- p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount+1));
- p->subscriber[ p->subscriberCount ].type = 5;
- p->subscriber[ p->subscriberCount ].hwnd = hwnd;
- p->subscriber[ p->subscriberCount ].message = message;
- p->subscriberCount++;
-
- ret = (HANDLE)((p->id << 16) | p->subscriberCount);
- LeaveCriticalSection(&csHooks);
- return ret;
-}
-
-int UnhookEvent(HANDLE hHook)
-{
- int i;
- THook* p = NULL;
-
- int hookId = (int)hHook >> 16;
- int subscriberId = ((int)hHook & 0xFFFF) - 1;
-
- if (hHook == NULL) return 0;
-
- EnterCriticalSection(&csHooks);
- for (i = 0; i < hooks.getCount(); i++) {
- if (hooks[i]->id == hookId) {
- p = hooks[i];
- break;
- } }
-
- if (p == NULL) {
- LeaveCriticalSection(&csHooks);
- return 1;
- }
-
- if (subscriberId >= p->subscriberCount || subscriberId < 0) {
- LeaveCriticalSection(&csHooks);
- return 1;
- }
-
- p->subscriber[subscriberId].type = 0;
- p->subscriber[subscriberId].pfnHook = NULL;
- p->subscriber[subscriberId].hOwner = NULL;
- while (p->subscriberCount && p->subscriber[p->subscriberCount-1].type == 0)
- p->subscriberCount--;
- if (p->subscriberCount == 0) {
- if (p->subscriber) mir_free(p->subscriber);
- p->subscriber = NULL;
- }
- LeaveCriticalSection(&csHooks);
- return 0;
-}
-
-void KillModuleEventHooks(HINSTANCE hInst)
-{
- int i, j;
-
- EnterCriticalSection(&csHooks);
- for (i = hooks.getCount()-1; i >= 0; i--) {
- if (hooks[i]->subscriberCount == 0)
- continue;
-
- for (j = hooks[i]->subscriberCount-1; j >= 0; j--) {
- if (hooks[i]->subscriber[j].hOwner == hInst) {
- char szModuleName[ MAX_PATH ];
- GetModuleFileNameA(hooks[i]->subscriber[j].hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(NULL, "A hook %08x for event '%s' was abnormally deleted because module '%s' didn't released it",
- hooks[i]->subscriber[j].pfnHook, hooks[i]->name, szModuleName);
- UnhookEvent((HANDLE)((hooks[i]->id << 16) + j + 1));
- if (hooks[i]->subscriberCount == 0)
- break;
- } } }
-
- LeaveCriticalSection(&csHooks);
-}
-
-void KillObjectEventHooks(void* pObject)
-{
- int i, j;
-
- EnterCriticalSection(&csHooks);
- for (i = hooks.getCount()-1; i >= 0; i--) {
- if (hooks[i]->subscriberCount == 0)
- continue;
-
- for (j = hooks[i]->subscriberCount-1; j >= 0; j--) {
- if (hooks[i]->subscriber[j].object == pObject) {
- UnhookEvent((HANDLE)((hooks[i]->id << 16) + j + 1));
- if (hooks[i]->subscriberCount == 0)
- break;
- } } }
-
- LeaveCriticalSection(&csHooks);
-}
-
-/////////////////////SERVICES
-
-static __inline TService* FindServiceByName(const char *name)
-{
- unsigned hash = hashstr(name);
- return services.find((TService*)&hash);
-}
-
-static HANDLE CreateServiceInt(int type, const char *name, MIRANDASERVICE serviceProc, void* object, LPARAM lParam)
-{
- if (name == NULL)
- return NULL;
-
- TService tmp;
- tmp.nameHash = hashstr(name);
-
- EnterCriticalSection(&csServices);
-
- if (services.getIndex(&tmp) != -1) {
- LeaveCriticalSection(&csServices);
- return NULL;
- }
-
- TService* p = (TService*)mir_alloc(sizeof(*p) + strlen(name));
- strcpy(p->name, name);
- p->nameHash = tmp.nameHash;
- p->pfnService = serviceProc;
- p->hOwner = GetInstByAddress(serviceProc);
- p->flags = type;
- p->lParam = lParam;
- p->object = object;
- services.insert(p);
-
- LeaveCriticalSection(&csServices);
- return (HANDLE)tmp.nameHash;
-}
-
-HANDLE CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc)
-{
- return CreateServiceInt(0, name, serviceProc, 0, 0);
-}
-
-HANDLE CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam)
-{
- return CreateServiceInt(1, name, (MIRANDASERVICE)serviceProc, 0, lParam);
-}
-
-HANDLE CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object)
-{
- return CreateServiceInt(2, name, (MIRANDASERVICE)serviceProc, object, 0);
-}
-
-HANDLE CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam)
-{
- return CreateServiceInt(3, name, (MIRANDASERVICE)serviceProc, object, lParam);
-}
-
-int DestroyServiceFunction(HANDLE hService)
-{
- int idx;
-
- EnterCriticalSection(&csServices);
- if ((idx = services.getIndex((TService*)&hService)) != -1) {
- mir_free(services[idx]);
- services.remove(idx);
- }
-
- LeaveCriticalSection(&csServices);
- return 0;
-}
-
-int ServiceExists(const char *name)
-{
- if (name == NULL)
- return FALSE;
-
- EnterCriticalSection(&csServices);
- int ret = FindServiceByName(name) != NULL;
- LeaveCriticalSection(&csServices);
- return ret;
-}
-
-INT_PTR CallService(const char *name, WPARAM wParam, LPARAM lParam)
-{
- #ifdef _DEBUG
- if (name == NULL) {
- MessageBoxA(0, "Someone tried to CallService(NULL, ..) see stack trace for details", "", 0);
- DebugBreak();
- return CALLSERVICE_NOTFOUND;
- }
- #else
- if (name == NULL) return CALLSERVICE_NOTFOUND;
- #endif
-
- EnterCriticalSection(&csServices);
- TService *pService = FindServiceByName(name);
- if (pService == NULL) {
- LeaveCriticalSection(&csServices);
- #ifdef _DEBUG
- //MessageBoxA(NULL, "Attempt to call non-existant service", name, MB_OK);
- OutputDebugStringA("Missing service called: \t");
- OutputDebugStringA(name);
- OutputDebugStringA("\n");
- #endif
-/* { MISSING_SERVICE_PARAMS params = { name, wParam, lParam };
- int result = NotifyEventHooks(hMissingService, 0, (LPARAM)&params);
- if (result != 0)
- return params.lParam;
- } */
- return CALLSERVICE_NOTFOUND;
- }
-
- MIRANDASERVICE pfnService = pService->pfnService;
- int flags = pService->flags;
- LPARAM fnParam = pService->lParam;
- void* object = pService->object;
- LeaveCriticalSection(&csServices);
- switch(flags) {
- case 1: return ((MIRANDASERVICEPARAM)pfnService)(wParam, lParam, fnParam);
- case 2: return ((MIRANDASERVICEOBJ)pfnService)(object, wParam, lParam);
- case 3: return ((MIRANDASERVICEOBJPARAM)pfnService)(object, wParam, lParam, fnParam);
- default: return pfnService(wParam, lParam);
-} }
-
-static void CALLBACK CallServiceToMainAPCFunc(ULONG_PTR dwParam)
-{
- TServiceToMainThreadItem *item = (TServiceToMainThreadItem*) dwParam;
- item->result = CallService(item->name, item->wParam, item->lParam);
- SetEvent(item->hDoneEvent);
-}
-
-INT_PTR CallServiceSync(const char *name, WPARAM wParam, LPARAM lParam)
-{
- extern HWND hAPCWindow;
-
- if (name == NULL) return CALLSERVICE_NOTFOUND;
- // the service is looked up within the main thread, since the time it takes
- // for the APC queue to clear the service being called maybe removed.
- // even thou it may exists before the call, the critsec can't be locked between calls.
- if (GetCurrentThreadId() != mainThreadId) {
- TServiceToMainThreadItem item;
- item.wParam = wParam;
- item.lParam = lParam;
- item.name = name;
- item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- QueueUserAPC(CallServiceToMainAPCFunc, hMainThread, (ULONG_PTR) &item);
- PostMessage(hAPCWindow, WM_NULL, 0, 0); // let this get processed in its own time
- WaitForSingleObject(item.hDoneEvent, INFINITE);
- CloseHandle(item.hDoneEvent);
- return item.result;
- }
-
- return CallService(name, wParam, lParam);
-}
-
-int CallFunctionAsync(void (__stdcall *func)(void *), void *arg)
-{
- extern HWND hAPCWindow;
- int r = QueueUserAPC((void (__stdcall *)(ULONG_PTR))func, hMainThread, (ULONG_PTR)arg);
- PostMessage(hAPCWindow, WM_NULL, 0, 0);
- return r;
-}
-
-void KillModuleServices(HINSTANCE hInst)
-{
- int i;
-
- EnterCriticalSection(&csServices);
- for (i = services.getCount()-1; i >= 0; i--) {
- if (services[i]->hOwner == hInst) {
- char szModuleName[ MAX_PATH ];
- GetModuleFileNameA(services[i]->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(NULL, "A service function '%s' was abnormally deleted because module '%s' didn't released it",
- services[i]->name, szModuleName);
- DestroyServiceFunction((HANDLE)services[i]->nameHash);
- } }
-
- LeaveCriticalSection(&csServices);
-}
-
-void KillObjectServices(void* pObject)
-{
- int i;
-
- EnterCriticalSection(&csServices);
- for (i = services.getCount()-1; i >= 0; i--)
- if (services[i]->object == pObject)
- DestroyServiceFunction((HANDLE)services[i]->nameHash);
-
- LeaveCriticalSection(&csServices);
}