From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/miranda.cpp | 941 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 941 insertions(+) create mode 100644 src/core/miranda.cpp (limited to 'src/core/miranda.cpp') diff --git a/src/core/miranda.cpp b/src/core/miranda.cpp new file mode 100644 index 0000000000..fe38d096e1 --- /dev/null +++ b/src/core/miranda.cpp @@ -0,0 +1,941 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2012 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +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, +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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "commonheaders.h" + +#define MMI_SIZE_V1 (4*sizeof(void*)) +#define MMI_SIZE_V2 (7*sizeof(void*)) + +int InitPathUtils(void); +int InitialiseModularEngine(void); +int LoadDefaultModules(void); +void DestroyModularEngine(void); +void UnloadNewPluginsModule(void); +void UnloadDefaultModules(void); +void RecalculateTime(void); + +HINSTANCE GetInstByAddress( void* codePtr ); + +pfnMyMonitorFromPoint MyMonitorFromPoint; +pfnMyMonitorFromRect MyMonitorFromRect; +pfnMyMonitorFromWindow MyMonitorFromWindow; +pfnMyGetMonitorInfo MyGetMonitorInfo; + +typedef DWORD (WINAPI *pfnMsgWaitForMultipleObjectsEx)(DWORD,CONST HANDLE*,DWORD,DWORD,DWORD); +pfnMsgWaitForMultipleObjectsEx msgWaitForMultipleObjectsEx; + +pfnSHAutoComplete shAutoComplete; +pfnSHGetSpecialFolderPathA shGetSpecialFolderPathA; +pfnSHGetSpecialFolderPathW shGetSpecialFolderPathW; + +pfnOpenInputDesktop openInputDesktop; +pfnCloseDesktop closeDesktop; + +pfnAnimateWindow animateWindow; +pfnSetLayeredWindowAttributes setLayeredWindowAttributes; + +pfnOpenThemeData openThemeData; +pfnIsThemeBackgroundPartiallyTransparent isThemeBackgroundPartiallyTransparent; +pfnDrawThemeParentBackground drawThemeParentBackground; +pfnDrawThemeBackground drawThemeBackground; +pfnDrawThemeText drawThemeText; +pfnDrawThemeTextEx drawThemeTextEx; +pfnGetThemeBackgroundContentRect getThemeBackgroundContentRect; +pfnGetThemeFont getThemeFont; +pfnCloseThemeData closeThemeData; +pfnEnableThemeDialogTexture enableThemeDialogTexture; +pfnSetWindowTheme setWindowTheme; +pfnSetWindowThemeAttribute setWindowThemeAttribute; +pfnIsThemeActive isThemeActive; +pfnBufferedPaintInit bufferedPaintInit; +pfnBufferedPaintUninit bufferedPaintUninit; +pfnBeginBufferedPaint beginBufferedPaint; +pfnEndBufferedPaint endBufferedPaint; +pfnGetBufferedPaintBits getBufferedPaintBits; + +pfnDwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea; +pfnDwmIsCompositionEnabled dwmIsCompositionEnabled; + +pfnGetaddrinfo MyGetaddrinfo; +pfnFreeaddrinfo MyFreeaddrinfo; + +ITaskbarList3 * pTaskbarInterface; + +static DWORD MsgWaitForMultipleObjectsExWorkaround(DWORD nCount, const HANDLE *pHandles, + DWORD dwMsecs, DWORD dwWakeMask, DWORD dwFlags); + +static HANDLE hOkToExitEvent,hModulesLoadedEvent; +static HANDLE hShutdownEvent,hPreShutdownEvent; +static HANDLE hWaitObjects[MAXIMUM_WAIT_OBJECTS-1]; +static char *pszWaitServices[MAXIMUM_WAIT_OBJECTS-1]; +static int waitObjectCount=0; +HANDLE hStackMutex,hMirandaShutdown,hThreadQueueEmpty; +HINSTANCE hMirandaInst; + +///////////////////////////////////////////////////////////////////////////////////////// +// exception handling + +static DWORD __cdecl sttDefaultFilter( DWORD, EXCEPTION_POINTERS* ) +{ + return EXCEPTION_EXECUTE_HANDLER; +} + +pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter; + +static INT_PTR GetExceptionFilter( WPARAM, LPARAM ) +{ + return ( INT_PTR )pMirandaExceptFilter; +} + +static INT_PTR SetExceptionFilter( WPARAM, LPARAM lParam ) +{ + pfnExceptionFilter oldOne = pMirandaExceptFilter; + if ( lParam != 0 ) + pMirandaExceptFilter = ( pfnExceptionFilter )lParam; + return ( INT_PTR )oldOne; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// thread support functions + +typedef struct +{ + DWORD dwThreadId; // valid if hThread isn't signalled + HANDLE hThread; + HINSTANCE hOwner; + void* pObject; + PVOID addr; +} +THREAD_WAIT_ENTRY; + +static LIST threads( 10, NumericKeySortT ); + +struct FORK_ARG { + HANDLE hEvent; + pThreadFunc threadcode; + pThreadFuncEx threadcodeex; + void *arg, *owner; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// forkthread - starts a new thread + +void __cdecl forkthread_r(void * arg) +{ + struct FORK_ARG * fa = (struct FORK_ARG *) arg; + void (*callercode)(void*)=fa->threadcode; + void * cookie=fa->arg; + CallService(MS_SYSTEM_THREAD_PUSH,0,(LPARAM)callercode); + SetEvent(fa->hEvent); + __try + { + callercode(cookie); + } + __except( pMirandaExceptFilter( GetExceptionCode(), GetExceptionInformation())) + { + Netlib_Logf( NULL, "Unhandled exception in thread %x", GetCurrentThreadId()); + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + CallService(MS_SYSTEM_THREAD_POP,0,0); + return; +} + +UINT_PTR forkthread ( + void (__cdecl *threadcode)(void*), + unsigned long stacksize, + void *arg + ) +{ + UINT_PTR rc; + struct FORK_ARG fa; + fa.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL); + fa.threadcode=threadcode; + fa.arg=arg; + rc=_beginthread(forkthread_r,stacksize,&fa); + if ((UINT_PTR)-1L != rc) + WaitForSingleObject(fa.hEvent,INFINITE); + + CloseHandle(fa.hEvent); + return rc; +} + +static INT_PTR ForkThreadService(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)forkthread(( pThreadFunc )wParam, 0, ( void* )lParam ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// forkthreadex - starts a new thread with the extended info and returns the thread id + +unsigned __stdcall forkthreadex_r(void * arg) +{ + struct FORK_ARG *fa = (struct FORK_ARG *)arg; + pThreadFuncEx threadcode = fa->threadcodeex; + pThreadFuncOwner threadcodeex = ( pThreadFuncOwner )fa->threadcodeex; + void *cookie = fa->arg; + void *owner = fa->owner; + unsigned long rc = 0; + + CallService(MS_SYSTEM_THREAD_PUSH, (WPARAM)fa->owner, (LPARAM)threadcode); + SetEvent(fa->hEvent); + __try + { + if ( owner ) + rc = threadcodeex( owner, cookie ); + else + rc = threadcode( cookie ); + } + __except( pMirandaExceptFilter( GetExceptionCode(), GetExceptionInformation())) + { + Netlib_Logf( NULL, "Unhandled exception in thread %x", GetCurrentThreadId()); + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + CallService(MS_SYSTEM_THREAD_POP,0,0); + return rc; +} + +UINT_PTR forkthreadex( + void *sec, + unsigned stacksize, + unsigned (__stdcall *threadcode)(void*), + void* owner, + void *arg, + unsigned *thraddr ) +{ + UINT_PTR rc; + struct FORK_ARG fa = { 0 }; + fa.threadcodeex = threadcode; + fa.arg = arg; + fa.owner = owner; + fa.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); + rc = _beginthreadex(sec,stacksize,forkthreadex_r,(void *)&fa,0,thraddr); + if (rc) + WaitForSingleObject(fa.hEvent,INFINITE); + + CloseHandle(fa.hEvent); + return rc; +} + +static INT_PTR ForkThreadServiceEx(WPARAM wParam, LPARAM lParam) +{ + FORK_THREADEX_PARAMS* params = (FORK_THREADEX_PARAMS*)lParam; + if ( params == NULL ) + return 0; + + UINT threadID; + return forkthreadex( NULL, params->iStackSize, params->pFunc, ( void* )wParam, params->arg, params->threadID ? params->threadID : &threadID ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// APC and mutex functions + +static void __stdcall DummyAPCFunc(ULONG_PTR) +{ + /* called in the context of thread that cleared it's APC queue */ + return; +} + +static int MirandaWaitForMutex(HANDLE hEvent) +{ + for (;;) { + // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result + DWORD rc = MsgWaitForMultipleObjectsExWorkaround(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); + if ( rc == WAIT_OBJECT_0 + 1 ) { + MSG msg; + while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { + if ( IsDialogMessage(msg.hwnd, &msg) ) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } else if ( rc==WAIT_OBJECT_0 ) { + // got object + return 1; + } else if ( rc==WAIT_ABANDONED_0 || rc == WAIT_FAILED ) return 0; + } +} + +VOID CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD) +{ + if ( MirandaWaitForMutex( hStackMutex )) { + for ( int j=0; j < threads.getCount(); j++ ) { + THREAD_WAIT_ENTRY* p = threads[j]; + char szModuleName[ MAX_PATH ]; + GetModuleFileNameA( p->hOwner, szModuleName, sizeof(szModuleName)); + Netlib_Logf( NULL, "Thread %p was abnormally terminated because module '%s' didn't release it. Entry point: %p", + p->hThread, szModuleName, p->addr ); + TerminateThread( p->hThread, 9999 ); + CloseHandle(p->hThread); + mir_free( p ); + } + + threads.destroy(); + + ReleaseMutex( hStackMutex ); + SetEvent( hThreadQueueEmpty ); + } +} + +void KillObjectThreads( void* owner ) +{ + if ( owner == NULL ) + return; + + WaitForSingleObject( hStackMutex, INFINITE ); + + HANDLE* threadPool = ( HANDLE* )alloca( threads.getCount()*sizeof( HANDLE )); + int threadCount = 0; + + for ( int j = threads.getCount(); j--; ) { + THREAD_WAIT_ENTRY* p = threads[j]; + if ( p->pObject == owner ) + threadPool[ threadCount++ ] = p->hThread; + } + ReleaseMutex(hStackMutex); + + // is there anything to kill? + if ( threadCount > 0 ) { + if ( WaitForMultipleObjects( threadCount, threadPool, TRUE, 5000 ) == WAIT_TIMEOUT ) { + // forcibly kill all remaining threads after 5 secs + WaitForSingleObject( hStackMutex, INFINITE ); + for ( int j = threads.getCount()-1; j >= 0; j-- ) { + THREAD_WAIT_ENTRY* p = threads[j]; + if ( p->pObject == owner ) { + TerminateThread( p->hThread, 9999 ); + CloseHandle( p->hThread ); + threads.remove( j ); + mir_free( p ); + } + } + ReleaseMutex(hStackMutex); + } + } +} + +static void UnwindThreadWait(void) +{ + // acquire the list and wake up any alertable threads + if ( MirandaWaitForMutex(hStackMutex) ) { + int j; + for ( j=0; j < threads.getCount(); j++ ) + QueueUserAPC(DummyAPCFunc,threads[j]->hThread, 0); + ReleaseMutex(hStackMutex); + } + + // give all unclosed threads 5 seconds to close + SetTimer( NULL, 0, 5000, KillAllThreads ); + + // wait til the thread list is empty + MirandaWaitForMutex(hThreadQueueEmpty); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG); +#define ThreadQuerySetWin32StartAddress 9 + +void* GetCurrentThreadEntryPoint() +{ + LONG ntStatus; + HANDLE hDupHandle, hCurrentProcess; + DWORD_PTR dwStartAddress; + + pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueryInformationThread" ); + if(NtQueryInformationThread == NULL) return 0; + + hCurrentProcess = GetCurrentProcess(); + if(!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)){ + SetLastError(ERROR_ACCESS_DENIED); + return NULL; + } + ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), NULL); + CloseHandle(hDupHandle); + + if(ntStatus != ERROR_SUCCESS) return 0; + return ( void* )dwStartAddress; +} + +INT_PTR UnwindThreadPush(WPARAM wParam,LPARAM lParam) +{ + ResetEvent(hThreadQueueEmpty); // thread list is not empty + if (WaitForSingleObject(hStackMutex, INFINITE) == WAIT_OBJECT_0) + { + THREAD_WAIT_ENTRY* p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY)); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); + p->dwThreadId = GetCurrentThreadId(); + p->pObject = (void*)wParam; + p->hOwner = GetInstByAddress((void*)lParam); + p->addr = (void*)lParam; + threads.insert(p); + + //Netlib_Logf( NULL, "*** pushing thread %x[%x] (%d)", hThread, GetCurrentThreadId(), threads.count ); + ReleaseMutex(hStackMutex); + } //if + return 0; +} + +INT_PTR UnwindThreadPop(WPARAM,LPARAM) +{ + if (WaitForSingleObject(hStackMutex,INFINITE)==WAIT_OBJECT_0) + { + DWORD dwThreadId=GetCurrentThreadId(); + int j; + //Netlib_Logf( NULL, "*** popping thread %x, %d threads left", dwThreadId, threads.count); + for ( j=0; j < threads.getCount(); j++ ) { + THREAD_WAIT_ENTRY* p = threads[j]; + if ( p->dwThreadId == dwThreadId ) { + SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL ); + CloseHandle( p->hThread ); + threads.remove( j ); + mir_free( p ); + + if ( !threads.getCount()) { + threads.destroy(); + ReleaseMutex( hStackMutex ); + SetEvent(hThreadQueueEmpty); // thread list is empty now + return 0; + } + + ReleaseMutex(hStackMutex); + return 0; + } //if + } //for + ReleaseMutex(hStackMutex); + } //if + return 1; +} + +INT_PTR MirandaIsTerminated(WPARAM, LPARAM) +{ + return WaitForSingleObject(hMirandaShutdown,0)==WAIT_OBJECT_0; +} + +static void __cdecl compactHeapsThread(void*) +{ + while (!Miranda_Terminated()) + { + HANDLE hHeaps[256]; + DWORD hc; + SleepEx((1000*60)*5,TRUE); // every 5 minutes + hc=GetProcessHeaps(255,(PHANDLE)&hHeaps); + if (hc != 0 && hc < 256) { + DWORD j; + for (j=0;jmessage) { + case WM_MOUSEACTIVATE: + case WM_MOUSEMOVE: + case WM_CHAR: + dwEventTime = GetTickCount(); + } +} + +static INT_PTR SystemGetIdle(WPARAM, LPARAM lParam) +{ + if ( lParam ) *(DWORD*)lParam = dwEventTime; + return 0; +} + +static DWORD MsgWaitForMultipleObjectsExWorkaround(DWORD nCount, const HANDLE *pHandles, + DWORD dwMsecs, DWORD dwWakeMask, DWORD dwFlags) +{ + DWORD rc; + if ( msgWaitForMultipleObjectsEx != NULL ) + return msgWaitForMultipleObjectsEx(nCount, pHandles, dwMsecs, dwWakeMask, dwFlags); + rc=MsgWaitForMultipleObjects(nCount, pHandles, FALSE, 50, QS_ALLINPUT); + if ( rc == WAIT_TIMEOUT ) rc=WaitForMultipleObjectsEx(nCount, pHandles, FALSE, 20, TRUE); + return rc; +} + +static int SystemShutdownProc(WPARAM, LPARAM) +{ + UnloadDefaultModules(); + return 0; +} + +#define MIRANDA_PROCESS_WAIT_TIMEOUT 60000 +#define MIRANDA_PROCESS_WAIT_RESOLUTION 1000 +#define MIRANDA_PROCESS_WAIT_STEPS (MIRANDA_PROCESS_WAIT_TIMEOUT/MIRANDA_PROCESS_WAIT_RESOLUTION) +static INT_PTR CALLBACK WaitForProcessDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault( hwnd ); + SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); + SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETRANGE, 0, MAKELPARAM(0, MIRANDA_PROCESS_WAIT_STEPS)); + SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETSTEP, 1, 0); + SetTimer(hwnd, 1, MIRANDA_PROCESS_WAIT_RESOLUTION, NULL); + break; + + case WM_TIMER: + if (SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_STEPIT, 0, 0) == MIRANDA_PROCESS_WAIT_STEPS) + EndDialog(hwnd, 0); + if (WaitForSingleObject((HANDLE)GetWindowLongPtr(hwnd, GWLP_USERDATA), 1) != WAIT_TIMEOUT) + { + SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETPOS, MIRANDA_PROCESS_WAIT_STEPS, 0); + EndDialog(hwnd, 0); + } + break; + + case WM_COMMAND: + if (HIWORD(wParam) == IDCANCEL) + { + SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETPOS, MIRANDA_PROCESS_WAIT_STEPS, 0); + EndDialog(hwnd, 0); + } + break; + } + return FALSE; +} + +void ParseCommandLine() +{ + char* cmdline = GetCommandLineA(); + char* p = strstr( cmdline, "/restart:" ); + if ( p ) { + HANDLE hProcess = OpenProcess( SYNCHRONIZE, FALSE, atol( p+9 )); + if ( hProcess ) { + DialogBoxParam(hMirandaInst, MAKEINTRESOURCE(IDD_WAITRESTART), NULL, WaitForProcessDlgProc, (LPARAM)hProcess); + CloseHandle( hProcess ); + } + } +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int ) +{ + DWORD myPid=0; + int messageloop=1; + HMODULE hUser32, hThemeAPI, hDwmApi, hShFolder = NULL; + int result = 0; + + hMirandaInst = hInstance; + + setlocale(LC_ALL, ""); + +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + + hUser32 = GetModuleHandleA("user32"); + openInputDesktop = (pfnOpenInputDesktop)GetProcAddress (hUser32, "OpenInputDesktop"); + closeDesktop = (pfnCloseDesktop)GetProcAddress (hUser32, "CloseDesktop"); + msgWaitForMultipleObjectsEx = (pfnMsgWaitForMultipleObjectsEx)GetProcAddress(hUser32, "MsgWaitForMultipleObjectsEx"); + animateWindow =(pfnAnimateWindow)GetProcAddress(hUser32, "AnimateWindow"); + setLayeredWindowAttributes =(pfnSetLayeredWindowAttributes)GetProcAddress(hUser32, "SetLayeredWindowAttributes"); + + MyMonitorFromPoint = (pfnMyMonitorFromPoint)GetProcAddress(hUser32, "MonitorFromPoint"); + MyMonitorFromRect = (pfnMyMonitorFromRect)GetProcAddress(hUser32, "MonitorFromRect"); + MyMonitorFromWindow = (pfnMyMonitorFromWindow)GetProcAddress(hUser32, "MonitorFromWindow"); +#ifdef _UNICODE + MyGetMonitorInfo = (pfnMyGetMonitorInfo)GetProcAddress(hUser32, "GetMonitorInfoW"); +#else + MyGetMonitorInfo = (pfnMyGetMonitorInfo)GetProcAddress(hUser32, "GetMonitorInfoA"); +#endif + + hShFolder = GetModuleHandleA("shell32"); + shGetSpecialFolderPathA = (pfnSHGetSpecialFolderPathA)GetProcAddress(hShFolder,"SHGetSpecialFolderPathA"); + shGetSpecialFolderPathW = (pfnSHGetSpecialFolderPathW)GetProcAddress(hShFolder,"SHGetSpecialFolderPathW"); + if (shGetSpecialFolderPathA == NULL) + { + hShFolder = LoadLibraryA("ShFolder.dll"); + shGetSpecialFolderPathA = (pfnSHGetSpecialFolderPathA)GetProcAddress(hShFolder,"SHGetSpecialFolderPathA"); + shGetSpecialFolderPathW = (pfnSHGetSpecialFolderPathW)GetProcAddress(hShFolder,"SHGetSpecialFolderPathW"); + } + + shAutoComplete = (pfnSHAutoComplete)GetProcAddress(GetModuleHandleA("shlwapi"),"SHAutoComplete"); + + if (IsWinVerXPPlus()) + { + hThemeAPI = LoadLibraryA("uxtheme.dll"); + if (hThemeAPI) + { + openThemeData = (pfnOpenThemeData)GetProcAddress(hThemeAPI, "OpenThemeData"); + isThemeBackgroundPartiallyTransparent = (pfnIsThemeBackgroundPartiallyTransparent)GetProcAddress(hThemeAPI, "IsThemeBackgroundPartiallyTransparent"); + drawThemeParentBackground = (pfnDrawThemeParentBackground)GetProcAddress(hThemeAPI, "DrawThemeParentBackground"); + drawThemeBackground = (pfnDrawThemeBackground)GetProcAddress(hThemeAPI, "DrawThemeBackground"); + drawThemeText = (pfnDrawThemeText)GetProcAddress(hThemeAPI, "DrawThemeText"); + drawThemeTextEx = (pfnDrawThemeTextEx)GetProcAddress(hThemeAPI, "DrawThemeTextEx"); + getThemeBackgroundContentRect = (pfnGetThemeBackgroundContentRect)GetProcAddress(hThemeAPI ,"GetThemeBackgroundContentRect"); + getThemeFont = (pfnGetThemeFont)GetProcAddress(hThemeAPI, "GetThemeFont"); + closeThemeData = (pfnCloseThemeData)GetProcAddress(hThemeAPI, "CloseThemeData"); + enableThemeDialogTexture = (pfnEnableThemeDialogTexture)GetProcAddress(hThemeAPI, "EnableThemeDialogTexture"); + setWindowTheme = (pfnSetWindowTheme)GetProcAddress(hThemeAPI, "SetWindowTheme"); + setWindowThemeAttribute = (pfnSetWindowThemeAttribute)GetProcAddress(hThemeAPI, "SetWindowThemeAttribute"); + isThemeActive = (pfnIsThemeActive)GetProcAddress(hThemeAPI, "IsThemeActive"); + bufferedPaintInit = (pfnBufferedPaintInit)GetProcAddress(hThemeAPI, "BufferedPaintInit"); + bufferedPaintUninit = (pfnBufferedPaintUninit)GetProcAddress(hThemeAPI, "BufferedPaintUninit"); + beginBufferedPaint = (pfnBeginBufferedPaint)GetProcAddress(hThemeAPI, "BeginBufferedPaint"); + endBufferedPaint = (pfnEndBufferedPaint)GetProcAddress(hThemeAPI, "EndBufferedPaint"); + getBufferedPaintBits = (pfnGetBufferedPaintBits)GetProcAddress(hThemeAPI, "GetBufferedPaintBits"); + } + } + + if (IsWinVerVistaPlus()) + { + hDwmApi = LoadLibraryA("dwmapi.dll"); + if (hDwmApi) + { + dwmExtendFrameIntoClientArea = (pfnDwmExtendFrameIntoClientArea)GetProcAddress(hDwmApi,"DwmExtendFrameIntoClientArea"); + dwmIsCompositionEnabled = (pfnDwmIsCompositionEnabled)GetProcAddress(hDwmApi,"DwmIsCompositionEnabled"); + } + } + + HMODULE hWinSock = GetModuleHandleA("ws2_32"); + MyGetaddrinfo = (pfnGetaddrinfo)GetProcAddress(hWinSock, "getaddrinfo"); + MyFreeaddrinfo = (pfnFreeaddrinfo)GetProcAddress(hWinSock, "freeaddrinfo"); + + if (bufferedPaintInit) bufferedPaintInit(); + + OleInitialize(NULL); + + if (IsWinVer7Plus()) + CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList3, (void**)&pTaskbarInterface); + + InitialiseModularEngine(); +// ParseCommandLine(); + + if (LoadDefaultModules()) { + NotifyEventHooks(hShutdownEvent,0,0); + UnloadDefaultModules(); + + result = 1; + goto exit; + } + NotifyEventHooks(hModulesLoadedEvent,0,0); + + // ensure that the kernel hooks the SystemShutdownProc() after all plugins + HookEvent(ME_SYSTEM_SHUTDOWN,SystemShutdownProc); + + forkthread(compactHeapsThread,0,NULL); + CreateServiceFunction(MS_SYSTEM_SETIDLECALLBACK,SystemSetIdleCallback); + CreateServiceFunction(MS_SYSTEM_GETIDLE, SystemGetIdle); + dwEventTime=GetTickCount(); + myPid=GetCurrentProcessId(); + for(;messageloop;) { + MSG msg; + DWORD rc; + BOOL dying=FALSE; + rc=MsgWaitForMultipleObjectsExWorkaround(waitObjectCount, hWaitObjects, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); + if ( rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + waitObjectCount) { + rc -= WAIT_OBJECT_0; + CallService(pszWaitServices[rc], (WPARAM) hWaitObjects[rc], 0); + } + // + while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { + if ( msg.message != WM_QUIT ) { + HWND h=GetForegroundWindow(); + DWORD pid = 0; + checkIdle(&msg); + if ( h != NULL && GetWindowThreadProcessId(h, &pid) && pid == myPid && + GetClassLongPtr(h, GCW_ATOM)==32770 ) + { + if ( IsDialogMessage(h, &msg) ) + continue; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + if ( SetIdleCallback != NULL ) + SetIdleCallback(); + } else if ( !dying ) { + dying++; + SetEvent(hMirandaShutdown); + NotifyEventHooks(hPreShutdownEvent, 0, 0); + + // this spins and processes the msg loop, objects and APC. + UnwindThreadWait(); + 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=0; + } + } // while + } + +exit: + UnloadNewPluginsModule(); + DestroyModularEngine(); + CloseHandle(hStackMutex); + CloseHandle(hMirandaShutdown); + CloseHandle(hThreadQueueEmpty); + DestroyWindow(hAPCWindow); + + if (pTaskbarInterface) + pTaskbarInterface->Release(); + + OleUninitialize(); + + if (bufferedPaintUninit) bufferedPaintUninit(); + + if (hDwmApi) FreeLibrary(hDwmApi); + if (hThemeAPI) FreeLibrary(hThemeAPI); + if (hShFolder) FreeLibrary(hShFolder); + + return result; +} + +static INT_PTR OkToExit(WPARAM, LPARAM) +{ + return NotifyEventHooks(hOkToExitEvent,0,0)==0; +} + +static INT_PTR GetMirandaVersion(WPARAM, LPARAM) +{ + TCHAR filename[MAX_PATH]; + DWORD unused; + DWORD verInfoSize; + UINT blockSize; + PVOID pVerInfo; + VS_FIXEDFILEINFO *vsffi; + DWORD ver; + + GetModuleFileName(NULL,filename,SIZEOF(filename)); + verInfoSize=GetFileVersionInfoSize(filename,&unused); + pVerInfo=mir_alloc(verInfoSize); + GetFileVersionInfo(filename,0,verInfoSize,pVerInfo); + VerQueryValue(pVerInfo,_T("\\"),(PVOID*)&vsffi,&blockSize); + ver=(((vsffi->dwProductVersionMS>>16)&0xFF)<<24)| + ((vsffi->dwProductVersionMS&0xFF)<<16)| + (((vsffi->dwProductVersionLS>>16)&0xFF)<<8)| + (vsffi->dwProductVersionLS&0xFF); + mir_free(pVerInfo); + return (INT_PTR)ver; +} + +static INT_PTR GetMirandaVersionText(WPARAM wParam,LPARAM lParam) +{ + TCHAR filename[MAX_PATH], *productVersion; + DWORD unused; + DWORD verInfoSize; + UINT blockSize; + PVOID pVerInfo; + + GetModuleFileName(NULL,filename,SIZEOF(filename)); + verInfoSize=GetFileVersionInfoSize(filename,&unused); + pVerInfo=mir_alloc(verInfoSize); + GetFileVersionInfo(filename,0,verInfoSize,pVerInfo); + VerQueryValue(pVerInfo,_T("\\StringFileInfo\\000004b0\\ProductVersion"),(LPVOID*)&productVersion,&blockSize); +#if defined( _WIN64 ) + mir_snprintf(( char* )lParam, wParam, "%S x64 Unicode", productVersion ); +#elif defined( _UNICODE ) + mir_snprintf(( char* )lParam, wParam, "%S Unicode", productVersion ); +#else + lstrcpyn((char*)lParam,productVersion,wParam); +#endif + mir_free(pVerInfo); + return 0; +} + +INT_PTR WaitOnHandle(WPARAM wParam,LPARAM lParam) +{ + if(waitObjectCount>=MAXIMUM_WAIT_OBJECTS-1) return 1; + hWaitObjects[waitObjectCount]=(HANDLE)wParam; + pszWaitServices[waitObjectCount]=(char*)lParam; + waitObjectCount++; + return 0; +} + +static INT_PTR RemoveWait(WPARAM wParam, LPARAM) +{ + int i; + + for(i=0;immi_malloc = mir_alloc; + mmi->mmi_realloc = mir_realloc; + mmi->mmi_free = mir_free; + + switch( mmi->cbSize ) { + case sizeof(struct MM_INTERFACE): + mmi->mir_snprintf = mir_snprintf; + mmi->mir_sntprintf = mir_sntprintf; + mmi->mir_vsnprintf = mir_vsnprintf; + mmi->mir_vsntprintf = mir_vsntprintf; + mmi->mir_a2u_cp = mir_a2u_cp; + mmi->mir_a2u = mir_a2u; + mmi->mir_u2a_cp = mir_u2a_cp; + mmi->mir_u2a = mir_u2a; + // fall through + + case MMI_SIZE_V2: + mmi->mmi_calloc = mir_calloc; + mmi->mmi_strdup = mir_strdup; + mmi->mmi_wstrdup = mir_wstrdup; + // fall through + + case MMI_SIZE_V1: + break; + + default: +#if defined( _DEBUG ) + DebugBreak(); +#endif + return 1; + } + + return 0; +} + +INT_PTR GetListInterface(WPARAM, LPARAM lParam) +{ + struct LIST_INTERFACE *li = (struct LIST_INTERFACE*) lParam; + if ( li == NULL ) + return 1; + + switch(li->cbSize) { + case LIST_INTERFACE_V3_SIZE: + li->List_Copy = List_Copy; + li->List_ObjCopy = List_ObjCopy; + + case LIST_INTERFACE_V2_SIZE: + li->List_InsertPtr = List_InsertPtr; + li->List_RemovePtr = List_RemovePtr; + + case LIST_INTERFACE_V1_SIZE: + li->List_Create = List_Create; + li->List_Destroy = List_Destroy; + li->List_Find = List_Find; + li->List_GetIndex = List_GetIndex; + li->List_Insert = List_Insert; + li->List_Remove = List_Remove; + li->List_IndexOf = List_IndexOf; + return 0; + } + return 1; +} + +INT_PTR GetUtfInterface(WPARAM, LPARAM lParam) +{ + struct UTF8_INTERFACE *utfi = (struct UTF8_INTERFACE*) lParam; + if ( utfi == NULL ) + return 1; + + switch( utfi->cbSize ) { + case UTF8_INTERFACE_SIZEOF_V1: + case UTF8_INTERFACE_SIZEOF_V2: + case sizeof( struct UTF8_INTERFACE ): + break; + + default: + return 1; + } + + utfi->utf8_decode = Utf8Decode; + utfi->utf8_decodecp = Utf8DecodeCP; + utfi->utf8_encode = Utf8Encode; + utfi->utf8_encodecp = Utf8EncodeCP; + utfi->utf8_encodeW = Utf8EncodeUcs2; + if (utfi->cbSize > UTF8_INTERFACE_SIZEOF_V1) + utfi->utf8_decodeW = Utf8DecodeUcs2; + if (utfi->cbSize > UTF8_INTERFACE_SIZEOF_V2) + utfi->utf8_lenW = Ucs2toUtf8Len; + + return 0; +} + +int LoadSystemModule(void) +{ + INITCOMMONCONTROLSEX icce = {0}; + icce.dwSize = sizeof(icce); + icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES; + InitCommonControlsEx(&icce); + + if (IsWinVerXPPlus()) { + hAPCWindow=CreateWindowEx(0,_T("ComboLBox"),NULL,0, 0,0,0,0, NULL,NULL,NULL,NULL); + SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); + DestroyWindow(hAPCWindow); + hAPCWindow = NULL; + } + + hAPCWindow=CreateWindowEx(0,_T("STATIC"),NULL,0, 0,0,0,0, NULL,NULL,NULL,NULL); // lame + SetWindowLongPtr(hAPCWindow,GWLP_WNDPROC,(LONG_PTR)APCWndProc); + hStackMutex=CreateMutex(NULL,FALSE,NULL); + hMirandaShutdown=CreateEvent(NULL,TRUE,FALSE,NULL); + hThreadQueueEmpty=CreateEvent(NULL,TRUE,TRUE,NULL); + + hShutdownEvent=CreateHookableEvent(ME_SYSTEM_SHUTDOWN); + hPreShutdownEvent=CreateHookableEvent(ME_SYSTEM_PRESHUTDOWN); + hModulesLoadedEvent=CreateHookableEvent(ME_SYSTEM_MODULESLOADED); + hOkToExitEvent=CreateHookableEvent(ME_SYSTEM_OKTOEXIT); + + CreateServiceFunction(MS_SYSTEM_FORK_THREAD,ForkThreadService); + CreateServiceFunction(MS_SYSTEM_FORK_THREAD_EX,ForkThreadServiceEx); + CreateServiceFunction(MS_SYSTEM_THREAD_PUSH,UnwindThreadPush); + CreateServiceFunction(MS_SYSTEM_THREAD_POP,UnwindThreadPop); + CreateServiceFunction(MS_SYSTEM_TERMINATED,MirandaIsTerminated); + CreateServiceFunction(MS_SYSTEM_OKTOEXIT,OkToExit); + CreateServiceFunction(MS_SYSTEM_GETVERSION,GetMirandaVersion); + CreateServiceFunction(MS_SYSTEM_GETVERSIONTEXT,GetMirandaVersionText); + CreateServiceFunction(MS_SYSTEM_WAITONHANDLE,WaitOnHandle); + CreateServiceFunction(MS_SYSTEM_REMOVEWAIT,RemoveWait); + CreateServiceFunction(MS_SYSTEM_GET_LI,GetListInterface); + CreateServiceFunction(MS_SYSTEM_GET_MMI,GetMemoryManagerInterface); + CreateServiceFunction(MS_SYSTEM_GET_UTFI,GetUtfInterface); + CreateServiceFunction(MS_SYSTEM_GETEXCEPTFILTER,GetExceptionFilter); + CreateServiceFunction(MS_SYSTEM_SETEXCEPTFILTER,SetExceptionFilter); + + InitPathUtils(); + return 0; +} -- cgit v1.2.3