From 939b54967dcda681318271d203eedd1dcf5ce934 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 27 Jun 2012 05:25:13 +0000 Subject: renamed as the rest git-svn-id: http://svn.miranda-ng.org/main/trunk@645 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Mir_core/commonheaders.cpp | 2 + plugins/Mir_core/commonheaders.h | 63 +++ plugins/Mir_core/langpack.cpp | 630 ++++++++++++++++++++++++++ plugins/Mir_core/lists.cpp | 278 ++++++++++++ plugins/Mir_core/memory.cpp | 280 ++++++++++++ plugins/Mir_core/mir_core.def | 5 + plugins/Mir_core/mir_core_10.vcxproj | 217 +++++++++ plugins/Mir_core/mir_core_10.vcxproj.filters | 67 +++ plugins/Mir_core/miranda.cpp | 403 +++++++++++++++++ plugins/Mir_core/miranda.h | 128 ++++++ plugins/Mir_core/modules.cpp | 644 +++++++++++++++++++++++++++ plugins/Mir_core/path.cpp | 210 +++++++++ plugins/Mir_core/utf.cpp | 406 +++++++++++++++++ plugins/Mir_core/utils.cpp | 150 +++++++ plugins/mir_core/commonheaders.cpp | 2 - plugins/mir_core/commonheaders.h | 63 --- plugins/mir_core/langpack.cpp | 630 -------------------------- plugins/mir_core/lists.cpp | 278 ------------ plugins/mir_core/memory.cpp | 280 ------------ plugins/mir_core/mir_core.def | 5 - plugins/mir_core/mir_core_10.vcxproj | 217 --------- plugins/mir_core/mir_core_10.vcxproj.filters | 67 --- plugins/mir_core/miranda.cpp | 403 ----------------- plugins/mir_core/miranda.h | 128 ------ plugins/mir_core/modules.cpp | 644 --------------------------- plugins/mir_core/path.cpp | 210 --------- plugins/mir_core/utf.cpp | 406 ----------------- plugins/mir_core/utils.cpp | 150 ------- 28 files changed, 3483 insertions(+), 3483 deletions(-) create mode 100644 plugins/Mir_core/commonheaders.cpp create mode 100644 plugins/Mir_core/commonheaders.h create mode 100644 plugins/Mir_core/langpack.cpp create mode 100644 plugins/Mir_core/lists.cpp create mode 100644 plugins/Mir_core/memory.cpp create mode 100644 plugins/Mir_core/mir_core.def create mode 100644 plugins/Mir_core/mir_core_10.vcxproj create mode 100644 plugins/Mir_core/mir_core_10.vcxproj.filters create mode 100644 plugins/Mir_core/miranda.cpp create mode 100644 plugins/Mir_core/miranda.h create mode 100644 plugins/Mir_core/modules.cpp create mode 100644 plugins/Mir_core/path.cpp create mode 100644 plugins/Mir_core/utf.cpp create mode 100644 plugins/Mir_core/utils.cpp delete mode 100644 plugins/mir_core/commonheaders.cpp delete mode 100644 plugins/mir_core/commonheaders.h delete mode 100644 plugins/mir_core/langpack.cpp delete mode 100644 plugins/mir_core/lists.cpp delete mode 100644 plugins/mir_core/memory.cpp delete mode 100644 plugins/mir_core/mir_core.def delete mode 100644 plugins/mir_core/mir_core_10.vcxproj delete mode 100644 plugins/mir_core/mir_core_10.vcxproj.filters delete mode 100644 plugins/mir_core/miranda.cpp delete mode 100644 plugins/mir_core/miranda.h delete mode 100644 plugins/mir_core/modules.cpp delete mode 100644 plugins/mir_core/path.cpp delete mode 100644 plugins/mir_core/utf.cpp delete mode 100644 plugins/mir_core/utils.cpp (limited to 'plugins') diff --git a/plugins/Mir_core/commonheaders.cpp b/plugins/Mir_core/commonheaders.cpp new file mode 100644 index 0000000000..95b2201163 --- /dev/null +++ b/plugins/Mir_core/commonheaders.cpp @@ -0,0 +1,2 @@ +#include "commonheaders.h" + diff --git a/plugins/Mir_core/commonheaders.h b/plugins/Mir_core/commonheaders.h new file mode 100644 index 0000000000..2d04e12f4b --- /dev/null +++ b/plugins/Mir_core/commonheaders.h @@ -0,0 +1,63 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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. +*/ + +#define MIRANDA_VER 0x0A00 + +#define WINVER 0x0700 +#define _WIN32_WINNT 0x0700 +#define _WIN32_IE 0x0601 + +#define INCL_WINSOCK_API_TYPEDEFS 1 + +#include "m_stdhdr.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "miranda.h" + +#include +#include diff --git a/plugins/Mir_core/langpack.cpp b/plugins/Mir_core/langpack.cpp new file mode 100644 index 0000000000..d38dd6807d --- /dev/null +++ b/plugins/Mir_core/langpack.cpp @@ -0,0 +1,630 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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 LANGPACK_BUF_SIZE 4000 + +static int CompareMuuids(const LangPackMuuid* p1, const LangPackMuuid* p2) +{ + return memcmp(&p1->muuid, &p2->muuid, sizeof(MUUID)); +} + +static LIST lMuuids(10, CompareMuuids); +static LangPackMuuid* pCurrentMuuid = NULL; + +static BOOL bModuleInitialized = FALSE; + +struct LangPackEntry { + DWORD englishHash; + char *local; + wchar_t *wlocal; + LangPackMuuid* pMuuid; + LangPackEntry* pNext; // for langpack items with the same hash value +}; + +struct LangPackStruct { + TCHAR filename[MAX_PATH]; + TCHAR filePath[MAX_PATH]; + char language[64]; + char lastModifiedUsing[64]; + char authors[256]; + char authorEmail[128]; + LangPackEntry *entry; + int entryCount, entriesAlloced; + LCID localeID; + UINT defaultANSICp; +} static langPack; + +static int IsEmpty(char *str) +{ + int i = 0; + + while (str[i]) + { + if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n') + return 0; + i++; + } + return 1; +} + +static void ConvertBackslashes(char *str, UINT fileCp) +{ + char *pstr; + for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) { + if (*pstr == '\\') { + switch(pstr[1]) { + case 'n': *pstr = '\n'; break; + case 't': *pstr = '\t'; break; + case 'r': *pstr = '\r'; break; + default: *pstr = pstr[1]; break; + } + memmove(pstr+1, pstr+2, strlen(pstr+2) + 1); +} } } + +#ifdef _DEBUG +//#pragma optimize("gt", on) +#endif + +// MurmurHash2 +MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + const unsigned int m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + unsigned int h = len; + + // Mix 4 bytes at a time into the hash + const unsigned char * data = (const unsigned char *)key; + + while (len >= 4) + { + unsigned int k = *(unsigned int *)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2) +{ + if (arg1->englishHash < arg2->englishHash) return -1; + if (arg1->englishHash > arg2->englishHash) return 1; + + return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1; +} + +static void swapBytes(void* p, size_t iSize) +{ + char *head = (char *)p; // here + char *tail = head + iSize - 1; + + for (; tail > head; --tail, ++head) { + char temp = *head; + *head = *tail; + *tail = temp; + } +} + +static bool EnterMuuid(const char* p, MUUID& result) +{ + if (*p++ != '{') + return false; + + BYTE* d = (BYTE*)&result; + + for (int nBytes = 0; *p && nBytes < 24; p++) { + if (*p == '-') + continue; + + if (*p == '}') + break; + + if ( !isxdigit(*p)) + return false; + + if ( !isxdigit(p[1])) + return false; + + int c = 0; + if (sscanf(p, "%2x", &c) != 1) + return false; + + *d++ = (BYTE)c; + nBytes++; + p++; + } + + if (*p != '}') + return false; + + swapBytes(&result.a, sizeof(result.a)); + swapBytes(&result.b, sizeof(result.b)); + swapBytes(&result.c, sizeof(result.c)); + return true; +} + +static void LoadLangPackFile(FILE* fp, char* line, UINT fileCp) +{ + while ( !feof(fp)) { + if (fgets(line, LANGPACK_BUF_SIZE, fp) == NULL) + break; + + if (IsEmpty(line) || line[0] == ';' || line[0] == 0) + continue; + + rtrim(line); + + if (line[0] == '#') { + strlwr(line); + + if ( !memcmp(line+1, "include", 7)) { + TCHAR tszFileName[ MAX_PATH ]; + TCHAR* fileName = mir_a2t(ltrim(line+9)); + mir_sntprintf(tszFileName, SIZEOF(tszFileName), _T("%s%s"), langPack.filePath, fileName); + mir_free(fileName); + + FILE* p = _tfopen(tszFileName, _T("r")); + if (p) { + line[0] = 0; + fgets(line, SIZEOF(line), p); + + UINT fileCp = CP_ACP; + if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') + { + fileCp = CP_UTF8; + fseek(p, 3, SEEK_SET); + } + else + { + fileCp = langPack.defaultANSICp; + fseek(p, 0, SEEK_SET); + } + + LoadLangPackFile(p, line, fileCp); + fclose(p); + } + } + else if ( !memcmp(line+1, "muuid", 5)) { + MUUID t; + if ( !EnterMuuid(line+7, t)) + continue; + + LangPackMuuid* pNew = (LangPackMuuid*)mir_alloc(sizeof(LangPackMuuid)); + memcpy(&pNew->muuid, &t, sizeof(t)); + pNew->pInfo = NULL; + lMuuids.insert(pNew); + pCurrentMuuid = pNew; + } + + continue; + } + + ConvertBackslashes(line, fileCp); + + if (line[0] == '[' && line[ lstrlenA(line)-1 ] == ']') { + if (langPack.entryCount && langPack.entry[ langPack.entryCount-1].local == NULL) + langPack.entryCount--; + + char* pszLine = line+1; + line[ lstrlenA(line)-1 ] = '\0'; + if (++langPack.entryCount > langPack.entriesAlloced) { + langPack.entriesAlloced += 128; + langPack.entry = (LangPackEntry*)mir_realloc(langPack.entry, sizeof(LangPackEntry)*langPack.entriesAlloced); + } + + LangPackEntry* E = &langPack.entry[ langPack.entryCount-1 ]; + E->englishHash = mir_hashstr(pszLine); + E->local = NULL; + E->wlocal = NULL; + E->pMuuid = pCurrentMuuid; + E->pNext = NULL; + continue; + } + + if ( !langPack.entryCount) + continue; + + LangPackEntry* E = &langPack.entry[ langPack.entryCount-1 ]; + if (E->local == NULL) { + E->local = mir_strdup(line); + if (fileCp == CP_UTF8) + Utf8DecodeCP(E->local, langPack.defaultANSICp, NULL); + + int iNeeded = MultiByteToWideChar(fileCp, 0, line, -1, 0, 0); + E->wlocal = (wchar_t *)mir_alloc((iNeeded+1) * sizeof(wchar_t)); + MultiByteToWideChar(fileCp, 0, line, -1, E->wlocal, iNeeded); + } + else { + size_t iOldLenA = strlen(E->local); + E->local = (char*)mir_realloc(E->local, iOldLenA + strlen(line) + 2); + strcat(E->local, "\n"); + strcat(E->local, line); + + if (fileCp == CP_UTF8) + Utf8DecodeCP(E->local + iOldLenA + 1, langPack.defaultANSICp, NULL); + + int iNeeded = MultiByteToWideChar(fileCp, 0, line, -1, 0, 0); + size_t iOldLen = wcslen(E->wlocal); + E->wlocal = (wchar_t*)mir_realloc(E->wlocal, (sizeof(wchar_t) * (iOldLen + iNeeded + 2))); + wcscat(E->wlocal, L"\n"); + MultiByteToWideChar(fileCp, 0, line, -1, E->wlocal + iOldLen + 1, iNeeded); + } + } +} + +MIR_CORE_DLL(int) LoadLangPack(const TCHAR *szLangPack) +{ + int startOfLine=0; + USHORT langID; + + lstrcpy(langPack.filename, szLangPack); + lstrcpy(langPack.filePath, szLangPack); + TCHAR* p = _tcsrchr(langPack.filePath, '\\'); + if (p) + p[1] = 0; + + FILE *fp = _tfopen(szLangPack, _T("rt")); + if (fp == NULL) + return 1; + + char line[ LANGPACK_BUF_SIZE ] = ""; + fgets(line, SIZEOF(line), fp); + + UINT fileCp = CP_ACP; + size_t lineLen = strlen(line); + if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') + { + fileCp = CP_UTF8; + memmove(line, line + 3, lineLen - 2); + } + + lrtrim(line); + if (lstrcmpA(line, "Miranda Language Pack Version 1")) { + fclose(fp); + return 2; + } + + //headers + while ( !feof(fp)) { + startOfLine = ftell(fp); + if (fgets(line, SIZEOF(line), fp) == NULL) + break; + + lrtrim(line); + if (IsEmpty(line) || line[0] == ';' || line[0] == 0) + continue; + + if (line[0] == '[' || line[0] == '#') + break; + + char* pszColon = strchr(line, ':'); + if (pszColon == NULL) { + fclose(fp); + return 3; + } + + *pszColon++ = 0; + if ( !lstrcmpA(line, "Language")) {mir_snprintf(langPack.language, sizeof(langPack.language), "%s", pszColon); lrtrim(langPack.language);} + else if ( !lstrcmpA(line, "Last-Modified-Using")) {mir_snprintf(langPack.lastModifiedUsing, sizeof(langPack.lastModifiedUsing), "%s", pszColon); lrtrim(langPack.lastModifiedUsing);} + else if ( !lstrcmpA(line, "Authors")) {mir_snprintf(langPack.authors, sizeof(langPack.authors), "%s", pszColon); lrtrim(langPack.authors);} + else if ( !lstrcmpA(line, "Author-email")) {mir_snprintf(langPack.authorEmail, sizeof(langPack.authorEmail), "%s", pszColon); lrtrim(langPack.authorEmail);} + else if ( !lstrcmpA(line, "Locale")) { + char szBuf[20], *stopped; + + lrtrim(pszColon + 1); + langID = (USHORT)strtol(pszColon, &stopped, 16); + langPack.localeID = MAKELCID(langID, 0); + GetLocaleInfoA(langPack.localeID, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10); + szBuf[5] = 0; // codepages have max. 5 digits + langPack.defaultANSICp = atoi(szBuf); + if (fileCp == CP_ACP) + fileCp = langPack.defaultANSICp; + } + } + + //body + fseek(fp, startOfLine, SEEK_SET); + langPack.entriesAlloced = 0; + + LoadLangPackFile(fp, line, fileCp); + fclose(fp); + pCurrentMuuid = NULL; + + qsort(langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2) +{ + if (arg1->englishHash < arg2->englishHash) return -1; + if (arg1->englishHash > arg2->englishHash) return 1; + return 0; +} + +static char *LangPackTranslateString(LangPackMuuid* pUuid, const char *szEnglish, const int W) +{ + if (langPack.entryCount == 0 || szEnglish == NULL) + return (char*)szEnglish; + + LangPackEntry key, *entry; + key.englishHash = W ? mir_hashstrW((WCHAR*)szEnglish) : mir_hashstr(szEnglish); + entry = (LangPackEntry*)bsearch(&key, langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2); + if (entry == NULL) + return (char*)szEnglish; + + // try to find the exact match, otherwise the first entry will be returned + if (pUuid) { + for (LangPackEntry* p = entry->pNext; p != NULL; p = p->pNext) { + if (p->pMuuid == pUuid) { + entry = p; + break; + } } } + + return W ? (char *)entry->wlocal : entry->local; +} + +MIR_CORE_DLL(int) LangPackGetDefaultCodePage() +{ + return langPack.defaultANSICp; +} + +MIR_CORE_DLL(int) LangPackGetDefaultLocale() +{ + return (langPack.localeID == 0) ? LOCALE_USER_DEFAULT : langPack.localeID; +} + +MIR_CORE_DLL(TCHAR*) LangPackPcharToTchar(const char* pszStr) +{ + if (pszStr == NULL) + return NULL; + + { int len = (int)strlen(pszStr); + TCHAR* result = (TCHAR*)alloca((len+1)*sizeof(TCHAR)); + MultiByteToWideChar(LangPackGetDefaultCodePage(), 0, pszStr, -1, result, len); + result[len] = 0; + return mir_wstrdup(TranslateW(result)); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(char*) TranslateA_LP(const char* str, int hLangpack) +{ + return (char*)LangPackTranslateString(LangPackLookupUuid(hLangpack), str, FALSE); +} + +MIR_CORE_DLL(WCHAR*) TranslateW_LP(const WCHAR* str, int hLangpack) +{ + return (WCHAR*)LangPackTranslateString(LangPackLookupUuid(hLangpack), (LPCSTR)str, TRUE); +} + +MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, int hLangpack) +{ + LangPackMuuid* uuid = LangPackLookupUuid(hLangpack); + + MENUITEMINFO mii; + mii.cbSize = MENUITEMINFO_V4_SIZE; + for (int i = GetMenuItemCount(hMenu)-1; i >= 0; i--) { + TCHAR str[256]; + mii.fMask = MIIM_TYPE|MIIM_SUBMENU; + mii.dwTypeData = (TCHAR*)str; + mii.cch = SIZEOF(str); + GetMenuItemInfo(hMenu, i, TRUE, &mii); + + if (mii.cch && mii.dwTypeData) { + TCHAR* result = (TCHAR*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE); + if (result != mii.dwTypeData) { + mii.dwTypeData = result; + mii.fMask = MIIM_TYPE; + SetMenuItemInfo(hMenu, i, TRUE, &mii); + } } + + if (mii.hSubMenu != NULL) TranslateMenu_LP(mii.hSubMenu, hLangpack); + } +} + +static void TranslateWindow(LangPackMuuid* pUuid, HWND hwnd) +{ + TCHAR title[2048]; + GetWindowText(hwnd, title, SIZEOF(title)); + + TCHAR* result = (TCHAR*)LangPackTranslateString(pUuid, (const char*)title, TRUE); + if (result != title) + SetWindowText(hwnd, result); +} + +struct LANGPACKTRANSLATEDIALOG +{ + HWND hwndDlg; + int hLangpack; +}; + +static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam) +{ + int hLangpack = (int)lParam; + TCHAR szClass[32]; + int id = GetDlgCtrlID(hwnd); + + LangPackMuuid* uuid = LangPackLookupUuid(hLangpack); + + GetClassName(hwnd, szClass, SIZEOF(szClass)); + if ( !lstrcmpi(szClass, _T("static")) || !lstrcmpi(szClass, _T("hyperlink")) || !lstrcmpi(szClass, _T("button")) || !lstrcmpi(szClass, _T("MButtonClass")) || !lstrcmpi(szClass, _T("MHeaderbarCtrl"))) + TranslateWindow(uuid, hwnd); + else if ( !lstrcmpi(szClass, _T("edit"))) { + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) + TranslateWindow(uuid, hwnd); + } + return TRUE; +} + +MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, int hLangpack) +{ + TranslateWindow(LangPackLookupUuid(hLangpack), hDlg); + EnumChildWindows(hDlg, TranslateDialogEnumProc, hLangpack); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(LangPackMuuid*) LangPackLookupUuid(WPARAM wParam) +{ + int idx = (wParam >> 16) & 0xFFFF; + return (idx > 0 && idx <= lMuuids.getCount()) ? lMuuids[ idx-1 ] : NULL; +} + +MIR_CORE_DLL(int) LangPackMarkPluginLoaded(PLUGININFOEX* pInfo) +{ + LangPackMuuid tmp; tmp.muuid = pInfo->uuid; + int idx = lMuuids.getIndex(&tmp); + if (idx == -1) + return 0; + + lMuuids[ idx ]->pInfo = pInfo; + return (idx+1) << 16; +} + +MIR_CORE_DLL(void) LangPackDropUnusedItems(void) +{ + if (langPack.entryCount == 0) + return; + + LangPackEntry *s = langPack.entry+1, *d = s, *pLast = langPack.entry; + DWORD dwSavedHash = langPack.entry->englishHash; + bool bSortNeeded = false; + + for (int i=1; i < langPack.entryCount; i++, s++) { + if (s->pMuuid != NULL && s->pMuuid->pInfo == NULL) + s->pMuuid = NULL; + + if (s->englishHash != dwSavedHash) { + pLast = d; + if (s != d) + *d++ = *s; + else + d++; + dwSavedHash = s->englishHash; + } + else { + bSortNeeded = true; + LangPackEntry* p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry)); + *p = *s; + pLast->pNext = p; pLast = p; + } + } + + if (bSortNeeded) { + langPack.entryCount = (int)(d - langPack.entry); + qsort(langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int LoadLangPackModule(void) +{ + bModuleInitialized = TRUE; + + ZeroMemory(&langPack, sizeof(langPack)); + + TCHAR szSearch[MAX_PATH]; + PathToAbsoluteT(_T("langpack_*.txt"), szSearch, NULL); + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(szSearch, &fd); + if (hFind != INVALID_HANDLE_VALUE) { + PathToAbsoluteT(fd.cFileName, szSearch, NULL); + FindClose(hFind); + LoadLangPack(szSearch); + } + return 0; +} + +void UnloadLangPackModule() +{ + if ( !bModuleInitialized) return; + + int i; + for (i=0; i < lMuuids.getCount(); i++) + mir_free(lMuuids[i]); + lMuuids.destroy(); + + LangPackEntry* p = langPack.entry; + for (i=0; i < langPack.entryCount; i++, p++) { + if (p->pNext != NULL) { + for (LangPackEntry* p1 = p->pNext; p1 != NULL;) { + LangPackEntry* p2 = p1; p1 = p1->pNext; + mir_free(p2->local); + mir_free(p2->wlocal); + mir_free(p2); + } } + + mir_free(p->local); + mir_free(p->wlocal); + } + + if (langPack.entryCount) { + mir_free(langPack.entry); + langPack.entry=0; + langPack.entryCount=0; +} } + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(void) ReloadLangpack(TCHAR *pszStr) +{ + if (pszStr == NULL) + pszStr = langPack.filename; + + UnloadLangPackModule(); + LoadLangPack(pszStr); + LangPackDropUnusedItems(); +} diff --git a/plugins/Mir_core/lists.cpp b/plugins/Mir_core/lists.cpp new file mode 100644 index 0000000000..e4996fc156 --- /dev/null +++ b/plugins/Mir_core/lists.cpp @@ -0,0 +1,278 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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" + +/* a simple sorted list implementation */ + +MIR_CORE_DLL(SortedList*) List_Create(int p_limit, int p_increment) +{ + SortedList* result = (SortedList*)mir_calloc(sizeof(SortedList)); + if (result == NULL) + return(NULL); + + result->increment = p_increment; + result->limit = p_limit; + return(result); +} + +MIR_CORE_DLL(void) List_Destroy(SortedList* p_list) +{ + if (p_list == NULL) + return; + + if (p_list->items != NULL) { + mir_free(p_list->items); + p_list->items = NULL; + } + + p_list->realCount = p_list->limit = 0; +} + +MIR_CORE_DLL(void*) List_Find(SortedList* p_list, void* p_value) +{ + int index; + + if ( !List_GetIndex(p_list, p_value, &index)) + return(NULL); + + return(p_list->items[ index ]); +} + +#ifdef _DEBUG +#pragma optimize("gt", on) +#endif + +MIR_CORE_DLL(int) List_GetIndex(SortedList* p_list, void* p_value, int* p_index) +{ + if (p_value == NULL) + { + *p_index = -1; + return 0; + } + + switch ((INT_PTR)p_list->sortFunc) + { + case 0: + break; + + case HandleKeySort: +#ifdef _WIN64 + { + const unsigned __int64 val = *(unsigned __int64 *)p_value; + int low = 0; + int high = p_list->realCount - 1; + + while (low <= high) + { + int i = (low + high) / 2; + unsigned __int64 vali = *(unsigned __int64 *)p_list->items[i]; + if (vali == val) + { + *p_index = i; + return 1; + } + + if (vali < val) + low = i + 1; + else + high = i - 1; + } + + *p_index = low; + } + break; +#endif + + case NumericKeySort: + { + const unsigned val = *(unsigned *)p_value; + int low = 0; + int high = p_list->realCount - 1; + + while (low <= high) + { + int i = (low + high) / 2; + unsigned vali = *(unsigned *)p_list->items[i]; + if (vali == val) + { + *p_index = i; + return 1; + } + + if (vali < val) + low = i + 1; + else + high = i - 1; + } + + *p_index = low; + } + break; + + case PtrKeySort: + { + int low = 0; + int high = p_list->realCount - 1; + + while (low <= high) + { + int i = (low + high) / 2; + const void* vali = p_list->items[i]; + if (vali == p_value) + { + *p_index = i; + return 1; + } + + if (vali < p_value) + low = i + 1; + else + high = i - 1; + } + + *p_index = low; + } + break; + + default: + { + int low = 0; + int high = p_list->realCount - 1; + + while (low <= high) + { + int i = (low + high) / 2; + int result = p_list->sortFunc(p_list->items[i], p_value); + if (result == 0) + { + *p_index = i; + return 1; + } + + if (result < 0) + low = i + 1; + else + high = i - 1; + } + + *p_index = low; + } + break; + } + + return 0; +} + +MIR_CORE_DLL(int) List_IndexOf(SortedList* p_list, void* p_value) +{ + if (p_value == NULL) + return -1; + + int i; + for (i=0; i < p_list->realCount; i++) + if (p_list->items[i] == p_value) + return i; + + return -1; +} + +#ifdef _DEBUG +#pragma optimize("", on) +#endif + +MIR_CORE_DLL(int) List_Insert(SortedList* p_list, void* p_value, int p_index) +{ + if (p_value == NULL || p_index > p_list->realCount) + return 0; + + if (p_list->realCount == p_list->limit) + { + p_list->items = (void**)mir_realloc(p_list->items, sizeof(void*)*(p_list->realCount + p_list->increment)); + p_list->limit += p_list->increment; + } + + if (p_index < p_list->realCount) + memmove(p_list->items+p_index+1, p_list->items+p_index, sizeof(void*)*(p_list->realCount-p_index)); + + p_list->realCount++; + + p_list->items[ p_index ] = p_value; + return 1; +} + +MIR_CORE_DLL(int) List_InsertPtr(SortedList* list, void* p) +{ + if (p == NULL) + return -1; + + int idx = list->realCount; + List_GetIndex(list, p, &idx); + return List_Insert(list, p, idx); +} + +MIR_CORE_DLL(int) List_Remove(SortedList* p_list, int index) +{ + if (index < 0 || index > p_list->realCount) + return(0); + + p_list->realCount--; + if (p_list->realCount > index) + { + memmove(p_list->items+index, p_list->items+index+1, sizeof(void*)*(p_list->realCount-index)); + p_list->items[ p_list->realCount ] = NULL; + } + + return 1; +} + +MIR_CORE_DLL(int) List_RemovePtr(SortedList* list, void* p) +{ + int idx = -1; + if (List_GetIndex(list, p, &idx)) + List_Remove(list, idx); + + return idx; +} + +MIR_CORE_DLL(void) List_Copy(SortedList* s, SortedList* d, size_t itemSize) +{ + d->increment = s->increment; + d->limit = s->limit; + d->realCount = s->realCount; + d->items = (void**)mir_alloc( sizeof(void*) * d->realCount); + memcpy(d->items, s->items, sizeof(void*) * d->realCount); +} + +MIR_CORE_DLL(void) List_ObjCopy(SortedList* s, SortedList* d, size_t itemSize) +{ + int i; + + d->increment = s->increment; + d->sortFunc = s->sortFunc; + + for (i = 0; i < s->realCount; i++) { + void* item = new char[ itemSize ]; + memcpy(item, s->items[i], itemSize); + List_Insert(d, item, i); +} } diff --git a/plugins/Mir_core/memory.cpp b/plugins/Mir_core/memory.cpp new file mode 100644 index 0000000000..25b4d880c2 --- /dev/null +++ b/plugins/Mir_core/memory.cpp @@ -0,0 +1,280 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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 BLOCK_ALLOCED 0xABBABABA +#define BLOCK_FREED 0xDEADBEEF + +static int CheckBlock(void* blk) +{ + int result = FALSE; + char* p = (char*)blk - sizeof(DWORD)*2; + DWORD size, *b, *e; + + __try + { + size = *(DWORD*)p; + b = (DWORD*)&p[ sizeof(DWORD) ]; + e = (DWORD*)&p[ sizeof(DWORD)*2 + size ]; + + if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED) + { + if (*b == BLOCK_FREED && *e == BLOCK_FREED) + OutputDebugStringA("memory block is already deleted\n"); + else + OutputDebugStringA("memory block is corrupted\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + } + else result = TRUE; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugStringA("access violation during checking memory block\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + } + + return result; +} + +/******************************************************************************/ + +MIR_CORE_DLL(void*) mir_alloc(size_t size) +{ + if (size == 0) + return NULL; + { + char* p = (char*)malloc(size + sizeof(DWORD)*3); + if (p == NULL) { + OutputDebugStringA("memory overflow\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + return NULL; + } + + *(DWORD*)p = (DWORD)size; + *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_ALLOCED; + *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_ALLOCED; + return p + sizeof(DWORD)*2; +} } + +/******************************************************************************/ + +MIR_CORE_DLL(void*) mir_calloc(size_t size) +{ + void* p = mir_alloc(size); + if (p != NULL) + memset(p, 0, size); + return p; +} + +/******************************************************************************/ + +MIR_CORE_DLL(void*) mir_realloc(void* ptr, size_t size) +{ + char* p; + + if (ptr != NULL) { + if ( !CheckBlock(ptr)) + return NULL; + p = (char*)ptr - sizeof(DWORD)*2; + } + else p = NULL; + + p = (char*)realloc(p, size + sizeof(DWORD)*3); + if (p == NULL) { + OutputDebugStringA("memory overflow\n"); + #if defined(_DEBUG) + DebugBreak(); + #endif + return NULL; + } + + *(DWORD*)p = (DWORD)size; + *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_ALLOCED; + *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_ALLOCED; + return p + sizeof(DWORD)*2; +} + +/******************************************************************************/ + +MIR_CORE_DLL(void) mir_free(void* ptr) +{ + char* p; + DWORD size; + + if (ptr == NULL) + return; + if ( !CheckBlock(ptr)) + return; + + p = (char*)ptr - sizeof(DWORD)*2; + size = *(DWORD*)p; + *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_FREED; + *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_FREED; + free(p); +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_strdup(const char* str) +{ + if (str != NULL) { + char* p = (char*)mir_alloc(strlen(str)+1); + if (p) + strcpy(p, str); + return p; + } + return NULL; +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_strndup(const char* str, size_t len) +{ + if (str != NULL && len != 0) { + char* p = (char*)mir_alloc(len + 1); + if ( !p) { + memcpy(p, str, len); + p[ len ] = 0; + } + return p; + } + return NULL; +} + +/******************************************************************************/ + +MIR_CORE_DLL(WCHAR*) mir_wstrdup(const WCHAR* str) +{ + if (str != NULL) { + WCHAR* p = (WCHAR*)mir_alloc(sizeof(WCHAR)*(wcslen(str)+1)); + if (p) + wcscpy(p, str); + return p; + } + return NULL; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...) +{ + va_list va; + int len; + + va_start(va, fmt); + len = _vsnprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_sntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, ...) +{ + va_list va; + int len; + + va_start(va, fmt); + len = _vsntprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va) +{ + int len; + + len = _vsnprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(int) mir_vsntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, va_list va) +{ + int len; + + len = _vsntprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +/******************************************************************************/ + +MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage) +{ + if (src == NULL) + return NULL; + + int cbLen = MultiByteToWideChar(codepage, 0, src, -1, NULL, 0); + wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1)); + if (result == NULL) + return NULL; + + MultiByteToWideChar(codepage, 0, src, -1, result, cbLen); + result[ cbLen ] = 0; + return result; +} + +/******************************************************************************/ + +MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src) +{ + return mir_a2u_cp(src, LangPackGetDefaultCodePage()); +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage) +{ + if (src == NULL) + return NULL; + + int cbLen = WideCharToMultiByte(codepage, 0, src, -1, NULL, 0, NULL, NULL); + char* result = (char*)mir_alloc(cbLen+1); + if (result == NULL) + return NULL; + + WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, NULL, NULL); + result[ cbLen ] = 0; + return result; +} + +/******************************************************************************/ + +MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src) +{ + return mir_u2a_cp(src, LangPackGetDefaultCodePage()); +} diff --git a/plugins/Mir_core/mir_core.def b/plugins/Mir_core/mir_core.def new file mode 100644 index 0000000000..78e8323ff8 --- /dev/null +++ b/plugins/Mir_core/mir_core.def @@ -0,0 +1,5 @@ +LIBRARY mir_core + +EXPORTS + CallContactService @1 + CallProtoService @2 diff --git a/plugins/Mir_core/mir_core_10.vcxproj b/plugins/Mir_core/mir_core_10.vcxproj new file mode 100644 index 0000000000..e3da90ac2b --- /dev/null +++ b/plugins/Mir_core/mir_core_10.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + Mir_core + {D9EFEA4B-B817-4DE1-BD62-68A5DB8F5F60} + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + WIN32;_DEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) + Use + commonheaders.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + mir_core.def + true + false + Windows + miranda32.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) + $(SolutionDir)\lib + $(IntDir)$(TargetName).lib + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + 4996;%(DisableSpecificWarnings) + WIN64;_DEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) + Use + commonheaders.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + mir_core.def + true + false + $(IntDir)$(TargetName).lib + Windows + miranda64.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) + $(SolutionDir)\lib + + + + + Full + OnlyExplicitInline + Size + ..\..\include;%(AdditionalIncludeDirectories) + true + false + true + Level3 + 4996;%(DisableSpecificWarnings) + WIN32;NDEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) + Use + commonheaders.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + mir_core.def + true + true + true + false + Windows + miranda32.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) + $(SolutionDir)\lib + $(IntDir)$(TargetName).lib + + + + + Full + OnlyExplicitInline + Size + ..\..\include;%(AdditionalIncludeDirectories) + true + false + true + Level3 + 4996;%(DisableSpecificWarnings) + WIN64;NDEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) + Use + commonheaders.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + mir_core.def + true + true + true + false + $(IntDir)$(TargetName).lib + Windows + miranda64.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) + $(SolutionDir)\lib + + + + + + \ No newline at end of file diff --git a/plugins/Mir_core/mir_core_10.vcxproj.filters b/plugins/Mir_core/mir_core_10.vcxproj.filters new file mode 100644 index 0000000000..1a051134b1 --- /dev/null +++ b/plugins/Mir_core/mir_core_10.vcxproj.filters @@ -0,0 +1,67 @@ + + + + + {bf74d1c9-acd8-4fba-837d-734f024521c9} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a578a180-0eb9-4c3e-b4ae-0eaefa01d207} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/plugins/Mir_core/miranda.cpp b/plugins/Mir_core/miranda.cpp new file mode 100644 index 0000000000..7f48e05bb2 --- /dev/null +++ b/plugins/Mir_core/miranda.cpp @@ -0,0 +1,403 @@ +/* + +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" + +HWND hAPCWindow = NULL; + +int InitPathUtils(void); +void (*RecalculateTime)(void); + +HANDLE hStackMutex, hThreadQueueEmpty; +int hLangpack = 0; +HINSTANCE hInst = 0; + +///////////////////////////////////////////////////////////////////////////////////////// +// exception handling + +static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*) +{ + return EXCEPTION_EXECUTE_HANDLER; +} + +pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter; + +MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter() +{ + return pMirandaExceptFilter; +} + +MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter pMirandaExceptFilter) +{ + pfnExceptionFilter oldOne = pMirandaExceptFilter; + if (pMirandaExceptFilter != 0) + pMirandaExceptFilter = pMirandaExceptFilter; + return oldOne; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// thread support functions + +struct THREAD_WAIT_ENTRY +{ + DWORD dwThreadId; // valid if hThread isn't signalled + HANDLE hThread; + HINSTANCE hOwner; + void* pObject; + PVOID addr; +}; + +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())) + { + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + return; +} + +MIR_CORE_DLL(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; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// 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())) + { + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + return rc; +} + +MIR_CORE_DLL(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; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// 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 = MsgWaitForMultipleObjectsEx(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; + } +} + +static 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)); + TerminateThread(p->hThread, 9999); + CloseHandle(p->hThread); + mir_free(p); + } + + threads.destroy(); + + ReleaseMutex(hStackMutex); + SetEvent(hThreadQueueEmpty); + } +} + +MIR_CORE_DLL(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); + } + } +} + +MIR_CORE_DLL(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 + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(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); + + ReleaseMutex(hStackMutex); + } + return 0; +} + +MIR_CORE_DLL(INT_PTR) UnwindThreadPop(WPARAM, LPARAM) +{ + if ( WaitForSingleObject(hStackMutex, INFINITE) == WAIT_OBJECT_0) { + DWORD dwThreadId = GetCurrentThreadId(); + for (int 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; + } + } + ReleaseMutex(hStackMutex); + } + return 1; +} + +static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_NULL) SleepEx(0, TRUE); + if (msg == WM_TIMECHANGE && RecalculateTime) + RecalculateTime(); + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// module init + +static void 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); + SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); + hStackMutex = CreateMutex(NULL, FALSE, NULL); + + #ifdef WIN64 + HMODULE mirInst = GetModuleHandleA("miranda64.exe"); + #else + HMODULE mirInst = GetModuleHandleA("miranda32.exe"); + #endif + RecalculateTime = (void (*)()) GetProcAddress(mirInst, "RecalculateTime"); + + InitPathUtils(); + InitialiseModularEngine(); +} + +static void UnloadSystemModule(void) +{ + DestroyModularEngine(); + UnloadLangPackModule(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// entry point + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) { + hInst = hinstDLL; + LoadSystemModule(); + } + else if(fdwReason == DLL_PROCESS_DETACH) + UnloadSystemModule(); + return TRUE; +} diff --git a/plugins/Mir_core/miranda.h b/plugins/Mir_core/miranda.h new file mode 100644 index 0000000000..8a03e4111c --- /dev/null +++ b/plugins/Mir_core/miranda.h @@ -0,0 +1,128 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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. +*/ + +#define NEWSTR_ALLOCA(A) (A == NULL)?NULL:strcpy((char*)alloca(strlen(A)+1), A) +#define NEWTSTR_ALLOCA(A) (A == NULL)?NULL:_tcscpy((TCHAR*)alloca((_tcslen(A)+1)* sizeof(TCHAR)), A) + +struct LangPackMuuid +{ + MUUID muuid; + PLUGININFOEX* pInfo; +}; + +MIR_CORE_DLL(int) LangPackMarkPluginLoaded(PLUGININFOEX* pInfo); + +MIR_CORE_DLL(LangPackMuuid*) LangPackLookupUuid(WPARAM wParam); + +int LoadLangPackModule(void); +void UnloadLangPackModule(void); + +int InitialiseModularEngine(void); +void DestroyModularEngine(void); + +int InitPathUtils(void); + +extern HINSTANCE hInst; + +/**** modules.cpp **********************************************************************/ + +struct THookSubscriber +{ + HINSTANCE hOwner; + int type; + union { + struct { + union { + MIRANDAHOOK pfnHook; + MIRANDAHOOKPARAM pfnHookParam; + MIRANDAHOOKOBJ pfnHookObj; + MIRANDAHOOKOBJPARAM pfnHookObjParam; + }; + void* object; + LPARAM lParam; + }; + struct { + HWND hwnd; + UINT message; + }; + }; +}; + +struct THook +{ + char name[ MAXMODULELABELLENGTH ]; + int id; + int subscriberCount; + THookSubscriber* subscriber; + MIRANDAHOOK pfnHook; + CRITICAL_SECTION csHook; +}; + +/**** langpack.cpp *********************************************************************/ + +char* LangPackTranslateString(struct LangPackMuuid* pUuid, const char *szEnglish, const int W); +TCHAR* LangPackTranslateStringT(int hLangpack, const TCHAR* tszEnglish); + +/**** options.cpp **********************************************************************/ + +HTREEITEM FindNamedTreeItemAtRoot(HWND hwndTree, const TCHAR* name); + +/**** utils.cpp ************************************************************************/ + +void HotkeyToName(TCHAR *buf, int size, BYTE shift, BYTE key); +WORD GetHotkeyValue(INT_PTR idHotkey); + +HBITMAP ConvertIconToBitmap(HICON hIcon, HIMAGELIST hIml, int iconId); + +class StrConvUT +{ +private: + wchar_t* m_body; + +public: + StrConvUT(const char* pSrc) : + m_body(mir_a2u(pSrc)) {} + + ~StrConvUT() { mir_free(m_body); } + operator const wchar_t* () const { return m_body; } +}; + +class StrConvAT +{ +private: + char* m_body; + +public: + StrConvAT(const wchar_t* pSrc) : + m_body(mir_u2a(pSrc)) {} + + ~StrConvAT() { mir_free(m_body); } + operator const char* () const { return m_body; } + operator const wchar_t* () const { return (wchar_t*)m_body; } // type cast to fake the interface definition + operator const LPARAM () const { return (LPARAM)m_body; } +}; + +#define StrConvT(x) StrConvUT(x) +#define StrConvTu(x) x +#define StrConvA(x) StrConvAT(x) +#define StrConvU(x) x diff --git a/plugins/Mir_core/modules.cpp b/plugins/Mir_core/modules.cpp new file mode 100644 index 0000000000..6a9aa54bcb --- /dev/null +++ b/plugins/Mir_core/modules.cpp @@ -0,0 +1,644 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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" +#include + +// list of hooks + +static int compareHooks(const THook* p1, const THook* p2) +{ + return strcmp(p1->name, p2->name); +} + +static LIST 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 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; + +/////////////////////////////////////////////////////////////////////////////// +// HOOKS + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent) +{ + EnterCriticalSection(&csHooks); + if (pLastHook == (THook*)hEvent) + pLastHook = NULL; + + int idx; + if ((idx = hooks.getIndex((THook*)hEvent)) == -1) { + LeaveCriticalSection(&csHooks); + return 1; + } + + THook* 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; +} + +MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook) +{ + THook* p = (THook*)hEvent; + + EnterCriticalSection(&csHooks); + if (hooks.getIndex(p) != -1) + p->pfnHook = pfnHook; + LeaveCriticalSection(&csHooks); + return 0; +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(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); +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(HANDLE) HookEvent(const char* name, MIRANDAHOOK hookProc) +{ + return HookEventInt(1, name, hookProc, 0, 0); +} + +MIR_CORE_DLL(HANDLE) HookEventParam(const char* name, MIRANDAHOOKPARAM hookProc, LPARAM lParam) +{ + return HookEventInt(2, name, (MIRANDAHOOK)hookProc, 0, lParam); +} + +MIR_CORE_DLL(HANDLE) HookEventObj(const char* name, MIRANDAHOOKOBJ hookProc, void* object) +{ + return HookEventInt(3, name, (MIRANDAHOOK)hookProc, object, 0); +} + +MIR_CORE_DLL(HANDLE) HookEventObjParam(const char* name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam) +{ + return HookEventInt(4, name, (MIRANDAHOOK)hookProc, object, lParam); +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(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)); + UnhookEvent((HANDLE)((hooks[i]->id << 16) + j + 1)); + if (hooks[i]->subscriberCount == 0) + break; + } } } + + LeaveCriticalSection(&csHooks); +} + +MIR_CORE_DLL(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 = mir_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 = mir_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; +} + +MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc) +{ + return CreateServiceInt(0, name, serviceProc, 0, 0); +} + +MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam) +{ + return CreateServiceInt(1, name, (MIRANDASERVICE)serviceProc, 0, lParam); +} + +MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object) +{ + return CreateServiceInt(2, name, (MIRANDASERVICE)serviceProc, object, 0); +} + +MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam) +{ + return CreateServiceInt(3, name, (MIRANDASERVICE)serviceProc, object, lParam); +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(int) ServiceExists(const char *name) +{ + if (name == NULL) + return FALSE; + + EnterCriticalSection(&csServices); + int ret = FindServiceByName(name) != NULL; + LeaveCriticalSection(&csServices); + return ret; +} + +MIR_CORE_DLL(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 + OutputDebugStringA("Missing service called: \t"); + OutputDebugStringA(name); + OutputDebugStringA("\n"); + #endif + + 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); +} + +MIR_CORE_DLL(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); +} + +MIR_CORE_DLL(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; +} + +MIR_CORE_DLL(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)); + DestroyServiceFunction((HANDLE)services[i]->nameHash); + } } + + LeaveCriticalSection(&csServices); +} + +MIR_CORE_DLL(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); +} + +/////////////////////////////////////////////////////////////////////////////// + +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) +{ + EnterCriticalSection(&csHooks); + for (int i=0; i < hooks.getCount(); i++) { + THook* 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 (int j=0; j < services.getCount(); j++) + mir_free(services[j]); + + services.destroy(); + LeaveCriticalSection(&csServices); + DeleteCriticalSection(&csServices); + CloseHandle(hMainThread); +} diff --git a/plugins/Mir_core/path.cpp b/plugins/Mir_core/path.cpp new file mode 100644 index 0000000000..fada3dcd18 --- /dev/null +++ b/plugins/Mir_core/path.cpp @@ -0,0 +1,210 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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" + +static char szMirandaPath[MAX_PATH]; +static char szMirandaPathLower[MAX_PATH]; +static TCHAR szMirandaPathW[MAX_PATH]; +static TCHAR szMirandaPathWLower[MAX_PATH]; + +static int pathIsAbsolute(const char *path) +{ + if (strlen(path) <= 2) + return 0; + if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +} + +MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut) +{ + if ( !pSrc || !strlen(pSrc) || strlen(pSrc)>MAX_PATH) return 0; + if ( !pathIsAbsolute(pSrc)) { + mir_snprintf(pOut, MAX_PATH, "%s", pSrc); + return (int)strlen(pOut); + } + + char szTmp[MAX_PATH]; + mir_snprintf(szTmp, SIZEOF(szTmp), "%s", pSrc); + _strlwr(szTmp); + if (strstr(szTmp, szMirandaPathLower)) { + mir_snprintf(pOut, MAX_PATH, "%s", pSrc+strlen(szMirandaPathLower)); + return (int)strlen(pOut); + } + else { + mir_snprintf(pOut, MAX_PATH, "%s", pSrc); + return (int)strlen(pOut); + } +} + +MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, char* base) +{ + if ( !pSrc || !strlen(pSrc) || strlen(pSrc) > MAX_PATH) + return 0; + + if (base == NULL) + base = szMirandaPath; + + char buf[MAX_PATH]; + if (pSrc[0] < ' ') + return mir_snprintf(pOut, MAX_PATH, "%s", pSrc); + else if (pathIsAbsolute(pSrc)) + return GetFullPathNameA(pSrc, MAX_PATH, pOut, NULL); + else if (pSrc[0] != '\\') + mir_snprintf(buf, MAX_PATH, "%s%s", base, pSrc); + else + mir_snprintf(buf, MAX_PATH, "%s%s", base, pSrc+1); + + return GetFullPathNameA(buf, MAX_PATH, pOut, NULL); +} + +MIR_CORE_DLL(void) CreatePathToFile(char* szFilePath) +{ + char* pszLastBackslash = strrchr(szFilePath, '\\'); + if (pszLastBackslash == NULL) + return; + + *pszLastBackslash = '\0'; + CreateDirectoryTree(szFilePath); + *pszLastBackslash = '\\'; +} + +MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir) +{ + DWORD dwAttributes; + char *pszLastBackslash, szTestDir[ MAX_PATH ]; + + lstrcpynA(szTestDir, szDir, SIZEOF(szTestDir)); + if ((dwAttributes = GetFileAttributesA(szTestDir)) != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) + return 0; + + pszLastBackslash = strrchr(szTestDir, '\\'); + if (pszLastBackslash == NULL) + return 0; + + *pszLastBackslash = '\0'; + CreateDirectoryTree(szTestDir); + *pszLastBackslash = '\\'; + return (CreateDirectoryA(szTestDir, NULL) == 0) ? GetLastError() : 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +static int pathIsAbsoluteW(const TCHAR *path) +{ + if (lstrlen(path) <= 2) + return 0; + if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +} + +MIR_CORE_DLL(int) PathToRelativeW(const WCHAR *pSrc, WCHAR *pOut) +{ + if ( !pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) + return 0; + + if ( !pathIsAbsoluteW(pSrc)) + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + else { + TCHAR szTmp[MAX_PATH]; + + mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc); + _tcslwr(szTmp); + if (_tcsstr(szTmp, szMirandaPathWLower)) + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc+lstrlen(szMirandaPathWLower)); + else + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + } + return lstrlen(pOut); +} + +MIR_CORE_DLL(int) PathToAbsoluteW(const TCHAR *pSrc, TCHAR *pOut, TCHAR* base) +{ + if ( !pSrc || !wcslen(pSrc) || wcslen(pSrc) > MAX_PATH) + return 0; + + if (base == NULL) + base = szMirandaPathW; + + TCHAR buf[MAX_PATH]; + if (pSrc[0] < ' ') + return mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + else if (pathIsAbsoluteW(pSrc)) + return GetFullPathName(pSrc, MAX_PATH, pOut, NULL); + else if (pSrc[0] != '\\') + mir_sntprintf(buf, MAX_PATH, _T("%s%s"), base, pSrc); + else + mir_sntprintf(buf, MAX_PATH, _T("%s%s"), base, pSrc+1); + + return GetFullPathName(buf, MAX_PATH, pOut, NULL); +} + +MIR_CORE_DLL(void) CreatePathToFileW(WCHAR* wszFilePath) +{ + WCHAR* pszLastBackslash = wcsrchr(wszFilePath, '\\'); + if (pszLastBackslash == NULL) + return; + + *pszLastBackslash = '\0'; + CreateDirectoryTreeW(wszFilePath); + *pszLastBackslash = '\\'; +} + +MIR_CORE_DLL(int) CreateDirectoryTreeW(const WCHAR* szDir) +{ + DWORD dwAttributes; + WCHAR* pszLastBackslash, szTestDir[ MAX_PATH ]; + + lstrcpynW(szTestDir, szDir, SIZEOF(szTestDir)); + if ((dwAttributes = GetFileAttributesW(szTestDir)) != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) + return 0; + + pszLastBackslash = wcsrchr(szTestDir, '\\'); + if (pszLastBackslash == NULL) + return 0; + + *pszLastBackslash = '\0'; + CreateDirectoryTreeW(szTestDir); + *pszLastBackslash = '\\'; + return (CreateDirectoryW(szTestDir, NULL) == 0) ? GetLastError() : 0; +} + +int InitPathUtils(void) +{ + char *p = 0; + GetModuleFileNameA(hInst, szMirandaPath, SIZEOF(szMirandaPath)); + p = strrchr(szMirandaPath, '\\'); + if (p) + p[1] = 0; + mir_snprintf(szMirandaPathLower, MAX_PATH, "%s", szMirandaPath); + _strlwr(szMirandaPathLower); + + GetModuleFileName(hInst, szMirandaPathW, SIZEOF(szMirandaPathW)); + TCHAR *tp = _tcsrchr(szMirandaPathW, '\\'); + if (tp) + tp[1] = 0; + mir_sntprintf(szMirandaPathWLower, SIZEOF(szMirandaPathWLower), _T("%s"), szMirandaPathW); + _tcslwr(szMirandaPathWLower); + return 0; +} diff --git a/plugins/Mir_core/utf.cpp b/plugins/Mir_core/utf.cpp new file mode 100644 index 0000000000..5ec6042758 --- /dev/null +++ b/plugins/Mir_core/utf.cpp @@ -0,0 +1,406 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + + Copyright 2000 Alexandre Julliard of Wine project + (UTF-8 conversion routines) + +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" + +/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ +static const char utf8_length[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */ + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */ +}; + +/* first byte mask depending on UTF-8 sequence length */ +static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 }; + +/* minimum Unicode value depending on UTF-8 sequence length */ +static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 }; + +/* get the next char value taking surrogates into account */ +static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen) +{ + if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */ + if (src[0] > 0xdbff || /* invalid high surrogate */ + srclen <= 1 || /* missing low surrogate */ + src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */ + return 0; + return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff); + } + return src[0]; +} + +/* query necessary dst length for src string */ +static int Ucs2toUtf8Len(const wchar_t *src, unsigned int srclen) +{ + int len; + unsigned int val; + + for (len = 0; srclen; srclen--, src++) { + if (*src < 0x80) { /* 0x00-0x7f: 1 byte */ + len++; + continue; + } + if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */ + len += 2; + continue; + } + if ( !(val = getSurrogateValue(src, srclen))) + return -2; + + if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ + len += 3; + else { /* 0x10000-0x10ffff: 4 bytes */ + len += 4; + src++; + srclen--; + } + } + return len; +} + +MIR_CORE_DLL(int) Ucs2toUtf8Len(const wchar_t *src) +{ + if (src == 0) + return 0; + + return Ucs2toUtf8Len(src, (int)wcslen(src)); +} + +/* wide char to UTF-8 string conversion */ +/* return -1 on dst buffer overflow, -2 on invalid input char */ +int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen) +{ + int len; + + for (len = dstlen; srclen; srclen--, src++) + { + WCHAR ch = *src; + unsigned int val; + + if (ch < 0x80) /* 0x00-0x7f: 1 byte */ + { + if ( !len--) return -1; /* overflow */ + *dst++ = ch; + continue; + } + + if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */ + { + if ((len -= 2) < 0) return -1; /* overflow */ + dst[1] = 0x80 | (ch & 0x3f); + ch >>= 6; + dst[0] = 0xc0 | ch; + dst += 2; + continue; + } + + if ( !(val = getSurrogateValue(src, srclen))) + { + return -2; + } + + if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ + { + if ((len -= 3) < 0) return -1; /* overflow */ + dst[2] = 0x80 | (val & 0x3f); + val >>= 6; + dst[1] = 0x80 | (val & 0x3f); + val >>= 6; + dst[0] = 0xe0 | val; + dst += 3; + } + else /* 0x10000-0x10ffff: 4 bytes */ + { + if ((len -= 4) < 0) return -1; /* overflow */ + dst[3] = 0x80 | (val & 0x3f); + val >>= 6; + dst[2] = 0x80 | (val & 0x3f); + val >>= 6; + dst[1] = 0x80 | (val & 0x3f); + val >>= 6; + dst[0] = 0xf0 | val; + dst += 4; + src++; + srclen--; + } + } + return dstlen - len; +} + +/* helper for the various utf8 mbstowcs functions */ +static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend) +{ + unsigned int len = utf8_length[ch-0x80]; + unsigned int res = ch & utf8_mask[len]; + const char *end = *str + len; + + if (end > strend) return ~0; + switch(len) + { + case 3: + if ((ch = end[-3] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + case 2: + if ((ch = end[-2] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + case 1: + if ((ch = end[-1] ^ 0x80) >= 0x40) break; + res = (res << 6) | ch; + (*str)++; + if (res < utf8_minval[len]) break; + return res; + } + return ~0; +} + +/* query necessary dst length for src string */ +static inline int Utf8toUcs2Len(const char *src, int srclen) +{ + int ret = 0; + unsigned int res; + const char *srcend = src + srclen; + + while (src < srcend) + { + unsigned char ch = *src++; + if (ch < 0x80) /* special fast case for 7-bit ASCII */ + { + ret++; + continue; + } + if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) + { + if (res > 0xffff) ret++; + ret++; + } + else return -2; /* bad char */ + /* otherwise ignore it */ + } + return ret; +} + +/* UTF-8 to wide char string conversion */ +/* return -1 on dst buffer overflow, -2 on invalid input char */ +int Utf8toUcs2(const char *src, int srclen, wchar_t *dst, int dstlen) +{ + unsigned int res; + const char *srcend = src + srclen; + wchar_t *dstend = dst + dstlen; + + while ((dst < dstend) && (src < srcend)) + { + unsigned char ch = *src++; + if (ch < 0x80) /* special fast case for 7-bit ASCII */ + { + *dst++ = ch; + continue; + } + if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff) + { + *dst++ = res; + } + else if (res <= 0x10ffff) /* we need surrogates */ + { + if (dst == dstend - 1) return -1; /* overflow */ + res -= 0x10000; + *dst++ = 0xd800 | (res >> 10); + *dst++ = 0xdc00 | (res & 0x3ff); + } + else return -2; /* bad char */ + /* otherwise ignore it */ + } + if (src < srcend) return -1; /* overflow */ + return dstlen - (dstend - dst); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Decode - converts UTF8-encoded string to the UCS2/MBCS format + +MIR_CORE_DLL(char*) Utf8DecodeCP(char* str, int codepage, wchar_t** ucs2) +{ + int len; + bool needs_free = false; + wchar_t* tempBuf = NULL; + if (ucs2) + *ucs2 = NULL; + + if (str == NULL) + return NULL; + + len = (int)strlen(str); + + if (len < 2) { + if (ucs2 != NULL) { + *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); + MultiByteToWideChar(codepage, 0, str, len, tempBuf, len); + tempBuf[len] = 0; + } + return str; + } + + int destlen = Utf8toUcs2Len(str, len); + if (destlen < 0) + return NULL; + + if (ucs2 == NULL) { + __try + { + tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t)); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + tempBuf = NULL; + needs_free = true; + } + } + + if (tempBuf == NULL) { + tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); + if (tempBuf == NULL) + return NULL; + } + + Utf8toUcs2(str, len, tempBuf, destlen); + tempBuf[destlen] = 0; + WideCharToMultiByte(codepage, 0, tempBuf, -1, str, len + 1, "?", NULL); + + if (ucs2) + *ucs2 = tempBuf; + else if (needs_free) + mir_free(tempBuf); + + return str; +} + +MIR_CORE_DLL(char*) Utf8Decode(char* str, wchar_t** ucs2) +{ + return Utf8DecodeCP(str, LangPackGetDefaultCodePage(), ucs2); +} + +MIR_CORE_DLL(wchar_t*) Utf8DecodeW(const char* str) +{ + if (str == NULL) + return NULL; + + int len = (int)strlen(str); + + int destlen = Utf8toUcs2Len(str, len); + if (destlen < 0) return NULL; + + wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); + if (ucs2 == NULL) return NULL; + + if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) + { + ucs2[destlen] = 0; + return ucs2; + } + + mir_free(ucs2); + + return NULL; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Encode - converts MBCS string to the UTF8-encoded format + +MIR_CORE_DLL(char*) Utf8EncodeCP(const char* src, int codepage) +{ + int len; + bool needs_free = false; + char* result = NULL; + wchar_t* tempBuf; + + if (src == NULL) + return NULL; + + len = (int)strlen(src); + + __try + { + tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t)); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); + if (tempBuf == NULL) return NULL; + needs_free = true; + } + + len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1); + + int destlen = Ucs2toUtf8Len(tempBuf, len); + if (destlen >= 0) + { + result = (char*)mir_alloc(destlen + 1); + if (result) + { + Ucs2toUtf8(tempBuf, len, result, destlen); + result[destlen] = 0; + } + } + + if (needs_free) + mir_free(tempBuf); + + return result; +} + +MIR_CORE_DLL(char*) Utf8Encode(const char* src) +{ + return Utf8EncodeCP(src, LangPackGetDefaultCodePage()); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Encode - converts UCS2 string to the UTF8-encoded format + +MIR_CORE_DLL(char*) Utf8EncodeW(const wchar_t* src) +{ + if (src == NULL) + return NULL; + + int len = (int)wcslen(src); + + int destlen = Ucs2toUtf8Len(src, len); + if (destlen < 0) return NULL; + + char* result = (char*)mir_alloc(destlen + 1); + if (result == NULL) + return NULL; + + Ucs2toUtf8(src, len, result, destlen); + result[destlen] = 0; + + return result; +} diff --git a/plugins/Mir_core/utils.cpp b/plugins/Mir_core/utils.cpp new file mode 100644 index 0000000000..f0fcdcfa07 --- /dev/null +++ b/plugins/Mir_core/utils.cpp @@ -0,0 +1,150 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 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" + +MIR_CORE_DLL(char*) rtrim(char* str) +{ + if (str == NULL) + return NULL; + + char* p = strchr(str, 0); + while (--p >= str) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + *p = 0; break; + default: + return str; + } + } + return str; +} + +MIR_CORE_DLL(WCHAR*) wrtrim(WCHAR *str) +{ + if (str == NULL) + return NULL; + + WCHAR* p = _tcschr(str, 0); + while (--p >= str) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + *p = 0; break; + default: + return str; + } + } + return str; +} + +MIR_CORE_DLL(char*) ltrim(char* str) +{ + if (str == NULL) + return NULL; + + char* p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + memmove(str, p, strlen(p) + 1); + return str; + } + } +} + +MIR_CORE_DLL(char*) ltrimp(char* str) +{ + if (str == NULL) + return NULL; + + char* p = str; + for (;;) { + switch (*p) { + case ' ': case '\t': case '\n': case '\r': + ++p; break; + default: + return p; + } + } +} + +MIR_CORE_DLL(int) wildcmp(char * name, char * mask) +{ + char * last='\0'; + for (;; mask++, name++) { + if (*mask != '?' && *mask != *name) break; + if (*name == '\0') return ((BOOL)!*mask); + } + if (*mask != '*') return FALSE; + for (;; mask++, name++){ + while (*mask == '*') { + last = mask++; + if (*mask == '\0') return ((BOOL)!*mask); /* true */ + } + if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ + if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static int sttComparePlugins(const HINSTANCE__* p1, const HINSTANCE__* p2) +{ + if (p1 == p2) + return 0; + + return (p1 < p2) ? -1 : 1; +} + +static LIST pluginListAddr(10, sttComparePlugins); + +MIR_CORE_DLL(void) RegisterModule(HINSTANCE hInst) +{ + pluginListAddr.insert(hInst); +} + +MIR_CORE_DLL(void) UnregisterModule(HINSTANCE hInst) +{ + pluginListAddr.remove(hInst); +} + +MIR_CORE_DLL(HINSTANCE) GetInstByAddress(void* codePtr) +{ + if (pluginListAddr.getCount() == 0) + return NULL; + + int idx; + List_GetIndex((SortedList*)&pluginListAddr, &codePtr, &idx); + if (idx > 0) + idx--; + + HINSTANCE result = pluginListAddr[idx]; + if (result < hInst && codePtr > hInst) + result = hInst; + else if (idx == 0 && codePtr < (void*)result) + result = NULL; + + return result; +} diff --git a/plugins/mir_core/commonheaders.cpp b/plugins/mir_core/commonheaders.cpp deleted file mode 100644 index 95b2201163..0000000000 --- a/plugins/mir_core/commonheaders.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "commonheaders.h" - diff --git a/plugins/mir_core/commonheaders.h b/plugins/mir_core/commonheaders.h deleted file mode 100644 index 2d04e12f4b..0000000000 --- a/plugins/mir_core/commonheaders.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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. -*/ - -#define MIRANDA_VER 0x0A00 - -#define WINVER 0x0700 -#define _WIN32_WINNT 0x0700 -#define _WIN32_IE 0x0601 - -#define INCL_WINSOCK_API_TYPEDEFS 1 - -#include "m_stdhdr.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "miranda.h" - -#include -#include diff --git a/plugins/mir_core/langpack.cpp b/plugins/mir_core/langpack.cpp deleted file mode 100644 index d38dd6807d..0000000000 --- a/plugins/mir_core/langpack.cpp +++ /dev/null @@ -1,630 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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 LANGPACK_BUF_SIZE 4000 - -static int CompareMuuids(const LangPackMuuid* p1, const LangPackMuuid* p2) -{ - return memcmp(&p1->muuid, &p2->muuid, sizeof(MUUID)); -} - -static LIST lMuuids(10, CompareMuuids); -static LangPackMuuid* pCurrentMuuid = NULL; - -static BOOL bModuleInitialized = FALSE; - -struct LangPackEntry { - DWORD englishHash; - char *local; - wchar_t *wlocal; - LangPackMuuid* pMuuid; - LangPackEntry* pNext; // for langpack items with the same hash value -}; - -struct LangPackStruct { - TCHAR filename[MAX_PATH]; - TCHAR filePath[MAX_PATH]; - char language[64]; - char lastModifiedUsing[64]; - char authors[256]; - char authorEmail[128]; - LangPackEntry *entry; - int entryCount, entriesAlloced; - LCID localeID; - UINT defaultANSICp; -} static langPack; - -static int IsEmpty(char *str) -{ - int i = 0; - - while (str[i]) - { - if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n') - return 0; - i++; - } - return 1; -} - -static void ConvertBackslashes(char *str, UINT fileCp) -{ - char *pstr; - for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) { - if (*pstr == '\\') { - switch(pstr[1]) { - case 'n': *pstr = '\n'; break; - case 't': *pstr = '\t'; break; - case 'r': *pstr = '\r'; break; - default: *pstr = pstr[1]; break; - } - memmove(pstr+1, pstr+2, strlen(pstr+2) + 1); -} } } - -#ifdef _DEBUG -//#pragma optimize("gt", on) -#endif - -// MurmurHash2 -MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len) -{ - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. - const unsigned int m = 0x5bd1e995; - const int r = 24; - - // Initialize the hash to a 'random' value - unsigned int h = len; - - // Mix 4 bytes at a time into the hash - const unsigned char * data = (const unsigned char *)key; - - while (len >= 4) - { - unsigned int k = *(unsigned int *)data; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - data += 4; - len -= 4; - } - - // Handle the last few bytes of the input array - switch(len) - { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; - h *= m; - }; - - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2) -{ - if (arg1->englishHash < arg2->englishHash) return -1; - if (arg1->englishHash > arg2->englishHash) return 1; - - return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1; -} - -static void swapBytes(void* p, size_t iSize) -{ - char *head = (char *)p; // here - char *tail = head + iSize - 1; - - for (; tail > head; --tail, ++head) { - char temp = *head; - *head = *tail; - *tail = temp; - } -} - -static bool EnterMuuid(const char* p, MUUID& result) -{ - if (*p++ != '{') - return false; - - BYTE* d = (BYTE*)&result; - - for (int nBytes = 0; *p && nBytes < 24; p++) { - if (*p == '-') - continue; - - if (*p == '}') - break; - - if ( !isxdigit(*p)) - return false; - - if ( !isxdigit(p[1])) - return false; - - int c = 0; - if (sscanf(p, "%2x", &c) != 1) - return false; - - *d++ = (BYTE)c; - nBytes++; - p++; - } - - if (*p != '}') - return false; - - swapBytes(&result.a, sizeof(result.a)); - swapBytes(&result.b, sizeof(result.b)); - swapBytes(&result.c, sizeof(result.c)); - return true; -} - -static void LoadLangPackFile(FILE* fp, char* line, UINT fileCp) -{ - while ( !feof(fp)) { - if (fgets(line, LANGPACK_BUF_SIZE, fp) == NULL) - break; - - if (IsEmpty(line) || line[0] == ';' || line[0] == 0) - continue; - - rtrim(line); - - if (line[0] == '#') { - strlwr(line); - - if ( !memcmp(line+1, "include", 7)) { - TCHAR tszFileName[ MAX_PATH ]; - TCHAR* fileName = mir_a2t(ltrim(line+9)); - mir_sntprintf(tszFileName, SIZEOF(tszFileName), _T("%s%s"), langPack.filePath, fileName); - mir_free(fileName); - - FILE* p = _tfopen(tszFileName, _T("r")); - if (p) { - line[0] = 0; - fgets(line, SIZEOF(line), p); - - UINT fileCp = CP_ACP; - if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') - { - fileCp = CP_UTF8; - fseek(p, 3, SEEK_SET); - } - else - { - fileCp = langPack.defaultANSICp; - fseek(p, 0, SEEK_SET); - } - - LoadLangPackFile(p, line, fileCp); - fclose(p); - } - } - else if ( !memcmp(line+1, "muuid", 5)) { - MUUID t; - if ( !EnterMuuid(line+7, t)) - continue; - - LangPackMuuid* pNew = (LangPackMuuid*)mir_alloc(sizeof(LangPackMuuid)); - memcpy(&pNew->muuid, &t, sizeof(t)); - pNew->pInfo = NULL; - lMuuids.insert(pNew); - pCurrentMuuid = pNew; - } - - continue; - } - - ConvertBackslashes(line, fileCp); - - if (line[0] == '[' && line[ lstrlenA(line)-1 ] == ']') { - if (langPack.entryCount && langPack.entry[ langPack.entryCount-1].local == NULL) - langPack.entryCount--; - - char* pszLine = line+1; - line[ lstrlenA(line)-1 ] = '\0'; - if (++langPack.entryCount > langPack.entriesAlloced) { - langPack.entriesAlloced += 128; - langPack.entry = (LangPackEntry*)mir_realloc(langPack.entry, sizeof(LangPackEntry)*langPack.entriesAlloced); - } - - LangPackEntry* E = &langPack.entry[ langPack.entryCount-1 ]; - E->englishHash = mir_hashstr(pszLine); - E->local = NULL; - E->wlocal = NULL; - E->pMuuid = pCurrentMuuid; - E->pNext = NULL; - continue; - } - - if ( !langPack.entryCount) - continue; - - LangPackEntry* E = &langPack.entry[ langPack.entryCount-1 ]; - if (E->local == NULL) { - E->local = mir_strdup(line); - if (fileCp == CP_UTF8) - Utf8DecodeCP(E->local, langPack.defaultANSICp, NULL); - - int iNeeded = MultiByteToWideChar(fileCp, 0, line, -1, 0, 0); - E->wlocal = (wchar_t *)mir_alloc((iNeeded+1) * sizeof(wchar_t)); - MultiByteToWideChar(fileCp, 0, line, -1, E->wlocal, iNeeded); - } - else { - size_t iOldLenA = strlen(E->local); - E->local = (char*)mir_realloc(E->local, iOldLenA + strlen(line) + 2); - strcat(E->local, "\n"); - strcat(E->local, line); - - if (fileCp == CP_UTF8) - Utf8DecodeCP(E->local + iOldLenA + 1, langPack.defaultANSICp, NULL); - - int iNeeded = MultiByteToWideChar(fileCp, 0, line, -1, 0, 0); - size_t iOldLen = wcslen(E->wlocal); - E->wlocal = (wchar_t*)mir_realloc(E->wlocal, (sizeof(wchar_t) * (iOldLen + iNeeded + 2))); - wcscat(E->wlocal, L"\n"); - MultiByteToWideChar(fileCp, 0, line, -1, E->wlocal + iOldLen + 1, iNeeded); - } - } -} - -MIR_CORE_DLL(int) LoadLangPack(const TCHAR *szLangPack) -{ - int startOfLine=0; - USHORT langID; - - lstrcpy(langPack.filename, szLangPack); - lstrcpy(langPack.filePath, szLangPack); - TCHAR* p = _tcsrchr(langPack.filePath, '\\'); - if (p) - p[1] = 0; - - FILE *fp = _tfopen(szLangPack, _T("rt")); - if (fp == NULL) - return 1; - - char line[ LANGPACK_BUF_SIZE ] = ""; - fgets(line, SIZEOF(line), fp); - - UINT fileCp = CP_ACP; - size_t lineLen = strlen(line); - if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf') - { - fileCp = CP_UTF8; - memmove(line, line + 3, lineLen - 2); - } - - lrtrim(line); - if (lstrcmpA(line, "Miranda Language Pack Version 1")) { - fclose(fp); - return 2; - } - - //headers - while ( !feof(fp)) { - startOfLine = ftell(fp); - if (fgets(line, SIZEOF(line), fp) == NULL) - break; - - lrtrim(line); - if (IsEmpty(line) || line[0] == ';' || line[0] == 0) - continue; - - if (line[0] == '[' || line[0] == '#') - break; - - char* pszColon = strchr(line, ':'); - if (pszColon == NULL) { - fclose(fp); - return 3; - } - - *pszColon++ = 0; - if ( !lstrcmpA(line, "Language")) {mir_snprintf(langPack.language, sizeof(langPack.language), "%s", pszColon); lrtrim(langPack.language);} - else if ( !lstrcmpA(line, "Last-Modified-Using")) {mir_snprintf(langPack.lastModifiedUsing, sizeof(langPack.lastModifiedUsing), "%s", pszColon); lrtrim(langPack.lastModifiedUsing);} - else if ( !lstrcmpA(line, "Authors")) {mir_snprintf(langPack.authors, sizeof(langPack.authors), "%s", pszColon); lrtrim(langPack.authors);} - else if ( !lstrcmpA(line, "Author-email")) {mir_snprintf(langPack.authorEmail, sizeof(langPack.authorEmail), "%s", pszColon); lrtrim(langPack.authorEmail);} - else if ( !lstrcmpA(line, "Locale")) { - char szBuf[20], *stopped; - - lrtrim(pszColon + 1); - langID = (USHORT)strtol(pszColon, &stopped, 16); - langPack.localeID = MAKELCID(langID, 0); - GetLocaleInfoA(langPack.localeID, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10); - szBuf[5] = 0; // codepages have max. 5 digits - langPack.defaultANSICp = atoi(szBuf); - if (fileCp == CP_ACP) - fileCp = langPack.defaultANSICp; - } - } - - //body - fseek(fp, startOfLine, SEEK_SET); - langPack.entriesAlloced = 0; - - LoadLangPackFile(fp, line, fileCp); - fclose(fp); - pCurrentMuuid = NULL; - - qsort(langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2) -{ - if (arg1->englishHash < arg2->englishHash) return -1; - if (arg1->englishHash > arg2->englishHash) return 1; - return 0; -} - -static char *LangPackTranslateString(LangPackMuuid* pUuid, const char *szEnglish, const int W) -{ - if (langPack.entryCount == 0 || szEnglish == NULL) - return (char*)szEnglish; - - LangPackEntry key, *entry; - key.englishHash = W ? mir_hashstrW((WCHAR*)szEnglish) : mir_hashstr(szEnglish); - entry = (LangPackEntry*)bsearch(&key, langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2); - if (entry == NULL) - return (char*)szEnglish; - - // try to find the exact match, otherwise the first entry will be returned - if (pUuid) { - for (LangPackEntry* p = entry->pNext; p != NULL; p = p->pNext) { - if (p->pMuuid == pUuid) { - entry = p; - break; - } } } - - return W ? (char *)entry->wlocal : entry->local; -} - -MIR_CORE_DLL(int) LangPackGetDefaultCodePage() -{ - return langPack.defaultANSICp; -} - -MIR_CORE_DLL(int) LangPackGetDefaultLocale() -{ - return (langPack.localeID == 0) ? LOCALE_USER_DEFAULT : langPack.localeID; -} - -MIR_CORE_DLL(TCHAR*) LangPackPcharToTchar(const char* pszStr) -{ - if (pszStr == NULL) - return NULL; - - { int len = (int)strlen(pszStr); - TCHAR* result = (TCHAR*)alloca((len+1)*sizeof(TCHAR)); - MultiByteToWideChar(LangPackGetDefaultCodePage(), 0, pszStr, -1, result, len); - result[len] = 0; - return mir_wstrdup(TranslateW(result)); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(char*) TranslateA_LP(const char* str, int hLangpack) -{ - return (char*)LangPackTranslateString(LangPackLookupUuid(hLangpack), str, FALSE); -} - -MIR_CORE_DLL(WCHAR*) TranslateW_LP(const WCHAR* str, int hLangpack) -{ - return (WCHAR*)LangPackTranslateString(LangPackLookupUuid(hLangpack), (LPCSTR)str, TRUE); -} - -MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, int hLangpack) -{ - LangPackMuuid* uuid = LangPackLookupUuid(hLangpack); - - MENUITEMINFO mii; - mii.cbSize = MENUITEMINFO_V4_SIZE; - for (int i = GetMenuItemCount(hMenu)-1; i >= 0; i--) { - TCHAR str[256]; - mii.fMask = MIIM_TYPE|MIIM_SUBMENU; - mii.dwTypeData = (TCHAR*)str; - mii.cch = SIZEOF(str); - GetMenuItemInfo(hMenu, i, TRUE, &mii); - - if (mii.cch && mii.dwTypeData) { - TCHAR* result = (TCHAR*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE); - if (result != mii.dwTypeData) { - mii.dwTypeData = result; - mii.fMask = MIIM_TYPE; - SetMenuItemInfo(hMenu, i, TRUE, &mii); - } } - - if (mii.hSubMenu != NULL) TranslateMenu_LP(mii.hSubMenu, hLangpack); - } -} - -static void TranslateWindow(LangPackMuuid* pUuid, HWND hwnd) -{ - TCHAR title[2048]; - GetWindowText(hwnd, title, SIZEOF(title)); - - TCHAR* result = (TCHAR*)LangPackTranslateString(pUuid, (const char*)title, TRUE); - if (result != title) - SetWindowText(hwnd, result); -} - -struct LANGPACKTRANSLATEDIALOG -{ - HWND hwndDlg; - int hLangpack; -}; - -static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam) -{ - int hLangpack = (int)lParam; - TCHAR szClass[32]; - int id = GetDlgCtrlID(hwnd); - - LangPackMuuid* uuid = LangPackLookupUuid(hLangpack); - - GetClassName(hwnd, szClass, SIZEOF(szClass)); - if ( !lstrcmpi(szClass, _T("static")) || !lstrcmpi(szClass, _T("hyperlink")) || !lstrcmpi(szClass, _T("button")) || !lstrcmpi(szClass, _T("MButtonClass")) || !lstrcmpi(szClass, _T("MHeaderbarCtrl"))) - TranslateWindow(uuid, hwnd); - else if ( !lstrcmpi(szClass, _T("edit"))) { - if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) - TranslateWindow(uuid, hwnd); - } - return TRUE; -} - -MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, int hLangpack) -{ - TranslateWindow(LangPackLookupUuid(hLangpack), hDlg); - EnumChildWindows(hDlg, TranslateDialogEnumProc, hLangpack); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(LangPackMuuid*) LangPackLookupUuid(WPARAM wParam) -{ - int idx = (wParam >> 16) & 0xFFFF; - return (idx > 0 && idx <= lMuuids.getCount()) ? lMuuids[ idx-1 ] : NULL; -} - -MIR_CORE_DLL(int) LangPackMarkPluginLoaded(PLUGININFOEX* pInfo) -{ - LangPackMuuid tmp; tmp.muuid = pInfo->uuid; - int idx = lMuuids.getIndex(&tmp); - if (idx == -1) - return 0; - - lMuuids[ idx ]->pInfo = pInfo; - return (idx+1) << 16; -} - -MIR_CORE_DLL(void) LangPackDropUnusedItems(void) -{ - if (langPack.entryCount == 0) - return; - - LangPackEntry *s = langPack.entry+1, *d = s, *pLast = langPack.entry; - DWORD dwSavedHash = langPack.entry->englishHash; - bool bSortNeeded = false; - - for (int i=1; i < langPack.entryCount; i++, s++) { - if (s->pMuuid != NULL && s->pMuuid->pInfo == NULL) - s->pMuuid = NULL; - - if (s->englishHash != dwSavedHash) { - pLast = d; - if (s != d) - *d++ = *s; - else - d++; - dwSavedHash = s->englishHash; - } - else { - bSortNeeded = true; - LangPackEntry* p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry)); - *p = *s; - pLast->pNext = p; pLast = p; - } - } - - if (bSortNeeded) { - langPack.entryCount = (int)(d - langPack.entry); - qsort(langPack.entry, langPack.entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int LoadLangPackModule(void) -{ - bModuleInitialized = TRUE; - - ZeroMemory(&langPack, sizeof(langPack)); - - TCHAR szSearch[MAX_PATH]; - PathToAbsoluteT(_T("langpack_*.txt"), szSearch, NULL); - - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(szSearch, &fd); - if (hFind != INVALID_HANDLE_VALUE) { - PathToAbsoluteT(fd.cFileName, szSearch, NULL); - FindClose(hFind); - LoadLangPack(szSearch); - } - return 0; -} - -void UnloadLangPackModule() -{ - if ( !bModuleInitialized) return; - - int i; - for (i=0; i < lMuuids.getCount(); i++) - mir_free(lMuuids[i]); - lMuuids.destroy(); - - LangPackEntry* p = langPack.entry; - for (i=0; i < langPack.entryCount; i++, p++) { - if (p->pNext != NULL) { - for (LangPackEntry* p1 = p->pNext; p1 != NULL;) { - LangPackEntry* p2 = p1; p1 = p1->pNext; - mir_free(p2->local); - mir_free(p2->wlocal); - mir_free(p2); - } } - - mir_free(p->local); - mir_free(p->wlocal); - } - - if (langPack.entryCount) { - mir_free(langPack.entry); - langPack.entry=0; - langPack.entryCount=0; -} } - -///////////////////////////////////////////////////////////////////////////////////////// - -MIR_CORE_DLL(void) ReloadLangpack(TCHAR *pszStr) -{ - if (pszStr == NULL) - pszStr = langPack.filename; - - UnloadLangPackModule(); - LoadLangPack(pszStr); - LangPackDropUnusedItems(); -} diff --git a/plugins/mir_core/lists.cpp b/plugins/mir_core/lists.cpp deleted file mode 100644 index e4996fc156..0000000000 --- a/plugins/mir_core/lists.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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" - -/* a simple sorted list implementation */ - -MIR_CORE_DLL(SortedList*) List_Create(int p_limit, int p_increment) -{ - SortedList* result = (SortedList*)mir_calloc(sizeof(SortedList)); - if (result == NULL) - return(NULL); - - result->increment = p_increment; - result->limit = p_limit; - return(result); -} - -MIR_CORE_DLL(void) List_Destroy(SortedList* p_list) -{ - if (p_list == NULL) - return; - - if (p_list->items != NULL) { - mir_free(p_list->items); - p_list->items = NULL; - } - - p_list->realCount = p_list->limit = 0; -} - -MIR_CORE_DLL(void*) List_Find(SortedList* p_list, void* p_value) -{ - int index; - - if ( !List_GetIndex(p_list, p_value, &index)) - return(NULL); - - return(p_list->items[ index ]); -} - -#ifdef _DEBUG -#pragma optimize("gt", on) -#endif - -MIR_CORE_DLL(int) List_GetIndex(SortedList* p_list, void* p_value, int* p_index) -{ - if (p_value == NULL) - { - *p_index = -1; - return 0; - } - - switch ((INT_PTR)p_list->sortFunc) - { - case 0: - break; - - case HandleKeySort: -#ifdef _WIN64 - { - const unsigned __int64 val = *(unsigned __int64 *)p_value; - int low = 0; - int high = p_list->realCount - 1; - - while (low <= high) - { - int i = (low + high) / 2; - unsigned __int64 vali = *(unsigned __int64 *)p_list->items[i]; - if (vali == val) - { - *p_index = i; - return 1; - } - - if (vali < val) - low = i + 1; - else - high = i - 1; - } - - *p_index = low; - } - break; -#endif - - case NumericKeySort: - { - const unsigned val = *(unsigned *)p_value; - int low = 0; - int high = p_list->realCount - 1; - - while (low <= high) - { - int i = (low + high) / 2; - unsigned vali = *(unsigned *)p_list->items[i]; - if (vali == val) - { - *p_index = i; - return 1; - } - - if (vali < val) - low = i + 1; - else - high = i - 1; - } - - *p_index = low; - } - break; - - case PtrKeySort: - { - int low = 0; - int high = p_list->realCount - 1; - - while (low <= high) - { - int i = (low + high) / 2; - const void* vali = p_list->items[i]; - if (vali == p_value) - { - *p_index = i; - return 1; - } - - if (vali < p_value) - low = i + 1; - else - high = i - 1; - } - - *p_index = low; - } - break; - - default: - { - int low = 0; - int high = p_list->realCount - 1; - - while (low <= high) - { - int i = (low + high) / 2; - int result = p_list->sortFunc(p_list->items[i], p_value); - if (result == 0) - { - *p_index = i; - return 1; - } - - if (result < 0) - low = i + 1; - else - high = i - 1; - } - - *p_index = low; - } - break; - } - - return 0; -} - -MIR_CORE_DLL(int) List_IndexOf(SortedList* p_list, void* p_value) -{ - if (p_value == NULL) - return -1; - - int i; - for (i=0; i < p_list->realCount; i++) - if (p_list->items[i] == p_value) - return i; - - return -1; -} - -#ifdef _DEBUG -#pragma optimize("", on) -#endif - -MIR_CORE_DLL(int) List_Insert(SortedList* p_list, void* p_value, int p_index) -{ - if (p_value == NULL || p_index > p_list->realCount) - return 0; - - if (p_list->realCount == p_list->limit) - { - p_list->items = (void**)mir_realloc(p_list->items, sizeof(void*)*(p_list->realCount + p_list->increment)); - p_list->limit += p_list->increment; - } - - if (p_index < p_list->realCount) - memmove(p_list->items+p_index+1, p_list->items+p_index, sizeof(void*)*(p_list->realCount-p_index)); - - p_list->realCount++; - - p_list->items[ p_index ] = p_value; - return 1; -} - -MIR_CORE_DLL(int) List_InsertPtr(SortedList* list, void* p) -{ - if (p == NULL) - return -1; - - int idx = list->realCount; - List_GetIndex(list, p, &idx); - return List_Insert(list, p, idx); -} - -MIR_CORE_DLL(int) List_Remove(SortedList* p_list, int index) -{ - if (index < 0 || index > p_list->realCount) - return(0); - - p_list->realCount--; - if (p_list->realCount > index) - { - memmove(p_list->items+index, p_list->items+index+1, sizeof(void*)*(p_list->realCount-index)); - p_list->items[ p_list->realCount ] = NULL; - } - - return 1; -} - -MIR_CORE_DLL(int) List_RemovePtr(SortedList* list, void* p) -{ - int idx = -1; - if (List_GetIndex(list, p, &idx)) - List_Remove(list, idx); - - return idx; -} - -MIR_CORE_DLL(void) List_Copy(SortedList* s, SortedList* d, size_t itemSize) -{ - d->increment = s->increment; - d->limit = s->limit; - d->realCount = s->realCount; - d->items = (void**)mir_alloc( sizeof(void*) * d->realCount); - memcpy(d->items, s->items, sizeof(void*) * d->realCount); -} - -MIR_CORE_DLL(void) List_ObjCopy(SortedList* s, SortedList* d, size_t itemSize) -{ - int i; - - d->increment = s->increment; - d->sortFunc = s->sortFunc; - - for (i = 0; i < s->realCount; i++) { - void* item = new char[ itemSize ]; - memcpy(item, s->items[i], itemSize); - List_Insert(d, item, i); -} } diff --git a/plugins/mir_core/memory.cpp b/plugins/mir_core/memory.cpp deleted file mode 100644 index 25b4d880c2..0000000000 --- a/plugins/mir_core/memory.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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 BLOCK_ALLOCED 0xABBABABA -#define BLOCK_FREED 0xDEADBEEF - -static int CheckBlock(void* blk) -{ - int result = FALSE; - char* p = (char*)blk - sizeof(DWORD)*2; - DWORD size, *b, *e; - - __try - { - size = *(DWORD*)p; - b = (DWORD*)&p[ sizeof(DWORD) ]; - e = (DWORD*)&p[ sizeof(DWORD)*2 + size ]; - - if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED) - { - if (*b == BLOCK_FREED && *e == BLOCK_FREED) - OutputDebugStringA("memory block is already deleted\n"); - else - OutputDebugStringA("memory block is corrupted\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - } - else result = TRUE; - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - OutputDebugStringA("access violation during checking memory block\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - } - - return result; -} - -/******************************************************************************/ - -MIR_CORE_DLL(void*) mir_alloc(size_t size) -{ - if (size == 0) - return NULL; - { - char* p = (char*)malloc(size + sizeof(DWORD)*3); - if (p == NULL) { - OutputDebugStringA("memory overflow\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - return NULL; - } - - *(DWORD*)p = (DWORD)size; - *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_ALLOCED; - *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_ALLOCED; - return p + sizeof(DWORD)*2; -} } - -/******************************************************************************/ - -MIR_CORE_DLL(void*) mir_calloc(size_t size) -{ - void* p = mir_alloc(size); - if (p != NULL) - memset(p, 0, size); - return p; -} - -/******************************************************************************/ - -MIR_CORE_DLL(void*) mir_realloc(void* ptr, size_t size) -{ - char* p; - - if (ptr != NULL) { - if ( !CheckBlock(ptr)) - return NULL; - p = (char*)ptr - sizeof(DWORD)*2; - } - else p = NULL; - - p = (char*)realloc(p, size + sizeof(DWORD)*3); - if (p == NULL) { - OutputDebugStringA("memory overflow\n"); - #if defined(_DEBUG) - DebugBreak(); - #endif - return NULL; - } - - *(DWORD*)p = (DWORD)size; - *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_ALLOCED; - *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_ALLOCED; - return p + sizeof(DWORD)*2; -} - -/******************************************************************************/ - -MIR_CORE_DLL(void) mir_free(void* ptr) -{ - char* p; - DWORD size; - - if (ptr == NULL) - return; - if ( !CheckBlock(ptr)) - return; - - p = (char*)ptr - sizeof(DWORD)*2; - size = *(DWORD*)p; - *(DWORD*)&p[ sizeof(DWORD) ] = BLOCK_FREED; - *(DWORD*)&p[ size + sizeof(DWORD)*2 ] = BLOCK_FREED; - free(p); -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_strdup(const char* str) -{ - if (str != NULL) { - char* p = (char*)mir_alloc(strlen(str)+1); - if (p) - strcpy(p, str); - return p; - } - return NULL; -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_strndup(const char* str, size_t len) -{ - if (str != NULL && len != 0) { - char* p = (char*)mir_alloc(len + 1); - if ( !p) { - memcpy(p, str, len); - p[ len ] = 0; - } - return p; - } - return NULL; -} - -/******************************************************************************/ - -MIR_CORE_DLL(WCHAR*) mir_wstrdup(const WCHAR* str) -{ - if (str != NULL) { - WCHAR* p = (WCHAR*)mir_alloc(sizeof(WCHAR)*(wcslen(str)+1)); - if (p) - wcscpy(p, str); - return p; - } - return NULL; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...) -{ - va_list va; - int len; - - va_start(va, fmt); - len = _vsnprintf(buffer, count-1, fmt, va); - va_end(va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_sntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, ...) -{ - va_list va; - int len; - - va_start(va, fmt); - len = _vsntprintf(buffer, count-1, fmt, va); - va_end(va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va) -{ - int len; - - len = _vsnprintf(buffer, count-1, fmt, va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(int) mir_vsntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, va_list va) -{ - int len; - - len = _vsntprintf(buffer, count-1, fmt, va); - buffer[count-1] = 0; - return len; -} - -/******************************************************************************/ - -MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage) -{ - if (src == NULL) - return NULL; - - int cbLen = MultiByteToWideChar(codepage, 0, src, -1, NULL, 0); - wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1)); - if (result == NULL) - return NULL; - - MultiByteToWideChar(codepage, 0, src, -1, result, cbLen); - result[ cbLen ] = 0; - return result; -} - -/******************************************************************************/ - -MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src) -{ - return mir_a2u_cp(src, LangPackGetDefaultCodePage()); -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage) -{ - if (src == NULL) - return NULL; - - int cbLen = WideCharToMultiByte(codepage, 0, src, -1, NULL, 0, NULL, NULL); - char* result = (char*)mir_alloc(cbLen+1); - if (result == NULL) - return NULL; - - WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, NULL, NULL); - result[ cbLen ] = 0; - return result; -} - -/******************************************************************************/ - -MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src) -{ - return mir_u2a_cp(src, LangPackGetDefaultCodePage()); -} diff --git a/plugins/mir_core/mir_core.def b/plugins/mir_core/mir_core.def deleted file mode 100644 index 78e8323ff8..0000000000 --- a/plugins/mir_core/mir_core.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY mir_core - -EXPORTS - CallContactService @1 - CallProtoService @2 diff --git a/plugins/mir_core/mir_core_10.vcxproj b/plugins/mir_core/mir_core_10.vcxproj deleted file mode 100644 index 3516d84166..0000000000 --- a/plugins/mir_core/mir_core_10.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - mir_core - {D9EFEA4B-B817-4DE1-BD62-68A5DB8F5F60} - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - Unicode - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ - $(SolutionDir)$(Configuration)64\ - $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ - - - - Disabled - ..\..\include;%(AdditionalIncludeDirectories) - EnableFastChecks - MultiThreadedDebugDLL - true - Level3 - EditAndContinue - 4996;%(DisableSpecificWarnings) - WIN32;_DEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) - Use - commonheaders.h - - - _DEBUG;%(PreprocessorDefinitions) - ..\..\include\msapi - - - mir_core.def - true - false - Windows - miranda32.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) - $(SolutionDir)\lib - $(IntDir)$(TargetName).lib - - - - - Disabled - ..\..\include;%(AdditionalIncludeDirectories) - EnableFastChecks - MultiThreadedDebugDLL - true - Level3 - 4996;%(DisableSpecificWarnings) - WIN64;_DEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) - Use - commonheaders.h - - - _DEBUG;%(PreprocessorDefinitions) - ..\..\include\msapi - - - mir_core.def - true - false - $(IntDir)$(TargetName).lib - Windows - miranda64.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) - $(SolutionDir)\lib - - - - - Full - OnlyExplicitInline - Size - ..\..\include;%(AdditionalIncludeDirectories) - true - false - true - Level3 - 4996;%(DisableSpecificWarnings) - WIN32;NDEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) - Use - commonheaders.h - - - NDEBUG;%(PreprocessorDefinitions) - ..\..\include\msapi - - - mir_core.def - true - true - true - false - Windows - miranda32.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) - $(SolutionDir)\lib - $(IntDir)$(TargetName).lib - - - - - Full - OnlyExplicitInline - Size - ..\..\include;%(AdditionalIncludeDirectories) - true - false - true - Level3 - 4996;%(DisableSpecificWarnings) - WIN64;NDEBUG;_WINDOWS;MIR_CORE_EXPORTS;_USRDLL;%(PreprocessorDefinitions) - Use - commonheaders.h - - - NDEBUG;%(PreprocessorDefinitions) - ..\..\include\msapi - - - mir_core.def - true - true - true - false - $(IntDir)$(TargetName).lib - Windows - miranda64.lib;ws2_32.lib;comctl32.lib;winmm.lib;version.lib;%(AdditionalDependencies) - $(SolutionDir)\lib - - - - - - \ No newline at end of file diff --git a/plugins/mir_core/mir_core_10.vcxproj.filters b/plugins/mir_core/mir_core_10.vcxproj.filters deleted file mode 100644 index 1a051134b1..0000000000 --- a/plugins/mir_core/mir_core_10.vcxproj.filters +++ /dev/null @@ -1,67 +0,0 @@ - - - - - {bf74d1c9-acd8-4fba-837d-734f024521c9} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {a578a180-0eb9-4c3e-b4ae-0eaefa01d207} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/plugins/mir_core/miranda.cpp b/plugins/mir_core/miranda.cpp deleted file mode 100644 index 7f48e05bb2..0000000000 --- a/plugins/mir_core/miranda.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - -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" - -HWND hAPCWindow = NULL; - -int InitPathUtils(void); -void (*RecalculateTime)(void); - -HANDLE hStackMutex, hThreadQueueEmpty; -int hLangpack = 0; -HINSTANCE hInst = 0; - -///////////////////////////////////////////////////////////////////////////////////////// -// exception handling - -static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*) -{ - return EXCEPTION_EXECUTE_HANDLER; -} - -pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter; - -MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter() -{ - return pMirandaExceptFilter; -} - -MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter pMirandaExceptFilter) -{ - pfnExceptionFilter oldOne = pMirandaExceptFilter; - if (pMirandaExceptFilter != 0) - pMirandaExceptFilter = pMirandaExceptFilter; - return oldOne; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// thread support functions - -struct THREAD_WAIT_ENTRY -{ - DWORD dwThreadId; // valid if hThread isn't signalled - HANDLE hThread; - HINSTANCE hOwner; - void* pObject; - PVOID addr; -}; - -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())) - { - } - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - CallService(MS_SYSTEM_THREAD_POP, 0, 0); - return; -} - -MIR_CORE_DLL(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; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// 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())) - { - } - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - CallService(MS_SYSTEM_THREAD_POP, 0, 0); - return rc; -} - -MIR_CORE_DLL(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; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// 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 = MsgWaitForMultipleObjectsEx(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; - } -} - -static 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)); - TerminateThread(p->hThread, 9999); - CloseHandle(p->hThread); - mir_free(p); - } - - threads.destroy(); - - ReleaseMutex(hStackMutex); - SetEvent(hThreadQueueEmpty); - } -} - -MIR_CORE_DLL(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); - } - } -} - -MIR_CORE_DLL(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 - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(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); - - ReleaseMutex(hStackMutex); - } - return 0; -} - -MIR_CORE_DLL(INT_PTR) UnwindThreadPop(WPARAM, LPARAM) -{ - if ( WaitForSingleObject(hStackMutex, INFINITE) == WAIT_OBJECT_0) { - DWORD dwThreadId = GetCurrentThreadId(); - for (int 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; - } - } - ReleaseMutex(hStackMutex); - } - return 1; -} - -static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_NULL) SleepEx(0, TRUE); - if (msg == WM_TIMECHANGE && RecalculateTime) - RecalculateTime(); - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// module init - -static void 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); - SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); - hStackMutex = CreateMutex(NULL, FALSE, NULL); - - #ifdef WIN64 - HMODULE mirInst = GetModuleHandleA("miranda64.exe"); - #else - HMODULE mirInst = GetModuleHandleA("miranda32.exe"); - #endif - RecalculateTime = (void (*)()) GetProcAddress(mirInst, "RecalculateTime"); - - InitPathUtils(); - InitialiseModularEngine(); -} - -static void UnloadSystemModule(void) -{ - DestroyModularEngine(); - UnloadLangPackModule(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// entry point - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - if (fdwReason == DLL_PROCESS_ATTACH) { - hInst = hinstDLL; - LoadSystemModule(); - } - else if(fdwReason == DLL_PROCESS_DETACH) - UnloadSystemModule(); - return TRUE; -} diff --git a/plugins/mir_core/miranda.h b/plugins/mir_core/miranda.h deleted file mode 100644 index 8a03e4111c..0000000000 --- a/plugins/mir_core/miranda.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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. -*/ - -#define NEWSTR_ALLOCA(A) (A == NULL)?NULL:strcpy((char*)alloca(strlen(A)+1), A) -#define NEWTSTR_ALLOCA(A) (A == NULL)?NULL:_tcscpy((TCHAR*)alloca((_tcslen(A)+1)* sizeof(TCHAR)), A) - -struct LangPackMuuid -{ - MUUID muuid; - PLUGININFOEX* pInfo; -}; - -MIR_CORE_DLL(int) LangPackMarkPluginLoaded(PLUGININFOEX* pInfo); - -MIR_CORE_DLL(LangPackMuuid*) LangPackLookupUuid(WPARAM wParam); - -int LoadLangPackModule(void); -void UnloadLangPackModule(void); - -int InitialiseModularEngine(void); -void DestroyModularEngine(void); - -int InitPathUtils(void); - -extern HINSTANCE hInst; - -/**** modules.cpp **********************************************************************/ - -struct THookSubscriber -{ - HINSTANCE hOwner; - int type; - union { - struct { - union { - MIRANDAHOOK pfnHook; - MIRANDAHOOKPARAM pfnHookParam; - MIRANDAHOOKOBJ pfnHookObj; - MIRANDAHOOKOBJPARAM pfnHookObjParam; - }; - void* object; - LPARAM lParam; - }; - struct { - HWND hwnd; - UINT message; - }; - }; -}; - -struct THook -{ - char name[ MAXMODULELABELLENGTH ]; - int id; - int subscriberCount; - THookSubscriber* subscriber; - MIRANDAHOOK pfnHook; - CRITICAL_SECTION csHook; -}; - -/**** langpack.cpp *********************************************************************/ - -char* LangPackTranslateString(struct LangPackMuuid* pUuid, const char *szEnglish, const int W); -TCHAR* LangPackTranslateStringT(int hLangpack, const TCHAR* tszEnglish); - -/**** options.cpp **********************************************************************/ - -HTREEITEM FindNamedTreeItemAtRoot(HWND hwndTree, const TCHAR* name); - -/**** utils.cpp ************************************************************************/ - -void HotkeyToName(TCHAR *buf, int size, BYTE shift, BYTE key); -WORD GetHotkeyValue(INT_PTR idHotkey); - -HBITMAP ConvertIconToBitmap(HICON hIcon, HIMAGELIST hIml, int iconId); - -class StrConvUT -{ -private: - wchar_t* m_body; - -public: - StrConvUT(const char* pSrc) : - m_body(mir_a2u(pSrc)) {} - - ~StrConvUT() { mir_free(m_body); } - operator const wchar_t* () const { return m_body; } -}; - -class StrConvAT -{ -private: - char* m_body; - -public: - StrConvAT(const wchar_t* pSrc) : - m_body(mir_u2a(pSrc)) {} - - ~StrConvAT() { mir_free(m_body); } - operator const char* () const { return m_body; } - operator const wchar_t* () const { return (wchar_t*)m_body; } // type cast to fake the interface definition - operator const LPARAM () const { return (LPARAM)m_body; } -}; - -#define StrConvT(x) StrConvUT(x) -#define StrConvTu(x) x -#define StrConvA(x) StrConvAT(x) -#define StrConvU(x) x diff --git a/plugins/mir_core/modules.cpp b/plugins/mir_core/modules.cpp deleted file mode 100644 index 6a9aa54bcb..0000000000 --- a/plugins/mir_core/modules.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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" -#include - -// list of hooks - -static int compareHooks(const THook* p1, const THook* p2) -{ - return strcmp(p1->name, p2->name); -} - -static LIST 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 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; - -/////////////////////////////////////////////////////////////////////////////// -// HOOKS - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent) -{ - EnterCriticalSection(&csHooks); - if (pLastHook == (THook*)hEvent) - pLastHook = NULL; - - int idx; - if ((idx = hooks.getIndex((THook*)hEvent)) == -1) { - LeaveCriticalSection(&csHooks); - return 1; - } - - THook* 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; -} - -MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook) -{ - THook* p = (THook*)hEvent; - - EnterCriticalSection(&csHooks); - if (hooks.getIndex(p) != -1) - p->pfnHook = pfnHook; - LeaveCriticalSection(&csHooks); - return 0; -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(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); -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(HANDLE) HookEvent(const char* name, MIRANDAHOOK hookProc) -{ - return HookEventInt(1, name, hookProc, 0, 0); -} - -MIR_CORE_DLL(HANDLE) HookEventParam(const char* name, MIRANDAHOOKPARAM hookProc, LPARAM lParam) -{ - return HookEventInt(2, name, (MIRANDAHOOK)hookProc, 0, lParam); -} - -MIR_CORE_DLL(HANDLE) HookEventObj(const char* name, MIRANDAHOOKOBJ hookProc, void* object) -{ - return HookEventInt(3, name, (MIRANDAHOOK)hookProc, object, 0); -} - -MIR_CORE_DLL(HANDLE) HookEventObjParam(const char* name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam) -{ - return HookEventInt(4, name, (MIRANDAHOOK)hookProc, object, lParam); -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(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)); - UnhookEvent((HANDLE)((hooks[i]->id << 16) + j + 1)); - if (hooks[i]->subscriberCount == 0) - break; - } } } - - LeaveCriticalSection(&csHooks); -} - -MIR_CORE_DLL(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 = mir_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 = mir_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; -} - -MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc) -{ - return CreateServiceInt(0, name, serviceProc, 0, 0); -} - -MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam) -{ - return CreateServiceInt(1, name, (MIRANDASERVICE)serviceProc, 0, lParam); -} - -MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object) -{ - return CreateServiceInt(2, name, (MIRANDASERVICE)serviceProc, object, 0); -} - -MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam) -{ - return CreateServiceInt(3, name, (MIRANDASERVICE)serviceProc, object, lParam); -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(int) ServiceExists(const char *name) -{ - if (name == NULL) - return FALSE; - - EnterCriticalSection(&csServices); - int ret = FindServiceByName(name) != NULL; - LeaveCriticalSection(&csServices); - return ret; -} - -MIR_CORE_DLL(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 - OutputDebugStringA("Missing service called: \t"); - OutputDebugStringA(name); - OutputDebugStringA("\n"); - #endif - - 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); -} - -MIR_CORE_DLL(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); -} - -MIR_CORE_DLL(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; -} - -MIR_CORE_DLL(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)); - DestroyServiceFunction((HANDLE)services[i]->nameHash); - } } - - LeaveCriticalSection(&csServices); -} - -MIR_CORE_DLL(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); -} - -/////////////////////////////////////////////////////////////////////////////// - -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) -{ - EnterCriticalSection(&csHooks); - for (int i=0; i < hooks.getCount(); i++) { - THook* 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 (int j=0; j < services.getCount(); j++) - mir_free(services[j]); - - services.destroy(); - LeaveCriticalSection(&csServices); - DeleteCriticalSection(&csServices); - CloseHandle(hMainThread); -} diff --git a/plugins/mir_core/path.cpp b/plugins/mir_core/path.cpp deleted file mode 100644 index fada3dcd18..0000000000 --- a/plugins/mir_core/path.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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" - -static char szMirandaPath[MAX_PATH]; -static char szMirandaPathLower[MAX_PATH]; -static TCHAR szMirandaPathW[MAX_PATH]; -static TCHAR szMirandaPathWLower[MAX_PATH]; - -static int pathIsAbsolute(const char *path) -{ - if (strlen(path) <= 2) - return 0; - if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) - return 1; - return 0; -} - -MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut) -{ - if ( !pSrc || !strlen(pSrc) || strlen(pSrc)>MAX_PATH) return 0; - if ( !pathIsAbsolute(pSrc)) { - mir_snprintf(pOut, MAX_PATH, "%s", pSrc); - return (int)strlen(pOut); - } - - char szTmp[MAX_PATH]; - mir_snprintf(szTmp, SIZEOF(szTmp), "%s", pSrc); - _strlwr(szTmp); - if (strstr(szTmp, szMirandaPathLower)) { - mir_snprintf(pOut, MAX_PATH, "%s", pSrc+strlen(szMirandaPathLower)); - return (int)strlen(pOut); - } - else { - mir_snprintf(pOut, MAX_PATH, "%s", pSrc); - return (int)strlen(pOut); - } -} - -MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, char* base) -{ - if ( !pSrc || !strlen(pSrc) || strlen(pSrc) > MAX_PATH) - return 0; - - if (base == NULL) - base = szMirandaPath; - - char buf[MAX_PATH]; - if (pSrc[0] < ' ') - return mir_snprintf(pOut, MAX_PATH, "%s", pSrc); - else if (pathIsAbsolute(pSrc)) - return GetFullPathNameA(pSrc, MAX_PATH, pOut, NULL); - else if (pSrc[0] != '\\') - mir_snprintf(buf, MAX_PATH, "%s%s", base, pSrc); - else - mir_snprintf(buf, MAX_PATH, "%s%s", base, pSrc+1); - - return GetFullPathNameA(buf, MAX_PATH, pOut, NULL); -} - -MIR_CORE_DLL(void) CreatePathToFile(char* szFilePath) -{ - char* pszLastBackslash = strrchr(szFilePath, '\\'); - if (pszLastBackslash == NULL) - return; - - *pszLastBackslash = '\0'; - CreateDirectoryTree(szFilePath); - *pszLastBackslash = '\\'; -} - -MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir) -{ - DWORD dwAttributes; - char *pszLastBackslash, szTestDir[ MAX_PATH ]; - - lstrcpynA(szTestDir, szDir, SIZEOF(szTestDir)); - if ((dwAttributes = GetFileAttributesA(szTestDir)) != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) - return 0; - - pszLastBackslash = strrchr(szTestDir, '\\'); - if (pszLastBackslash == NULL) - return 0; - - *pszLastBackslash = '\0'; - CreateDirectoryTree(szTestDir); - *pszLastBackslash = '\\'; - return (CreateDirectoryA(szTestDir, NULL) == 0) ? GetLastError() : 0; -} - -/////////////////////////////////////////////////////////////////////////////// - -static int pathIsAbsoluteW(const TCHAR *path) -{ - if (lstrlen(path) <= 2) - return 0; - if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) - return 1; - return 0; -} - -MIR_CORE_DLL(int) PathToRelativeW(const WCHAR *pSrc, WCHAR *pOut) -{ - if ( !pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) - return 0; - - if ( !pathIsAbsoluteW(pSrc)) - mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); - else { - TCHAR szTmp[MAX_PATH]; - - mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc); - _tcslwr(szTmp); - if (_tcsstr(szTmp, szMirandaPathWLower)) - mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc+lstrlen(szMirandaPathWLower)); - else - mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); - } - return lstrlen(pOut); -} - -MIR_CORE_DLL(int) PathToAbsoluteW(const TCHAR *pSrc, TCHAR *pOut, TCHAR* base) -{ - if ( !pSrc || !wcslen(pSrc) || wcslen(pSrc) > MAX_PATH) - return 0; - - if (base == NULL) - base = szMirandaPathW; - - TCHAR buf[MAX_PATH]; - if (pSrc[0] < ' ') - return mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); - else if (pathIsAbsoluteW(pSrc)) - return GetFullPathName(pSrc, MAX_PATH, pOut, NULL); - else if (pSrc[0] != '\\') - mir_sntprintf(buf, MAX_PATH, _T("%s%s"), base, pSrc); - else - mir_sntprintf(buf, MAX_PATH, _T("%s%s"), base, pSrc+1); - - return GetFullPathName(buf, MAX_PATH, pOut, NULL); -} - -MIR_CORE_DLL(void) CreatePathToFileW(WCHAR* wszFilePath) -{ - WCHAR* pszLastBackslash = wcsrchr(wszFilePath, '\\'); - if (pszLastBackslash == NULL) - return; - - *pszLastBackslash = '\0'; - CreateDirectoryTreeW(wszFilePath); - *pszLastBackslash = '\\'; -} - -MIR_CORE_DLL(int) CreateDirectoryTreeW(const WCHAR* szDir) -{ - DWORD dwAttributes; - WCHAR* pszLastBackslash, szTestDir[ MAX_PATH ]; - - lstrcpynW(szTestDir, szDir, SIZEOF(szTestDir)); - if ((dwAttributes = GetFileAttributesW(szTestDir)) != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) - return 0; - - pszLastBackslash = wcsrchr(szTestDir, '\\'); - if (pszLastBackslash == NULL) - return 0; - - *pszLastBackslash = '\0'; - CreateDirectoryTreeW(szTestDir); - *pszLastBackslash = '\\'; - return (CreateDirectoryW(szTestDir, NULL) == 0) ? GetLastError() : 0; -} - -int InitPathUtils(void) -{ - char *p = 0; - GetModuleFileNameA(hInst, szMirandaPath, SIZEOF(szMirandaPath)); - p = strrchr(szMirandaPath, '\\'); - if (p) - p[1] = 0; - mir_snprintf(szMirandaPathLower, MAX_PATH, "%s", szMirandaPath); - _strlwr(szMirandaPathLower); - - GetModuleFileName(hInst, szMirandaPathW, SIZEOF(szMirandaPathW)); - TCHAR *tp = _tcsrchr(szMirandaPathW, '\\'); - if (tp) - tp[1] = 0; - mir_sntprintf(szMirandaPathWLower, SIZEOF(szMirandaPathWLower), _T("%s"), szMirandaPathW); - _tcslwr(szMirandaPathWLower); - return 0; -} diff --git a/plugins/mir_core/utf.cpp b/plugins/mir_core/utf.cpp deleted file mode 100644 index 5ec6042758..0000000000 --- a/plugins/mir_core/utf.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - - Copyright 2000 Alexandre Julliard of Wine project - (UTF-8 conversion routines) - -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" - -/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ -static const char utf8_length[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */ - 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */ -}; - -/* first byte mask depending on UTF-8 sequence length */ -static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 }; - -/* minimum Unicode value depending on UTF-8 sequence length */ -static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 }; - -/* get the next char value taking surrogates into account */ -static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen) -{ - if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */ - if (src[0] > 0xdbff || /* invalid high surrogate */ - srclen <= 1 || /* missing low surrogate */ - src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */ - return 0; - return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff); - } - return src[0]; -} - -/* query necessary dst length for src string */ -static int Ucs2toUtf8Len(const wchar_t *src, unsigned int srclen) -{ - int len; - unsigned int val; - - for (len = 0; srclen; srclen--, src++) { - if (*src < 0x80) { /* 0x00-0x7f: 1 byte */ - len++; - continue; - } - if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */ - len += 2; - continue; - } - if ( !(val = getSurrogateValue(src, srclen))) - return -2; - - if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ - len += 3; - else { /* 0x10000-0x10ffff: 4 bytes */ - len += 4; - src++; - srclen--; - } - } - return len; -} - -MIR_CORE_DLL(int) Ucs2toUtf8Len(const wchar_t *src) -{ - if (src == 0) - return 0; - - return Ucs2toUtf8Len(src, (int)wcslen(src)); -} - -/* wide char to UTF-8 string conversion */ -/* return -1 on dst buffer overflow, -2 on invalid input char */ -int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen) -{ - int len; - - for (len = dstlen; srclen; srclen--, src++) - { - WCHAR ch = *src; - unsigned int val; - - if (ch < 0x80) /* 0x00-0x7f: 1 byte */ - { - if ( !len--) return -1; /* overflow */ - *dst++ = ch; - continue; - } - - if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */ - { - if ((len -= 2) < 0) return -1; /* overflow */ - dst[1] = 0x80 | (ch & 0x3f); - ch >>= 6; - dst[0] = 0xc0 | ch; - dst += 2; - continue; - } - - if ( !(val = getSurrogateValue(src, srclen))) - { - return -2; - } - - if (val < 0x10000) /* 0x800-0xffff: 3 bytes */ - { - if ((len -= 3) < 0) return -1; /* overflow */ - dst[2] = 0x80 | (val & 0x3f); - val >>= 6; - dst[1] = 0x80 | (val & 0x3f); - val >>= 6; - dst[0] = 0xe0 | val; - dst += 3; - } - else /* 0x10000-0x10ffff: 4 bytes */ - { - if ((len -= 4) < 0) return -1; /* overflow */ - dst[3] = 0x80 | (val & 0x3f); - val >>= 6; - dst[2] = 0x80 | (val & 0x3f); - val >>= 6; - dst[1] = 0x80 | (val & 0x3f); - val >>= 6; - dst[0] = 0xf0 | val; - dst += 4; - src++; - srclen--; - } - } - return dstlen - len; -} - -/* helper for the various utf8 mbstowcs functions */ -static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend) -{ - unsigned int len = utf8_length[ch-0x80]; - unsigned int res = ch & utf8_mask[len]; - const char *end = *str + len; - - if (end > strend) return ~0; - switch(len) - { - case 3: - if ((ch = end[-3] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - case 2: - if ((ch = end[-2] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - case 1: - if ((ch = end[-1] ^ 0x80) >= 0x40) break; - res = (res << 6) | ch; - (*str)++; - if (res < utf8_minval[len]) break; - return res; - } - return ~0; -} - -/* query necessary dst length for src string */ -static inline int Utf8toUcs2Len(const char *src, int srclen) -{ - int ret = 0; - unsigned int res; - const char *srcend = src + srclen; - - while (src < srcend) - { - unsigned char ch = *src++; - if (ch < 0x80) /* special fast case for 7-bit ASCII */ - { - ret++; - continue; - } - if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) - { - if (res > 0xffff) ret++; - ret++; - } - else return -2; /* bad char */ - /* otherwise ignore it */ - } - return ret; -} - -/* UTF-8 to wide char string conversion */ -/* return -1 on dst buffer overflow, -2 on invalid input char */ -int Utf8toUcs2(const char *src, int srclen, wchar_t *dst, int dstlen) -{ - unsigned int res; - const char *srcend = src + srclen; - wchar_t *dstend = dst + dstlen; - - while ((dst < dstend) && (src < srcend)) - { - unsigned char ch = *src++; - if (ch < 0x80) /* special fast case for 7-bit ASCII */ - { - *dst++ = ch; - continue; - } - if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff) - { - *dst++ = res; - } - else if (res <= 0x10ffff) /* we need surrogates */ - { - if (dst == dstend - 1) return -1; /* overflow */ - res -= 0x10000; - *dst++ = 0xd800 | (res >> 10); - *dst++ = 0xdc00 | (res & 0x3ff); - } - else return -2; /* bad char */ - /* otherwise ignore it */ - } - if (src < srcend) return -1; /* overflow */ - return dstlen - (dstend - dst); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Utf8Decode - converts UTF8-encoded string to the UCS2/MBCS format - -MIR_CORE_DLL(char*) Utf8DecodeCP(char* str, int codepage, wchar_t** ucs2) -{ - int len; - bool needs_free = false; - wchar_t* tempBuf = NULL; - if (ucs2) - *ucs2 = NULL; - - if (str == NULL) - return NULL; - - len = (int)strlen(str); - - if (len < 2) { - if (ucs2 != NULL) { - *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); - MultiByteToWideChar(codepage, 0, str, len, tempBuf, len); - tempBuf[len] = 0; - } - return str; - } - - int destlen = Utf8toUcs2Len(str, len); - if (destlen < 0) - return NULL; - - if (ucs2 == NULL) { - __try - { - tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t)); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - tempBuf = NULL; - needs_free = true; - } - } - - if (tempBuf == NULL) { - tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); - if (tempBuf == NULL) - return NULL; - } - - Utf8toUcs2(str, len, tempBuf, destlen); - tempBuf[destlen] = 0; - WideCharToMultiByte(codepage, 0, tempBuf, -1, str, len + 1, "?", NULL); - - if (ucs2) - *ucs2 = tempBuf; - else if (needs_free) - mir_free(tempBuf); - - return str; -} - -MIR_CORE_DLL(char*) Utf8Decode(char* str, wchar_t** ucs2) -{ - return Utf8DecodeCP(str, LangPackGetDefaultCodePage(), ucs2); -} - -MIR_CORE_DLL(wchar_t*) Utf8DecodeW(const char* str) -{ - if (str == NULL) - return NULL; - - int len = (int)strlen(str); - - int destlen = Utf8toUcs2Len(str, len); - if (destlen < 0) return NULL; - - wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t)); - if (ucs2 == NULL) return NULL; - - if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) - { - ucs2[destlen] = 0; - return ucs2; - } - - mir_free(ucs2); - - return NULL; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Utf8Encode - converts MBCS string to the UTF8-encoded format - -MIR_CORE_DLL(char*) Utf8EncodeCP(const char* src, int codepage) -{ - int len; - bool needs_free = false; - char* result = NULL; - wchar_t* tempBuf; - - if (src == NULL) - return NULL; - - len = (int)strlen(src); - - __try - { - tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t)); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t)); - if (tempBuf == NULL) return NULL; - needs_free = true; - } - - len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1); - - int destlen = Ucs2toUtf8Len(tempBuf, len); - if (destlen >= 0) - { - result = (char*)mir_alloc(destlen + 1); - if (result) - { - Ucs2toUtf8(tempBuf, len, result, destlen); - result[destlen] = 0; - } - } - - if (needs_free) - mir_free(tempBuf); - - return result; -} - -MIR_CORE_DLL(char*) Utf8Encode(const char* src) -{ - return Utf8EncodeCP(src, LangPackGetDefaultCodePage()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Utf8Encode - converts UCS2 string to the UTF8-encoded format - -MIR_CORE_DLL(char*) Utf8EncodeW(const wchar_t* src) -{ - if (src == NULL) - return NULL; - - int len = (int)wcslen(src); - - int destlen = Ucs2toUtf8Len(src, len); - if (destlen < 0) return NULL; - - char* result = (char*)mir_alloc(destlen + 1); - if (result == NULL) - return NULL; - - Ucs2toUtf8(src, len, result, destlen); - result[destlen] = 0; - - return result; -} diff --git a/plugins/mir_core/utils.cpp b/plugins/mir_core/utils.cpp deleted file mode 100644 index f0fcdcfa07..0000000000 --- a/plugins/mir_core/utils.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2009 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" - -MIR_CORE_DLL(char*) rtrim(char* str) -{ - if (str == NULL) - return NULL; - - char* p = strchr(str, 0); - while (--p >= str) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - *p = 0; break; - default: - return str; - } - } - return str; -} - -MIR_CORE_DLL(WCHAR*) wrtrim(WCHAR *str) -{ - if (str == NULL) - return NULL; - - WCHAR* p = _tcschr(str, 0); - while (--p >= str) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - *p = 0; break; - default: - return str; - } - } - return str; -} - -MIR_CORE_DLL(char*) ltrim(char* str) -{ - if (str == NULL) - return NULL; - - char* p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - memmove(str, p, strlen(p) + 1); - return str; - } - } -} - -MIR_CORE_DLL(char*) ltrimp(char* str) -{ - if (str == NULL) - return NULL; - - char* p = str; - for (;;) { - switch (*p) { - case ' ': case '\t': case '\n': case '\r': - ++p; break; - default: - return p; - } - } -} - -MIR_CORE_DLL(int) wildcmp(char * name, char * mask) -{ - char * last='\0'; - for (;; mask++, name++) { - if (*mask != '?' && *mask != *name) break; - if (*name == '\0') return ((BOOL)!*mask); - } - if (*mask != '*') return FALSE; - for (;; mask++, name++){ - while (*mask == '*') { - last = mask++; - if (*mask == '\0') return ((BOOL)!*mask); /* true */ - } - if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */ - if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static int sttComparePlugins(const HINSTANCE__* p1, const HINSTANCE__* p2) -{ - if (p1 == p2) - return 0; - - return (p1 < p2) ? -1 : 1; -} - -static LIST pluginListAddr(10, sttComparePlugins); - -MIR_CORE_DLL(void) RegisterModule(HINSTANCE hInst) -{ - pluginListAddr.insert(hInst); -} - -MIR_CORE_DLL(void) UnregisterModule(HINSTANCE hInst) -{ - pluginListAddr.remove(hInst); -} - -MIR_CORE_DLL(HINSTANCE) GetInstByAddress(void* codePtr) -{ - if (pluginListAddr.getCount() == 0) - return NULL; - - int idx; - List_GetIndex((SortedList*)&pluginListAddr, &codePtr, &idx); - if (idx > 0) - idx--; - - HINSTANCE result = pluginListAddr[idx]; - if (result < hInst && codePtr > hInst) - result = hInst; - else if (idx == 0 && codePtr < (void*)result) - result = NULL; - - return result; -} -- cgit v1.2.3