From 72348ec753695b71234631f4c358ca4505a1d737 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 16 Feb 2021 22:01:27 +0300 Subject: fixes #2745 (Dbx_sqlite: wrong behaviour when launching second Miranda with the same profile) --- plugins/Dbx_sqlite/src/dbintf.cpp | 82 +++++++++++++++++++-------------------- plugins/Dbx_sqlite/src/dbintf.h | 14 +++---- plugins/Dbx_sqlite/src/main.cpp | 30 ++++++++++++-- plugins/Dbx_sqlite/src/stdafx.h | 2 + plugins/Dbx_sqlite/src/version.h | 2 +- 5 files changed, 78 insertions(+), 52 deletions(-) (limited to 'plugins/Dbx_sqlite/src') diff --git a/plugins/Dbx_sqlite/src/dbintf.cpp b/plugins/Dbx_sqlite/src/dbintf.cpp index bb977059e7..7523153359 100755 --- a/plugins/Dbx_sqlite/src/dbintf.cpp +++ b/plugins/Dbx_sqlite/src/dbintf.cpp @@ -1,9 +1,11 @@ #include "stdafx.h" -CDbxSQLite::CDbxSQLite(sqlite3 *database) : - m_db(database), +CDbxSQLite::CDbxSQLite(const wchar_t *pwszFileName, bool bReadOnly, bool bShared) : m_impl(*this), + m_wszFileName(mir_wstrdup(pwszFileName)), m_safetyMode(true), + m_bReadOnly(bReadOnly), + m_bShared(bShared), m_modules(1, strcmp) { } @@ -27,50 +29,47 @@ CDbxSQLite::~CDbxSQLite() ///////////////////////////////////////////////////////////////////////////////////////// -int CDbxSQLite::Create(const wchar_t *profile) +int CDbxSQLite::Create() { - sqlite3 *database = nullptr; - ptrA path(mir_utf8encodeW(profile)); - int rc = sqlite3_open_v2(path, &database, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_EXCLUSIVE, nullptr); + ptrA path(mir_utf8encodeW(m_wszFileName)); + int rc = sqlite3_open_v2(path, &m_db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_EXCLUSIVE, nullptr); logError(rc, __FILE__, __LINE__); if (rc != SQLITE_OK) { logError(rc, __FILE__, __LINE__); return 1; } - rc = sqlite3_exec(database, "CREATE TABLE contacts (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "CREATE TABLE contacts (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE TABLE events (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL, module TEXT NOT NULL," + rc = sqlite3_exec(m_db, "CREATE TABLE events (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL, module TEXT NOT NULL," "timestamp INTEGER NOT NULL, type INTEGER NOT NULL, flags INTEGER NOT NULL, data BLOB, server_id TEXT);", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE INDEX idx_events_contactid_timestamp ON events(contact_id, timestamp);", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "CREATE INDEX idx_events_contactid_timestamp ON events(contact_id, timestamp);", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE INDEX idx_events_module_serverid ON events(module, server_id);", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "CREATE INDEX idx_events_module_serverid ON events(module, server_id);", nullptr, nullptr, nullptr); if (rc != SQLITE_OK) logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE TABLE events_srt (id INTEGER NOT NULL, contact_id INTEGER NOT NULL, timestamp INTEGER, PRIMARY KEY(contact_id, timestamp, id));", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "CREATE TABLE events_srt (id INTEGER NOT NULL, contact_id INTEGER NOT NULL, timestamp INTEGER, PRIMARY KEY(contact_id, timestamp, id));", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE TABLE settings (contact_id INTEGER NOT NULL, module TEXT NOT NULL, setting TEXT NOT NULL, type INTEGER NOT NULL, value ANY," + rc = sqlite3_exec(m_db, "CREATE TABLE settings (contact_id INTEGER NOT NULL, module TEXT NOT NULL, setting TEXT NOT NULL, type INTEGER NOT NULL, value ANY," "PRIMARY KEY(contact_id, module, setting)) WITHOUT ROWID;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "CREATE INDEX idx_settings_module ON settings(module);", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "CREATE INDEX idx_settings_module ON settings(module);", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - - sqlite3_close(database); return 0; } ///////////////////////////////////////////////////////////////////////////////////////// -int CDbxSQLite::Check(const wchar_t *profile) +int CDbxSQLite::Check() { - FILE *hFile = _wfopen(profile, L"rb"); + FILE *hFile = _wfopen(m_wszFileName, L"rb"); if (hFile == INVALID_HANDLE_VALUE) return EGROKPRF_CANTREAD; @@ -88,7 +87,7 @@ int CDbxSQLite::Check(const wchar_t *profile) return EGROKPRF_UNKHEADER; sqlite3 *database = nullptr; - ptrA path(mir_utf8encodeW(profile)); + ptrA path(mir_utf8encodeW(m_wszFileName)); int rc = sqlite3_open_v2(path, &database, SQLITE_OPEN_READONLY | SQLITE_OPEN_EXCLUSIVE, nullptr); if (rc != SQLITE_OK) { logError(rc, __FILE__, __LINE__); @@ -102,48 +101,49 @@ int CDbxSQLite::Check(const wchar_t *profile) ///////////////////////////////////////////////////////////////////////////////////////// -MDatabaseCommon* CDbxSQLite::Load(const wchar_t *profile, int readonly) +int CDbxSQLite::Load() { - sqlite3 *database = nullptr; - ptrA path(mir_utf8encodeW(profile)); - int flags = SQLITE_OPEN_EXCLUSIVE; - if (readonly) + if (!LockName(m_wszFileName)) + return EGROKPRF_CANTREAD; + + ptrA path(mir_utf8encodeW(m_wszFileName)); + int flags = 0; + if (!m_bShared) + flags |= SQLITE_OPEN_EXCLUSIVE; + if (m_bReadOnly) flags |= SQLITE_OPEN_READONLY; else flags |= SQLITE_OPEN_READWRITE; - int rc = sqlite3_open_v2(path, &database, flags, nullptr); + int rc = sqlite3_open_v2(path, &m_db, flags, nullptr); if (rc != SQLITE_OK) { logError(rc, __FILE__, __LINE__); - return nullptr; + return EGROKPRF_CANTREAD; } - rc = sqlite3_exec(database, "pragma locking_mode = EXCLUSIVE;", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "pragma locking_mode = EXCLUSIVE;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "pragma synchronous = NORMAL;", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "pragma synchronous = NORMAL;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "pragma foreign_keys = OFF;", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "pragma foreign_keys = OFF;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - rc = sqlite3_exec(database, "pragma journal_mode = OFF;", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "pragma journal_mode = OFF;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); if (rc == SQLITE_BUSY) { - sqlite3_close(database); - return nullptr; + sqlite3_close(m_db); + return EGROKPRF_CANTREAD; } - CDbxSQLite *db = new CDbxSQLite(database); - db->InitContacts(); - db->InitSettings(); - db->InitEvents(); + InitContacts(); + InitSettings(); + InitEvents(); - if (db->InitCrypt()) { - delete db; - return nullptr; - } + if (InitCrypt()) + return EGROKPRF_CANTREAD; - rc = sqlite3_exec(database, "begin transaction;", nullptr, nullptr, nullptr); + rc = sqlite3_exec(m_db, "begin transaction;", nullptr, nullptr, nullptr); logError(rc, __FILE__, __LINE__); - return db; + return EGROKPRF_NOERROR; } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/Dbx_sqlite/src/dbintf.h b/plugins/Dbx_sqlite/src/dbintf.h index 9acbe25db9..b2f2c264ca 100755 --- a/plugins/Dbx_sqlite/src/dbintf.h +++ b/plugins/Dbx_sqlite/src/dbintf.h @@ -36,7 +36,8 @@ private: class CDbxSQLite : public MDatabaseCommon, public MZeroedObject { - sqlite3 *m_db; + ptrW m_wszFileName; + sqlite3 *m_db = nullptr; sqlite3_stmt *evt_cur_fwd = nullptr, *evt_cur_backwd = nullptr; MCONTACT evt_cnt_fwd = 0, evt_cnt_backwd = 0; @@ -61,9 +62,7 @@ class CDbxSQLite : public MDatabaseCommon, public MZeroedObject } } m_impl; - bool m_safetyMode; - - CDbxSQLite(sqlite3 *database); + bool m_safetyMode, m_bReadOnly, m_bShared; void InitContacts(); void UninitContacts(); @@ -78,11 +77,12 @@ class CDbxSQLite : public MDatabaseCommon, public MZeroedObject void DBFlush(bool bForce = false); public: + CDbxSQLite(const wchar_t *pwszFileName, bool bReadOnly, bool bShared); ~CDbxSQLite(); - static int Create(const wchar_t *profile); - static int Check(const wchar_t *profile); - static MDatabaseCommon* Load(const wchar_t *profile, int readonly); + int Create(); + int Check(); + int Load(); STDMETHODIMP_(BOOL) IsRelational(void) override; STDMETHODIMP_(void) SetCacheSafetyMode(BOOL) override; diff --git a/plugins/Dbx_sqlite/src/main.cpp b/plugins/Dbx_sqlite/src/main.cpp index e3fe8b51d9..6c0f75b741 100644 --- a/plugins/Dbx_sqlite/src/main.cpp +++ b/plugins/Dbx_sqlite/src/main.cpp @@ -27,14 +27,38 @@ CMPlugin::CMPlugin() : ///////////////////////////////////////////////////////////////////////////////////////// +// returns 0 if the profile is created, EMKPRF* +static int makeDatabase(const wchar_t *profile) +{ + std::unique_ptr db(new CDbxSQLite(profile, false, false)); + return db->Create(); +} + +// returns 0 if the given profile has a valid header +static int grokHeader(const wchar_t *profile) +{ + std::unique_ptr db(new CDbxSQLite(profile, true, true)); + return db->Check(); +} + +// returns 0 if all the APIs are injected otherwise, 1 +static MDatabaseCommon* loadDatabase(const wchar_t *profile, BOOL bReadOnly) +{ + std::unique_ptr db(new CDbxSQLite(profile, bReadOnly, false)); + if (db->Load() != ERROR_SUCCESS) + return nullptr; + + return db.release(); +} + static DATABASELINK dblink = { MDB_CAPS_CREATE | MDB_CAPS_COMPACT, "dbx_sqlite", L"SQLite database driver", - &CDbxSQLite::Create, - &CDbxSQLite::Check, - &CDbxSQLite::Load, + makeDatabase, + grokHeader, + loadDatabase , }; STDMETHODIMP_(DATABASELINK *) CDbxSQLite::GetDriver() diff --git a/plugins/Dbx_sqlite/src/stdafx.h b/plugins/Dbx_sqlite/src/stdafx.h index 90cba22430..ff83996237 100644 --- a/plugins/Dbx_sqlite/src/stdafx.h +++ b/plugins/Dbx_sqlite/src/stdafx.h @@ -4,6 +4,8 @@ #include #include +#include + #include #include #include diff --git a/plugins/Dbx_sqlite/src/version.h b/plugins/Dbx_sqlite/src/version.h index 5f086b9e31..04c7f4a7a4 100644 --- a/plugins/Dbx_sqlite/src/version.h +++ b/plugins/Dbx_sqlite/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 95 #define __RELEASE_NUM 13 -#define __BUILD_NUM 3 +#define __BUILD_NUM 4 #include -- cgit v1.2.3