diff options
author | George Hazan <ghazan@miranda.im> | 2022-05-10 21:45:21 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-05-10 21:45:21 +0300 |
commit | ad9b7e867404e4c2d14153a2d5c63007338101e4 (patch) | |
tree | 2817d07cbabe4b13e6d41fe9fc540800cd7527d6 /src/mir_core | |
parent | d19032779296481ece089c77a2c180a4f383b788 (diff) |
Windows-specific code moved from mir_app to mir_core
Diffstat (limited to 'src/mir_core')
-rw-r--r-- | src/mir_core/src/Windows/miranda.cpp | 221 | ||||
-rw-r--r-- | src/mir_core/src/mir_core.def | 10 | ||||
-rw-r--r-- | src/mir_core/src/mir_core64.def | 10 | ||||
-rw-r--r-- | src/mir_core/src/miranda.h | 9 | ||||
-rw-r--r-- | src/mir_core/src/modules.cpp | 13 | ||||
-rw-r--r-- | src/mir_core/src/stdafx.h | 4 |
6 files changed, 259 insertions, 8 deletions
diff --git a/src/mir_core/src/Windows/miranda.cpp b/src/mir_core/src/Windows/miranda.cpp index d6c63c7ca1..aea24d96d8 100644 --- a/src/mir_core/src/Windows/miranda.cpp +++ b/src/mir_core/src/Windows/miranda.cpp @@ -43,8 +43,76 @@ HINSTANCE g_hInst = nullptr; HCURSOR g_hCursorNS, g_hCursorWE; HANDLE hThreadQueueEmpty; +HANDLE hShutdownEvent, hPreShutdownEvent; uint32_t mir_tls = 0; +static bool g_bMirandaTerminated = false; + +MIR_CORE_DLL(bool) Miranda_IsTerminated() +{ + return g_bMirandaTerminated; +} + +MIR_CORE_DLL(void) Miranda_SetTerminated(void) +{ + g_bMirandaTerminated = true; + + NotifyEventHooks(hPreShutdownEvent, 0, 0); + NotifyEventHooks(hShutdownEvent, 0, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +struct MWaitableObject +{ + MWaitableObject(MWaitableStub pFunc, HANDLE hEvent) : + m_bOwnsEvent(false), + m_hEvent(hEvent), + m_pFunc(pFunc), + m_pInfo(INVALID_HANDLE_VALUE) + { + if (hEvent == nullptr) { + m_hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr); + m_bOwnsEvent = true; + } + } + + MWaitableObject(MWaitableStubEx pFunc, void *pInfo) : + m_bOwnsEvent(true), + m_hEvent(CreateEvent(nullptr, TRUE, TRUE, nullptr)), + m_pFuncEx(pFunc), + m_pInfo(pInfo) + {} + + ~MWaitableObject() + { + if (m_bOwnsEvent) + ::CloseHandle(m_hEvent); + } + + HANDLE m_hEvent; + union + { + MWaitableStub m_pFunc; + MWaitableStubEx m_pFuncEx; + }; + void *m_pInfo; + + bool m_bOwnsEvent; +}; + +static OBJLIST<MWaitableObject> arWaitableObjects(1, HandleKeySortT); + +MIR_CORE_DLL(void) Miranda_WaitOnHandle(MWaitableStub pFunc, HANDLE hEvent) +{ + arWaitableObjects.insert(new MWaitableObject(pFunc, hEvent)); +} + +MIR_CORE_DLL(void) Miranda_WaitOnHandleEx(MWaitableStubEx pFunc, void *pInfo) +{ + arWaitableObjects.insert(new MWaitableObject(pFunc, pInfo)); +} + ///////////////////////////////////////////////////////////////////////////////////////// static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam) @@ -116,6 +184,9 @@ static void LoadCoreModule(void) CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda); + hShutdownEvent = CreateHookableEvent(ME_SYSTEM_SHUTDOWN); + hPreShutdownEvent = CreateHookableEvent(ME_SYSTEM_PRESHUTDOWN); + pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036"); } @@ -131,6 +202,156 @@ MIR_CORE_DLL(void) UnloadCoreModule(void) } ///////////////////////////////////////////////////////////////////////////////////////// +// Message loop + +static HMODULE hThemeAPI; + +typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintInit)(void); +pfnBufferedPaintInit bufferedPaintInit; + +typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintUninit)(void); +pfnBufferedPaintUninit bufferedPaintUninit; + +static void crtErrorHandler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned, uintptr_t) +{} + +static void __cdecl compactHeapsThread(void*) +{ + Thread_SetName("compactHeapsThread"); + + while (!Miranda_IsTerminated()) { + SleepEx((1000 * 60) * 5, TRUE); // every 5 minutes + + HANDLE hHeaps[256]; + uint32_t hc = GetProcessHeaps(255, (PHANDLE)&hHeaps); + if (hc != 0 && hc < 256) { + __try { + for (uint32_t j = 0; j < hc; j++) + HeapCompact(hHeaps[j], 0); + } + __except (EXCEPTION_EXECUTE_HANDLER) + {} + } + } +} + +MIR_CORE_DLL(void) BeginMessageLoop() +{ + _set_invalid_parameter_handler(&crtErrorHandler); + + #ifdef _DEBUG + _CrtSetReportMode(_CRT_ASSERT, 0); + #endif + + #ifdef _DEBUG + if (CmdLine_GetOption(L"memdebug")) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + #endif + + hThemeAPI = LoadLibrary(L"uxtheme.dll"); + if (hThemeAPI) { + bufferedPaintInit = (pfnBufferedPaintInit)GetProcAddress(hThemeAPI, "BufferedPaintInit"); + bufferedPaintUninit = (pfnBufferedPaintUninit)GetProcAddress(hThemeAPI, "BufferedPaintUninit"); + } + + if (bufferedPaintInit) + bufferedPaintInit(); + + OleInitialize(nullptr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static uint32_t dwEventTime = 0; + +void checkIdle(MSG *msg) +{ + switch (msg->message) { + case WM_MOUSEACTIVATE: + case WM_MOUSEMOVE: + case WM_CHAR: + dwEventTime = GetTickCount(); + } +} + +MIR_CORE_DLL(uint32_t) Miranda_GetIdle() +{ + return dwEventTime; +} + +static uint32_t myWait() +{ + HANDLE *hWaitObjects = (HANDLE *)_alloca(arWaitableObjects.getCount() * sizeof(HANDLE)); + for (int i = 0; i < arWaitableObjects.getCount(); i++) + hWaitObjects[i] = arWaitableObjects[i].m_hEvent; + + return MsgWaitForMultipleObjectsEx(arWaitableObjects.getCount(), hWaitObjects, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); +} + +MIR_CORE_DLL(void) EnterMessageLoop() +{ + mir_forkthread(compactHeapsThread); + dwEventTime = GetTickCount(); + uint32_t myPid = GetCurrentProcessId(); + + bool messageloop = true; + while (messageloop) { + MSG msg; + BOOL dying = FALSE; + uint32_t rc = myWait(); + if (rc < WAIT_OBJECT_0 + arWaitableObjects.getCount()) { + auto &pWait = arWaitableObjects[rc - WAIT_OBJECT_0]; + if (pWait.m_pInfo == INVALID_HANDLE_VALUE) + (*pWait.m_pFunc)(); + else + (*pWait.m_pFuncEx)(pWait.m_pInfo); + + if (pWait.m_bOwnsEvent) + arWaitableObjects.remove(&pWait); + } + + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.message != WM_QUIT) { + HWND h = GetForegroundWindow(); + DWORD pid = 0; + checkIdle(&msg); + if (h != nullptr && GetWindowThreadProcessId(h, &pid) && pid == myPid && GetClassLongPtr(h, GCW_ATOM) == 32770) + if (h != nullptr && IsDialogMessage(h, &msg)) /* Wine fix. */ + continue; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else if (!dying) { + dying++; + g_bMirandaTerminated = true; + NotifyEventHooks(hPreShutdownEvent, 0, 0); + + // this spins and processes the msg loop, objects and APC. + Thread_Wait(); + NotifyEventHooks(hShutdownEvent, 0, 0); + // if the hooks generated any messages, it'll get processed before the second WM_QUIT + PostQuitMessage(0); + } + else if (dying) + messageloop = false; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(void) LeaveMessageLoop() +{ + OleUninitialize(); + + if (bufferedPaintUninit) { + bufferedPaintUninit(); + FreeLibrary(hThemeAPI); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// // entry point BOOL WINAPI DllMain(HINSTANCE hinstDLL, uint32_t fdwReason, LPVOID) diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def index 965ef0703e..f2034f9ae2 100644 --- a/src/mir_core/src/mir_core.def +++ b/src/mir_core/src/mir_core.def @@ -2,8 +2,11 @@ LIBRARY mir_core.mir EXPORTS
?g_pCurrDb@@3PAVMDatabaseCommon@@A @1 NONAME
-DeleteDirectoryTreeW @2
+BeginMessageLoop @2 NONAME
+EnterMessageLoop @3 NONAME
+LeaveMessageLoop @4 NONAME
CallFunctionAsync @5
+DeleteDirectoryTreeW @6
CallPluginEventHook @7
CallService @8
CallServiceSync @9
@@ -19,6 +22,7 @@ CreateServiceFunctionParam @18 DestroyHookableEvent @19
DestroyServiceFunction @20
GetExceptionFilter @21
+Miranda_GetIdle @22 NONAME
HookEvent @23
HookEventMessage @24
HookEventObj @25
@@ -1531,3 +1535,7 @@ db_copy_module @1736 ?move@MFilePath@@QAE_NPB_W@Z @1755 NONAME
?search@MFilePath@@QAE?AVMFileIterator@1@XZ @1756 NONAME
??Eiterator@MFileIterator@MFilePath@@QAE?AV012@XZ @1757 NONAME
+Miranda_IsTerminated @1758 NONAME
+Miranda_SetTerminated @1759 NONAME
+Miranda_WaitOnHandle @1760 NONAME
+Miranda_WaitOnHandleEx @1761 NONAME
diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def index 741a548e83..8834dde5db 100644 --- a/src/mir_core/src/mir_core64.def +++ b/src/mir_core/src/mir_core64.def @@ -2,8 +2,11 @@ LIBRARY mir_core.mir EXPORTS
?g_pCurrDb@@3PEAVMDatabaseCommon@@EA @1 NONAME
-DeleteDirectoryTreeW @2
+BeginMessageLoop @2 NONAME
+EnterMessageLoop @3 NONAME
+LeaveMessageLoop @4 NONAME
CallFunctionAsync @5
+DeleteDirectoryTreeW @6
CallPluginEventHook @7
CallService @8
CallServiceSync @9
@@ -19,6 +22,7 @@ CreateServiceFunctionParam @18 DestroyHookableEvent @19
DestroyServiceFunction @20
GetExceptionFilter @21
+Miranda_GetIdle @22 NONAME
HookEvent @23
HookEventMessage @24
HookEventObj @25
@@ -1531,3 +1535,7 @@ db_copy_module @1736 ?move@MFilePath@@QEAA_NPEB_W@Z @1755 NONAME
?search@MFilePath@@QEAA?AVMFileIterator@1@XZ @1756 NONAME
??Eiterator@MFileIterator@MFilePath@@QEAA?AV012@XZ @1757 NONAME
+Miranda_IsTerminated @1758 NONAME
+Miranda_SetTerminated @1759 NONAME
+Miranda_WaitOnHandle @1760 NONAME
+Miranda_WaitOnHandleEx @1761 NONAME
diff --git a/src/mir_core/src/miranda.h b/src/mir_core/src/miranda.h index 147bc1998f..24a15d0af9 100644 --- a/src/mir_core/src/miranda.h +++ b/src/mir_core/src/miranda.h @@ -65,7 +65,7 @@ struct THookSubscriber struct THook : public MZeroedObject { - char name[ MAXMODULELABELLENGTH ]; + char name[MAXMODULELABELLENGTH]; int id; int subscriberCount; THookSubscriber* subscriber; @@ -82,6 +82,13 @@ extern LIST<CMPluginBase> pluginListAddr; char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W); ///////////////////////////////////////////////////////////////////////////////////////// +// miranda.cpp + +EXTERN_C MIR_CORE_DLL(void) BeginMessageLoop(void); +EXTERN_C MIR_CORE_DLL(void) EnterMessageLoop(void); +EXTERN_C MIR_CORE_DLL(void) LeaveMessageLoop(void); + +///////////////////////////////////////////////////////////////////////////////////////// // threads.cpp extern uint32_t mir_tls; diff --git a/src/mir_core/src/modules.cpp b/src/mir_core/src/modules.cpp index 6e867aa95c..1636d7449e 100644 --- a/src/mir_core/src/modules.cpp +++ b/src/mir_core/src/modules.cpp @@ -63,15 +63,14 @@ struct TService LIST<TService> services(100, NumericKeySortT); -typedef struct +struct TServiceToMainThreadItem { HANDLE hDoneEvent; WPARAM wParam; LPARAM lParam; int result; const char *name; -} -TServiceToMainThreadItem; +}; // other static variables static BOOL bServiceMode = FALSE; @@ -154,9 +153,13 @@ MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnH return 0; } -MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, HANDLE hEvent, WPARAM wParam, LPARAM lParam) +MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, const char *pszEvent, WPARAM wParam, LPARAM lParam) { - THook *p = (THook*)hEvent; + int idx; + if ((idx = hooks.getIndex((THook *)pszEvent)) == -1) + return -1; + + THook *p = hooks[idx]; if (p == nullptr || hInst == nullptr) return -1; diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h index f053907693..54ec535a4c 100644 --- a/src/mir_core/src/stdafx.h +++ b/src/mir_core/src/stdafx.h @@ -42,6 +42,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <process.h> #include <io.h> #include <direct.h> + + #ifdef _DEBUG + #include <crtdbg.h> + #endif #else #include <Elementary.h> #endif // _WINDOWS |