summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/m_database.h4
-rw-r--r--include/m_db_int.h5
-rw-r--r--libs/win32/mir_app.libbin170150 -> 171002 bytes
-rw-r--r--libs/win64/mir_app.libbin165348 -> 166200 bytes
-rw-r--r--plugins/Dbx_mdbx/src/dbintf.cpp12
-rw-r--r--plugins/Dbx_mdbx/src/init.cpp2
-rw-r--r--src/mir_app/src/MDatabaseCommon.cpp34
-rw-r--r--src/mir_app/src/database.cpp38
-rw-r--r--src/mir_app/src/db_util.cpp16
-rw-r--r--src/mir_app/src/mir_app.def3
-rw-r--r--src/mir_app/src/mir_app64.def3
-rw-r--r--src/mir_app/src/profilemanager.cpp2
-rw-r--r--src/mir_app/src/profilemanager.h2
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
index e26e11a99f..0a53ac8f12 100644
--- a/libs/win32/mir_app.lib
+++ b/libs/win32/mir_app.lib
Binary files differ
diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib
index a699c36c3a..bba5b4e599 100644
--- a/libs/win64/mir_app.lib
+++ b/libs/win64/mir_app.lib
Binary files differ
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;