From bfe1bd0fc087be44c70904aee0fe4276643d206d Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 20 Jul 2012 15:56:25 +0000 Subject: - db3x_mmap is completely moved to a class; - the old nightmare in the core "How to detect a db plugin and load it" is eliminated forever; - databases are the usual plugins now (loadable via Load) - dynamic DATABASELINK registration git-svn-id: http://svn.miranda-ng.org/main/trunk@1082 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/database/database.cpp | 76 +++++++++++++++------------------ src/modules/database/dbintf.cpp | 34 ++++++++++++++- src/modules/database/profilemanager.cpp | 65 ++++++++++------------------ src/modules/database/profilemanager.h | 11 ----- src/modules/plugins/dll_sniffer.cpp | 2 +- src/modules/plugins/newplugins.cpp | 70 +++++++----------------------- src/modules/plugins/plugins.h | 7 +-- 7 files changed, 107 insertions(+), 158 deletions(-) (limited to 'src/modules') diff --git a/src/modules/database/database.cpp b/src/modules/database/database.cpp index 8686d50bc6..13ce6bbfa9 100644 --- a/src/modules/database/database.cpp +++ b/src/modules/database/database.cpp @@ -23,8 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "..\..\core\commonheaders.h" #include "profilemanager.h" -MIR_CORE_DLL(void) db_setCurrent(MIDatabase* _db); - // contains the location of mirandaboot.ini extern TCHAR mirandabootini[MAX_PATH]; bool dbCreated; @@ -413,59 +411,59 @@ int makeDatabase(TCHAR *profile, DATABASELINK * link, HWND hwndDlg) } // enumerate all plugins that had valid DatabasePluginInfo() -static int FindDbPluginForProfile(const TCHAR*, DATABASELINK *dblink, LPARAM lParam) +int tryOpenDatabase(const TCHAR* tszProfile) { - TCHAR* tszProfile = (TCHAR*)lParam; - int res = DBPE_CONT; - if (dblink && dblink->cbSize == sizeof(DATABASELINK)) { + for (int i=0; i < arDbPlugins.getCount(); i++) { + DATABASELINK* p = arDbPlugins[i]; + // liked the profile? int err = 0; - if (dblink->grokHeader(tszProfile, &err) == 0) { + if ( p->grokHeader(tszProfile, &err) == 0) { // added APIs? - MIDatabase* pDb = dblink->Load(tszProfile); + MIDatabase* pDb = p->Load(tszProfile); if (pDb) { fillProfileName(tszProfile); + currDblink = p; db_setCurrent(currDb = pDb); - res = DBPE_DONE; + return 0; } - else res = DBPE_HALT; + return 1; } else { - res = DBPE_HALT; switch (err) { case EGROKPRF_CANTREAD: case EGROKPRF_UNKHEADER: // just not supported. - res = DBPE_CONT; + continue; case EGROKPRF_VERNEWER: case EGROKPRF_DAMAGED: - break; + return 1; } } //if } - return res; + return 1; } // enumerate all plugins that had valid DatabasePluginInfo() -static int FindDbPluginAutoCreate(const TCHAR* ptszProfile, DATABASELINK * dblink, LPARAM lParam) +static int tryCreateDatabase(const TCHAR* ptszProfile) { - int res = DBPE_CONT; - if (dblink && dblink->cbSize == sizeof(DATABASELINK)) { - TCHAR* tszProfile = NEWTSTR_ALLOCA(ptszProfile); - CreatePathToFileT(tszProfile); + TCHAR* tszProfile = NEWTSTR_ALLOCA(ptszProfile); + CreatePathToFileT(tszProfile); + + for (int i=0; i < arDbPlugins.getCount(); i++) { + DATABASELINK* p = arDbPlugins[i]; int err; - if (dblink->makeDatabase(tszProfile, &err) == 0) { - dbCreated = true; - if ( !dblink->Load(tszProfile)) { + if (p->makeDatabase(tszProfile, &err) == 0) { + if ( !p->Load(tszProfile)) { fillProfileName(tszProfile); - res = DBPE_DONE; + return 0; } - else res = DBPE_HALT; + return 1; } } - return res; + return 1; } typedef struct { @@ -514,28 +512,24 @@ int LoadDatabaseModule(void) if ( !getProfile(szProfile, SIZEOF(szProfile))) return 1; - pfnDbEnumCallback pFunc; - if (_taccess(szProfile, 0) && shouldAutoCreate(szProfile)) - pFunc = FindDbPluginAutoCreate; - else - pFunc = FindDbPluginForProfile; + if ( arDbPlugins.getCount() == 0) { + TCHAR buf[256]; + TCHAR* p = _tcsrchr(szProfile, '\\'); + mir_sntprintf(buf, SIZEOF(buf), TranslateT("Miranda is unable to open '%s' because you do not have any profile plugins installed.\nYou need to install dbx_3x.dll or equivalent."), p ? ++p : szProfile); + MessageBox(0, buf, TranslateT("No profile support installed!"), MB_OK | MB_ICONERROR); + } // find a driver to support the given profile bool retry; int rc; do { retry = false; - rc = enumDbPlugins(pFunc, (LPARAM)szProfile); - switch (rc) { - case -1: { - // no plugins at all - TCHAR buf[256]; - TCHAR* p = _tcsrchr(szProfile, '\\'); - mir_sntprintf(buf, SIZEOF(buf), TranslateT("Miranda is unable to open '%s' because you do not have any profile plugins installed.\nYou need to install dbx_3x.dll or equivalent."), p ? ++p : szProfile); - MessageBox(0, buf, TranslateT("No profile support installed!"), MB_OK | MB_ICONERROR); - break; - } - case 1: + if ( _taccess(szProfile, 0) && shouldAutoCreate(szProfile)) + rc = tryCreateDatabase(szProfile); + else + rc = tryOpenDatabase(szProfile); + + if (rc != 0) { // if there were drivers but they all failed cos the file is locked, try and find the miranda which locked it if (fileExist(szProfile)) { // file isn't locked, just no driver could open it. diff --git a/src/modules/database/dbintf.cpp b/src/modules/database/dbintf.cpp index c3bf4f3b5c..2f7cf4ea72 100644 --- a/src/modules/database/dbintf.cpp +++ b/src/modules/database/dbintf.cpp @@ -23,7 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "..\..\core\commonheaders.h" -MIDatabase* currDb = NULL; +MIDatabase *currDb = NULL; +DATABASELINK *currDblink = NULL; MIR_CORE_DLL(void) db_setCurrent(MIDatabase*); @@ -159,6 +160,34 @@ static INT_PTR srvEnumResidentSettings(WPARAM wParam,LPARAM lParam) { return (currDb) ? (INT_PTR)currDb->EnumResidentSettings((DBMODULEENUMPROC)wParam, (void*)lParam) : 0; } +/////////////////////////////////////////////////////////////////////////////// +// Database list + +LIST arDbPlugins(5); + +static INT_PTR srvRegisterPlugin(WPARAM wParam,LPARAM lParam) +{ + DATABASELINK* pPlug = (DATABASELINK*)lParam; + if (pPlug == NULL) + return 1; + + arDbPlugins.insert(pPlug); + return 0; +} + +static INT_PTR srvFindPlugin(WPARAM wParam,LPARAM lParam) +{ + for (int i=0; i < arDbPlugins.getCount(); i++) { + int error; + if (arDbPlugins[i]->grokHeader((TCHAR*)lParam, &error) == ERROR_SUCCESS) + return (INT_PTR)arDbPlugins[i]; + } + + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + int LoadDbintfModule() { CreateServiceFunction(MS_DB_SETSAFETYMODE, srvSetSafetyMode); @@ -194,5 +223,8 @@ int LoadDbintfModule() CreateServiceFunction(MS_DB_CONTACT_ENUMSETTINGS, srvEnumContactSettings); CreateServiceFunction(MS_DB_SETSETTINGRESIDENT, srvSetSettingResident); CreateServiceFunction("DB/ResidentSettings/Enum", srvEnumResidentSettings); + + CreateServiceFunction(MS_DB_REGISTER_PLUGIN, srvRegisterPlugin); + CreateServiceFunction(MS_DB_FIND_PLUGIN, srvFindPlugin); return 0; } diff --git a/src/modules/database/profilemanager.cpp b/src/modules/database/profilemanager.cpp index 4e8ebc381f..6ca3206574 100644 --- a/src/modules/database/profilemanager.cpp +++ b/src/modules/database/profilemanager.cpp @@ -115,20 +115,6 @@ static LRESULT CALLBACK ProfileNameValidate(HWND edit, UINT msg, WPARAM wParam, return CallWindowProc((WNDPROC)GetWindowLongPtr(edit, GWLP_USERDATA), edit, msg, wParam, lParam); } -static int FindDbProviders(const TCHAR* tszProfileName, DATABASELINK *dblink, LPARAM lParam) -{ - HWND hwndDlg = (HWND)lParam; - HWND hwndCombo = GetDlgItem(hwndDlg, IDC_PROFILEDRIVERS); - TCHAR szName[64]; - - if (dblink->getFriendlyName(szName, SIZEOF(szName), 1) == 0) { - // add to combo box - LRESULT index = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)szName); - SendMessage(hwndCombo, CB_SETITEMDATA, index, (LPARAM)dblink); - } - return DBPE_CONT; -} - static INT_PTR CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { struct DlgProfData * dat = (struct DlgProfData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); @@ -138,18 +124,26 @@ static INT_PTR CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPA SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); dat = (struct DlgProfData *)lParam; { - // fill in the db plugins present - if (enumDbPlugins(FindDbProviders, (LPARAM)hwndDlg) == -1) { - // what, no plugins?! - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILEDRIVERS), FALSE); + HWND hwndCombo = GetDlgItem(hwndDlg, IDC_PROFILEDRIVERS); + + // what, no plugins?! + if (arDbPlugins.getCount() == 0) { + EnableWindow(hwndCombo, FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILENAME), FALSE); ShowWindow(GetDlgItem(hwndDlg, IDC_NODBDRIVERS), TRUE); } + else { + for (int i=0; i < arDbPlugins.getCount(); i++) { + DATABASELINK* p = arDbPlugins[i]; + LRESULT index = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)TranslateTS(p->szFullName)); + SendMessage(hwndCombo, CB_SETITEMDATA, index, (LPARAM)p); + } + } + // default item - SendDlgItemMessage(hwndDlg, IDC_PROFILEDRIVERS, CB_SETCURSEL, 0, 0); - } - // subclass the profile name box - { + SendMessage(hwndCombo, CB_SETCURSEL, 0, 0); + + // subclass the profile name box HWND hwndProfile = GetDlgItem(hwndDlg, IDC_PROFILENAME); WNDPROC proc = (WNDPROC)GetWindowLongPtr(hwndProfile, GWLP_WNDPROC); SetWindowLongPtr(hwndProfile, GWLP_USERDATA, (LONG_PTR)proc); @@ -157,8 +151,7 @@ static INT_PTR CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPA } // decide if there is a default profile name given in the INI and if it should be used - if (dat->pd->noProfiles || (shouldAutoCreate(dat->pd->szProfile) && _taccess(dat->pd->szProfile, 0))) - { + if (dat->pd->noProfiles || (shouldAutoCreate(dat->pd->szProfile) && _taccess(dat->pd->szProfile, 0))) { TCHAR* profile = _tcsrchr(dat->pd->szProfile, '\\'); if (profile) ++profile; else profile = dat->pd->szProfile; @@ -216,21 +209,6 @@ static INT_PTR CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPA return FALSE; } -static int DetectDbProvider(const TCHAR*, DATABASELINK * dblink, LPARAM lParam) -{ - int error; - int ret = dblink->grokHeader((TCHAR*)lParam, &error); - if (ret == 0) { - - TCHAR tmp[ MAX_PATH ]; - dblink->getFriendlyName(tmp, SIZEOF(tmp), 1); - _tcsncpy((TCHAR*)lParam, tmp, MAX_PATH); - return DBPE_HALT; - } - - return DBPE_CONT; -} - BOOL EnumProfilesForList(TCHAR *fullpath, TCHAR *profile, LPARAM lParam) { ProfileEnumData *ped = (ProfileEnumData*)lParam; @@ -260,7 +238,6 @@ BOOL EnumProfilesForList(TCHAR *fullpath, TCHAR *profile, LPARAM lParam) _tcscpy(sizeBuf+5, _T(" KB")); } bFileExists = TRUE; - bFileLocked = !fileExist(fullpath); } @@ -283,7 +260,8 @@ BOOL EnumProfilesForList(TCHAR *fullpath, TCHAR *profile, LPARAM lParam) item2.mask = LVIF_TEXT; item2.iItem = iItem; - if ( enumDbPlugins(DetectDbProvider, (LPARAM)szPath) == 1) { + DATABASELINK* dblink = FindDatabasePlugin(szPath); + if (dblink != NULL) { if (bFileLocked) { // file locked item2.pszText = TranslateT(""); @@ -291,10 +269,11 @@ BOOL EnumProfilesForList(TCHAR *fullpath, TCHAR *profile, LPARAM lParam) SendMessage(hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item2); } else { - item.pszText = szPath; + item.pszText = TranslateTS(dblink->szFullName); item.iSubItem = 1; SendMessage(hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item); - } } + } + } item2.iSubItem = 3; item2.pszText = trtrim(_tctime(&statbuf.st_ctime)); diff --git a/src/modules/database/profilemanager.h b/src/modules/database/profilemanager.h index 64e4960fdc..e3ed554e56 100644 --- a/src/modules/database/profilemanager.h +++ b/src/modules/database/profilemanager.h @@ -42,14 +42,3 @@ bool shouldAutoCreate(TCHAR *szProfile); extern TCHAR g_profileDir[MAX_PATH]; extern TCHAR g_profileName[MAX_PATH]; - -/////////////////////////////////////////////////////////////////////////////// -// former m_plugins.h - -#define DBPE_DONE 1 -#define DBPE_CONT 0 -#define DBPE_HALT (-1) - -typedef int (*pfnDbEnumCallback) (const TCHAR *pluginname, DATABASELINK* link, LPARAM lParam); - -int enumDbPlugins(pfnDbEnumCallback pFunc, LPARAM lParam); diff --git a/src/modules/plugins/dll_sniffer.cpp b/src/modules/plugins/dll_sniffer.cpp index 469cebf931..531c9e6919 100644 --- a/src/modules/plugins/dll_sniffer.cpp +++ b/src/modules/plugins/dll_sniffer.cpp @@ -42,7 +42,7 @@ MUUID* GetPluginInterfaces(const TCHAR* ptszFileName, bool& bIsPlugin) MUUID* pResult = NULL; BYTE* ptr = NULL; - HANDLE hMap = CreateFileMapping( hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL ); + HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL ); __try { diff --git a/src/modules/plugins/newplugins.cpp b/src/modules/plugins/newplugins.cpp index 083338614d..ce412e8d34 100644 --- a/src/modules/plugins/newplugins.cpp +++ b/src/modules/plugins/newplugins.cpp @@ -76,7 +76,7 @@ static int serviceModeIdx = -1, sttFakeID = -100; static HANDLE hPluginListHeap = NULL; static int askAboutIgnoredPlugins; -static pluginEntry *pluginListSM, *pluginListDb, *pluginListUI, *pluginList_freeimg, *pluginList_crshdmp; +static pluginEntry *pluginListSM, *pluginListUI, *pluginList_freeimg, *pluginList_crshdmp; int InitIni(void); void UninitIni(void); @@ -197,11 +197,6 @@ static int isPluginBanned(MUUID u1, DWORD dwVersion) return 0; } -// returns true if the API exports were good, otherwise, passed in data is returned -#define CHECKAPI_NONE 0 -#define CHECKAPI_DB 1 -#define CHECKAPI_CLIST 2 - /* * historyeditor added by nightwish - plugin is problematic and can ruin database as it does not understand UTF-8 message * storage @@ -291,17 +286,6 @@ LBL_Ok: return 1; } - // check for DB? - if (checkTypeAPI == CHECKAPI_DB) { - bpi->DbInfo = (Database_Plugin_Info) GetProcAddress(h, "DatabasePluginInfo"); - if (bpi->DbInfo) { - // fetch internal database function pointers - bpi->dblink = bpi->DbInfo(NULL); - // validate returned link structure - if (bpi->dblink && bpi->dblink->cbSize == sizeof(DATABASELINK)) - goto LBL_Ok; - } } - // check clist ? if (checkTypeAPI == CHECKAPI_CLIST) { bpi->clistlink = (CList_Initialise) GetProcAddress(h, "CListInitialise"); @@ -316,10 +300,6 @@ LBL_Ok: // perform any API related tasks to freeing void Plugin_Uninit(pluginEntry* p) { - // if it was an installed database plugin, call its unload - if (p->pclass & PCLASS_DB) - p->bpi.dblink->Unload(p->pclass & PCLASS_OK); - // if the basic API check had passed, call Unload if Load(void) was ever called if (p->pclass & PCLASS_LOADED) p->bpi.Unload(); @@ -406,33 +386,6 @@ void enumPlugins(SCAN_PLUGINS_CALLBACK cb, WPARAM wParam, LPARAM lParam) } } -// this is called by the db module to return all DBs plugins, then when it finds the one it likes the others are unloaded -int enumDbPlugins(pfnDbEnumCallback pFunc, LPARAM lParam) -{ - pluginEntry *x = pluginListDb; - if (pFunc == NULL) - return 1; - - while (x != NULL) { - int rc = pFunc(x->pluginname, x->bpi.dblink, lParam); - if (rc == DBPE_DONE) { - // this db has been picked, get rid of all the others - pluginEntry *y = pluginListDb, *n; - while (y != NULL) { - n = y->nextclass; - if (x != y) - Plugin_Uninit(y); - y = n; - } // while - x->pclass |= PCLASS_LOADED | PCLASS_OK | PCLASS_LAST; - return 0; - } - else if (rc == DBPE_HALT) return 1; - x = x->nextclass; - } // while - return pluginListDb != NULL ? 1 : -1; -} - pluginEntry* OpenPlugin(TCHAR *tszFileName, TCHAR *dir, TCHAR *path) { pluginEntry* p = (pluginEntry*)HeapAlloc(hPluginListHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, sizeof(pluginEntry)); @@ -455,18 +408,19 @@ pluginEntry* OpenPlugin(TCHAR *tszFileName, TCHAR *dir, TCHAR *path) // plugin declared that it's a database. load it asap! if ( hasMuuid(pIds, miid_database)) { BASIC_PLUGIN_INFO bpi; - if (checkAPI(tszFullPath, &bpi, mirandaVersion, CHECKAPI_DB)) { + if (checkAPI(tszFullPath, &bpi, mirandaVersion, CHECKAPI_NONE)) { // db plugin is valid p->pclass |= (PCLASS_DB | PCLASS_BASICAPI); // copy the dblink stuff p->bpi = bpi; - // keep a faster list. - if (pluginListDb != NULL) p->nextclass = pluginListDb; - pluginListDb = p; + + RegisterModule(p->bpi.hInst); + if (bpi.Load() != 0) + p->pclass |= PCLASS_FAILED; + else + p->pclass |= PCLASS_LOADED; } - else - // didn't have basic APIs or DB exports - failed. - p->pclass |= PCLASS_FAILED; + else p->pclass |= PCLASS_FAILED; } // plugin declared that it's a contact list. mark it for the future load else if ( hasMuuid(pIds, miid_clist)) { @@ -859,6 +813,12 @@ void UnloadNewPluginsModule(void) Plugin_Uninit(pluginList_crshdmp); // unload the DB + if (currDb != NULL) { + db_setCurrent(NULL); + currDblink->Unload(currDb); + currDb = NULL; + } + for (int k = pluginList.getCount()-1; k >= 0; k--) { pluginEntry* p = pluginList[k]; Plugin_Uninit(p); diff --git a/src/modules/plugins/plugins.h b/src/modules/plugins/plugins.h index 64118a45ed..e0466ccc35 100644 --- a/src/modules/plugins/plugins.h +++ b/src/modules/plugins/plugins.h @@ -1,8 +1,7 @@ // returns true if the API exports were good, otherwise, passed in data is returned #define CHECKAPI_NONE 0 -#define CHECKAPI_DB 1 -#define CHECKAPI_CLIST 2 +#define CHECKAPI_CLIST 1 // block these plugins #define DEFMOD_REMOVED_UIPLUGINOPTS 21 @@ -13,8 +12,6 @@ typedef int (__cdecl * Miranda_Plugin_Load) (void); typedef int (__cdecl * Miranda_Plugin_Unload) (void); // version control typedef PLUGININFOEX * (__cdecl * Miranda_Plugin_InfoEx) (DWORD mirandaVersion); -// prototype for databases -typedef DATABASELINK * (__cdecl * Database_Plugin_Info) (void * reserved); // prototype for clists typedef int (__cdecl * CList_Initialise) (void); @@ -25,11 +22,9 @@ struct BASIC_PLUGIN_INFO Miranda_Plugin_Load Load; Miranda_Plugin_Unload Unload; Miranda_Plugin_InfoEx InfoEx; - Database_Plugin_Info DbInfo; CList_Initialise clistlink; PLUGININFOEX * pluginInfo; // must be freed if hInst = = NULL then its a copy MUUID *Interfaces; // array of supported interfaces - DATABASELINK * dblink; // only valid during module being in memory }; #define PCLASS_FAILED 0x1 // not a valid plugin, or API is invalid, pluginname is valid -- cgit v1.2.3