diff options
-rw-r--r-- | include/m_database.h | 4 | ||||
-rw-r--r-- | include/m_db_int.h | 5 | ||||
-rw-r--r-- | libs/win32/mir_app.lib | bin | 170150 -> 171002 bytes | |||
-rw-r--r-- | libs/win64/mir_app.lib | bin | 165348 -> 166200 bytes | |||
-rw-r--r-- | plugins/Dbx_mdbx/src/dbintf.cpp | 12 | ||||
-rw-r--r-- | plugins/Dbx_mdbx/src/init.cpp | 2 | ||||
-rw-r--r-- | src/mir_app/src/MDatabaseCommon.cpp | 34 | ||||
-rw-r--r-- | src/mir_app/src/database.cpp | 38 | ||||
-rw-r--r-- | src/mir_app/src/db_util.cpp | 16 | ||||
-rw-r--r-- | src/mir_app/src/mir_app.def | 3 | ||||
-rw-r--r-- | src/mir_app/src/mir_app64.def | 3 | ||||
-rw-r--r-- | src/mir_app/src/profilemanager.cpp | 2 | ||||
-rw-r--r-- | src/mir_app/src/profilemanager.h | 2 |
13 files changed, 87 insertions, 34 deletions
diff --git a/include/m_database.h b/include/m_database.h index 651a0a3b0a..8f7e974b40 100644 --- a/include/m_database.h +++ b/include/m_database.h @@ -458,9 +458,11 @@ EXTERN_C MIR_APP_DLL(int) Profile_GetPathW(size_t cbLen, wchar_t *pwszDest); // Sets the default profile name programmatically
// Analog of Database/DefaultProfile in mirandaboot.ini
-
EXTERN_C MIR_APP_DLL(void) Profile_SetDefault(const wchar_t *pwszPath);
+// Checks if a profile is opened
+EXTERN_C MIR_APP_DLL(bool) Profile_CheckOpened(const wchar_t *pwszProfileName);
+
/////////////////////////////////////////////////////////////////////////////////////////
// Contact services
diff --git a/include/m_db_int.h b/include/m_db_int.h index f32439c213..d0b66e8f25 100644 --- a/include/m_db_int.h +++ b/include/m_db_int.h @@ -133,6 +133,7 @@ interface MIR_APP_EXPORT MIDatabase class MIR_APP_EXPORT MDatabaseCommon : public MIDatabase
{
+ HANDLE m_hLock;
protected:
int m_codePage;
@@ -142,7 +143,9 @@ protected: MIDatabaseCache* m_cache;
protected:
- int CheckProto(DBCachedContact *cc, const char *proto);
+ bool LockName(const wchar_t *pwszProfileName);
+ int CheckProto(DBCachedContact *cc, const char *proto);
+ void UnlockName();
STDMETHOD_(BOOL, GetContactSettingWorker)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) PURE;
diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib Binary files differindex e26e11a99f..0a53ac8f12 100644 --- a/libs/win32/mir_app.lib +++ b/libs/win32/mir_app.lib diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib Binary files differindex a699c36c3a..bba5b4e599 100644 --- a/libs/win64/mir_app.lib +++ b/libs/win64/mir_app.lib diff --git a/plugins/Dbx_mdbx/src/dbintf.cpp b/plugins/Dbx_mdbx/src/dbintf.cpp index 21c6c3a988..4247806e0a 100644 --- a/plugins/Dbx_mdbx/src/dbintf.cpp +++ b/plugins/Dbx_mdbx/src/dbintf.cpp @@ -150,7 +150,7 @@ int CDbxMDBX::Load() }
size_t iDefHeaderOffset = 0;
-BYTE bDefHeader[] = { 0 };
+BYTE bDefHeader[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0 };
int CDbxMDBX::Check(void)
{
@@ -215,6 +215,9 @@ STDMETHODIMP_(void) CDbxMDBX::SetCacheSafetyMode(BOOL bIsSet) int CDbxMDBX::Map()
{
+ if (!LockName(m_tszProfileName))
+ return EGROKPRF_CANTREAD;
+
#ifdef _WIN64
__int64 upperLimit = 0x400000000ul;
#else
@@ -229,13 +232,16 @@ int CDbxMDBX::Map() 512ul << 10, // 512K shrink threshold
-1); // default page size
if (rc != MDBX_SUCCESS)
- return rc;
+ return EGROKPRF_CANTREAD;
unsigned int mode = MDBX_NOSUBDIR | MDBX_MAPASYNC | MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_COALESCE;
if (m_bReadOnly)
mode |= MDBX_RDONLY;
- return mdbx_env_open(m_env, _T2A(m_tszProfileName), mode, 0664);
+ if (mdbx_env_open(m_env, _T2A(m_tszProfileName), mode, 0664) != MDBX_SUCCESS)
+ return EGROKPRF_CANTREAD;
+
+ return EGROKPRF_NOERROR;
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/Dbx_mdbx/src/init.cpp b/plugins/Dbx_mdbx/src/init.cpp index 3419fd6c78..6a85913bde 100644 --- a/plugins/Dbx_mdbx/src/init.cpp +++ b/plugins/Dbx_mdbx/src/init.cpp @@ -67,7 +67,7 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_DATABA static int makeDatabase(const TCHAR *profile)
{
std::unique_ptr<CDbxMDBX> db(new CDbxMDBX(profile, 0));
- return (db->Map() == MDBX_SUCCESS) ? 0 : EGROKPRF_CANTREAD;
+ return db->Map();
}
// returns 0 if the given profile has a valid header
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;
|