From 00d71971d9cf831b991d391bb073dd846a15855f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 13 Jun 2018 14:14:35 +0300 Subject: profile lock detection unbound from contact list services --- src/mir_app/src/MDatabaseCommon.cpp | 34 +++++++++++++++++++++++++++++++++ src/mir_app/src/database.cpp | 38 ++++++++++++------------------------- src/mir_app/src/db_util.cpp | 16 ++++++++++++++++ src/mir_app/src/mir_app.def | 3 +++ src/mir_app/src/mir_app64.def | 3 +++ src/mir_app/src/profilemanager.cpp | 2 +- src/mir_app/src/profilemanager.h | 2 +- 7 files changed, 70 insertions(+), 28 deletions(-) (limited to 'src/mir_app') diff --git a/src/mir_app/src/MDatabaseCommon.cpp b/src/mir_app/src/MDatabaseCommon.cpp index 74f33688dc..db053e03fd 100644 --- a/src/mir_app/src/MDatabaseCommon.cpp +++ b/src/mir_app/src/MDatabaseCommon.cpp @@ -38,6 +38,7 @@ MDatabaseCommon::MDatabaseCommon() : MDatabaseCommon::~MDatabaseCommon() { + UnlockName(); delete (MDatabaseCache*)m_cache; } @@ -60,6 +61,39 @@ int MDatabaseCommon::CheckProto(DBCachedContact *cc, const char *proto) return !mir_strcmp(cc->szProto, proto); } +bool MDatabaseCommon::LockName(const wchar_t *pwszProfileName) +{ + if (m_hLock != nullptr) + return true; + + if (pwszProfileName == nullptr) + return false; + + CMStringW wszPhysName(pwszProfileName); + wszPhysName.Replace(L"\\", L"_"); + wszPhysName.Insert(0, L"Global\\"); + + HANDLE hMutex = ::CreateMutexW(nullptr, false, wszPhysName); + if (hMutex == nullptr) + return false; + + if (GetLastError() == ERROR_ALREADY_EXISTS) { + ::CloseHandle(hMutex); + return false; + } + + m_hLock = hMutex; + return true; +} + +void MDatabaseCommon::UnlockName() +{ + if (m_hLock) { + CloseHandle(m_hLock); + m_hLock = nullptr; + } +} + ///////////////////////////////////////////////////////////////////////////////////////// // Modules diff --git a/src/mir_app/src/database.cpp b/src/mir_app/src/database.cpp index e7f5483e59..29f5bdd512 100644 --- a/src/mir_app/src/database.cpp +++ b/src/mir_app/src/database.cpp @@ -431,38 +431,21 @@ static int tryCreateDatabase(const wchar_t *ptszProfile) return -1; // no suitable driver found } -typedef struct -{ - wchar_t *profile; - UINT msg; - ATOM aPath; - int found; -} ENUMMIRANDAWINDOW; +///////////////////////////////////////////////////////////////////////////////////////// static BOOL CALLBACK EnumMirandaWindows(HWND hwnd, LPARAM lParam) { wchar_t classname[256]; - ENUMMIRANDAWINDOW *x = (ENUMMIRANDAWINDOW *)lParam; - DWORD_PTR res = 0; if (GetClassName(hwnd, classname, _countof(classname)) && mir_wstrcmp(L"Miranda", classname) == 0) { - if (SendMessageTimeout(hwnd, x->msg, (WPARAM)x->aPath, 0, SMTO_ABORTIFHUNG, 100, &res) && res) { - x->found++; + DWORD_PTR res = 0; + if (SendMessageTimeout(hwnd, uMsgProcessProfile, lParam, 0, SMTO_ABORTIFHUNG, 100, &res) && res) return FALSE; - } } + return TRUE; } -int findMirandaForProfile(wchar_t *szProfile) -{ - ENUMMIRANDAWINDOW x = {}; - x.profile = szProfile; - x.msg = RegisterWindowMessage(L"Miranda::ProcessProfile"); - x.aPath = GlobalAddAtom(szProfile); - EnumWindows(EnumMirandaWindows, (LPARAM)&x); - GlobalDeleteAtom(x.aPath); - return x.found; -} +///////////////////////////////////////////////////////////////////////////////////////// static wchar_t tszNoDrivers[] = LPGENW("Miranda is unable to open '%s' because you do not have any profile plugins installed.\nYou need to install dbx_mdbx.dll"); static wchar_t tszUnknownFormat[] = LPGENW("Miranda was unable to open '%s', it's in an unknown format."); @@ -484,15 +467,18 @@ int LoadDatabaseModule(void) ptszFileName = (ptszFileName) ? ptszFileName + 1 : szProfile; if (arDbPlugins.getCount() == 0) { - MessageBox(nullptr, - CMStringW(FORMAT, TranslateW(tszNoDrivers), ptszFileName), - TranslateT("No profile support installed!"), MB_OK | MB_ICONERROR); + MessageBox(nullptr, CMStringW(FORMAT, TranslateW(tszNoDrivers), ptszFileName), TranslateT("No profile support installed!"), MB_OK | MB_ICONERROR); return 1; } // if this profile is already opened in another miranda, silently return - if (findMirandaForProfile(szProfile)) + if (Profile_CheckOpened(szProfile)) { + uMsgProcessProfile = RegisterWindowMessage(L"Miranda::ProcessProfile"); + ATOM aPath = GlobalAddAtom(szProfile); + EnumWindows(EnumMirandaWindows, (LPARAM)aPath); + GlobalDeleteAtom(aPath); return 1; + } // find a driver to support the given profile bool retry; diff --git a/src/mir_app/src/db_util.cpp b/src/mir_app/src/db_util.cpp index 1853ff2319..7b95357a4f 100644 --- a/src/mir_app/src/db_util.cpp +++ b/src/mir_app/src/db_util.cpp @@ -71,3 +71,19 @@ MIR_APP_DLL(void) Profile_SetDefault(const wchar_t *pwszPath) extern wchar_t* g_defaultProfile; replaceStrW(g_defaultProfile, pwszPath); } + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_APP_DLL(bool) Profile_CheckOpened(const wchar_t *pwszProfileName) +{ + CMStringW wszPhysName(pwszProfileName); + wszPhysName.Replace(L"\\", L"_"); + wszPhysName.Insert(0, L"Global\\"); + + HANDLE hMutex = ::OpenMutexW(SYNCHRONIZE, false, wszPhysName); + if (hMutex == nullptr) + return false; + + ::CloseHandle(hMutex); + return true; +} diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index 513d8cae5c..cde723cefb 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -619,3 +619,6 @@ UnregisterPlugin @633 ?Unload@CMPluginBase@@UAEHXZ @648 NONAME Srmm_ClickStatusIcon @649 ?getModule@CMPluginBase@@QBEPBDXZ @650 NONAME +?LockName@MDatabaseCommon@@IAE_NPB_W@Z @651 NONAME +?UnlockName@MDatabaseCommon@@IAEXXZ @652 NONAME +Profile_CheckOpened @653 diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 732effd29f..44634d5ce9 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -619,3 +619,6 @@ UnregisterPlugin @633 ?Unload@CMPluginBase@@UEAAHXZ @648 NONAME Srmm_ClickStatusIcon @649 ?getModule@CMPluginBase@@QEBAPEBDXZ @650 NONAME +?LockName@MDatabaseCommon@@IEAA_NPEB_W@Z @651 NONAME +?UnlockName@MDatabaseCommon@@IEAAXXZ @652 NONAME +Profile_CheckOpened @653 diff --git a/src/mir_app/src/profilemanager.cpp b/src/mir_app/src/profilemanager.cpp index f5b6e486d7..ad50cbbde8 100644 --- a/src/mir_app/src/profilemanager.cpp +++ b/src/mir_app/src/profilemanager.cpp @@ -270,7 +270,7 @@ class CChooseProfileDlg : public CDlgBase mir_snwprintf(sizeBuf, L"%.3lf", (double)statbuf.st_size / 1024.0); mir_wstrcpy(sizeBuf + 5, L" KB"); } - bFileLocked = findMirandaForProfile(tszFullPath) != 0; + bFileLocked = Profile_CheckOpened(tszFullPath); } else bFileLocked = true; diff --git a/src/mir_app/src/profilemanager.h b/src/mir_app/src/profilemanager.h index a3c238f9ca..11b5c6ed52 100644 --- a/src/mir_app/src/profilemanager.h +++ b/src/mir_app/src/profilemanager.h @@ -35,7 +35,6 @@ struct PROFILEMANAGERDATA DATABASELINK *dblink; // out }; -int findMirandaForProfile(wchar_t *szProfile); char* makeFileName(const wchar_t *tszOriginalName); int touchDatabase(const wchar_t *tszProfile, DATABASELINK **pDblink); int getProfileManager(PROFILEMANAGERDATA *pd); @@ -46,3 +45,4 @@ bool shouldAutoCreate(wchar_t *szProfile); extern wchar_t g_profileDir[MAX_PATH], g_profileName[MAX_PATH], g_shortProfileName[MAX_PATH]; extern bool g_bDbCreated; +extern UINT uMsgProcessProfile; -- cgit v1.2.3