int PluginsManager::loadPlugin(const TCHAR *pluginFilePath, vector<generic_string> & dll2Remove) { const TCHAR *pluginFileName = ::PathFindFileName(pluginFilePath); if (isInLoadedDlls(pluginFileName)) return 0; NppParameters * nppParams = NppParameters::getInstance(); PluginInfo *pi = new PluginInfo; try { pi->_moduleName = pluginFileName; if (GetBinaryArchitectureType(pluginFilePath) != ARCH_TYPE) throw generic_string(ARCH_ERR_MSG); pi->_hLib = ::LoadLibrary(pluginFilePath); if (!pi->_hLib) { generic_string lastErrorMsg = GetLastErrorAsString(); if (lastErrorMsg.empty()) throw generic_string(TEXT("Load Library has failed.\nChanging the project's \"Runtime Library\" setting to \"Multi-threaded(/MT)\" might solve this problem.")); else throw generic_string(lastErrorMsg.c_str()); } pi->_pFuncIsUnicode = (PFUNCISUNICODE)GetProcAddress(pi->_hLib, "isUnicode"); if (!pi->_pFuncIsUnicode || !pi->_pFuncIsUnicode()) throw generic_string(TEXT("This ANSI plugin is not compatible with your Unicode Notepad++.")); pi->_pFuncSetInfo = (PFUNCSETINFO)GetProcAddress(pi->_hLib, "setInfo"); if (!pi->_pFuncSetInfo) throw generic_string(TEXT("Missing \"setInfo\" function")); pi->_pFuncGetName = (PFUNCGETNAME)GetProcAddress(pi->_hLib, "getName"); if (!pi->_pFuncGetName) throw generic_string(TEXT("Missing \"getName\" function")); pi->_funcName = pi->_pFuncGetName(); pi->_pBeNotified = (PBENOTIFIED)GetProcAddress(pi->_hLib, "beNotified"); if (!pi->_pBeNotified) throw generic_string(TEXT("Missing \"beNotified\" function")); pi->_pMessageProc = (PMESSAGEPROC)GetProcAddress(pi->_hLib, "messageProc"); if (!pi->_pMessageProc) throw generic_string(TEXT("Missing \"messageProc\" function")); pi->_pFuncSetInfo(_nppData); pi->_pFuncGetFuncsArray = (PFUNCGETFUNCSARRAY)GetProcAddress(pi->_hLib, "getFuncsArray"); if (!pi->_pFuncGetFuncsArray) throw generic_string(TEXT("Missing \"getFuncsArray\" function")); pi->_funcItems = pi->_pFuncGetFuncsArray(&pi->_nbFuncItem); if ((!pi->_funcItems) || (pi->_nbFuncItem <= 0)) throw generic_string(TEXT("Missing \"FuncItems\" array, or the nb of Function Item is not set correctly")); pi->_pluginMenu = ::CreateMenu(); GetLexerCountFn GetLexerCount = (GetLexerCountFn)::GetProcAddress(pi->_hLib, "GetLexerCount"); // it's a lexer plugin if (GetLexerCount) { GetLexerNameFn GetLexerName = (GetLexerNameFn)::GetProcAddress(pi->_hLib, "GetLexerName"); if (!GetLexerName) throw generic_string(TEXT("Loading GetLexerName function failed.")); GetLexerStatusTextFn GetLexerStatusText = (GetLexerStatusTextFn)::GetProcAddress(pi->_hLib, "GetLexerStatusText"); if (!GetLexerStatusText) throw generic_string(TEXT("Loading GetLexerStatusText function failed.")); // Assign a buffer for the lexer name. char lexName[MAX_EXTERNAL_LEXER_NAME_LEN]; lexName[0] = '\0'; TCHAR lexDesc[MAX_EXTERNAL_LEXER_DESC_LEN]; lexDesc[0] = '\0'; int numLexers = GetLexerCount(); ExternalLangContainer *containers[30]; WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance(); for (int x = 0; x < numLexers; ++x) { GetLexerName(x, lexName, MAX_EXTERNAL_LEXER_NAME_LEN); GetLexerStatusText(x, lexDesc, MAX_EXTERNAL_LEXER_DESC_LEN); const TCHAR *pLexerName = wmc->char2wchar(lexName, CP_ACP); if (!nppParams->isExistingExternalLangName(pLexerName) && nppParams->ExternalLangHasRoom()) containers[x] = new ExternalLangContainer(pLexerName, lexDesc); else containers[x] = NULL; } TCHAR xmlPath[MAX_PATH]; lstrcpy(xmlPath, nppParams->getNppPath().c_str()); PathAppend(xmlPath, TEXT("plugins\\Config")); PathAppend(xmlPath, pi->_moduleName.c_str()); PathRemoveExtension(xmlPath); PathAddExtension(xmlPath, TEXT(".xml")); if (!PathFileExists(xmlPath)) { lstrcpyn(xmlPath, TEXT("\0"), MAX_PATH ); lstrcpy(xmlPath, nppParams->getAppDataNppDir() ); PathAppend(xmlPath, TEXT("plugins\\Config")); PathAppend(xmlPath, pi->_moduleName.c_str()); PathRemoveExtension( xmlPath ); PathAddExtension( xmlPath, TEXT(".xml") ); if (! PathFileExists( xmlPath ) ) { throw generic_string(generic_string(xmlPath) + TEXT(" is missing.")); } } TiXmlDocument *pXmlDoc = new TiXmlDocument(xmlPath); if (!pXmlDoc->LoadFile()) { delete pXmlDoc; pXmlDoc = NULL; throw generic_string(generic_string(xmlPath) + TEXT(" failed to load.")); } for (int x = 0; x < numLexers; ++x) // postpone adding in case the xml is missing/corrupt { if (containers[x] != NULL) nppParams->addExternalLangToEnd(containers[x]); } nppParams->getExternalLexerFromXmlTree(pXmlDoc); nppParams->getExternalLexerDoc()->push_back(pXmlDoc); const char *pDllName = wmc->wchar2char(pluginFilePath, CP_ACP); ::SendMessage(_nppData._scintillaMainHandle, SCI_LOADLEXERLIBRARY, 0, reinterpret_cast<LPARAM>(pDllName)); } addInLoadedDlls(pluginFilePath, pluginFileName); _pluginInfos.push_back(pi); return static_cast<int32_t>(_pluginInfos.size() - 1); } catch (std::exception& e) { ::MessageBoxA(NULL, e.what(), "Exception", MB_OK); return -1; } catch (generic_string s) { s += TEXT("\n\n"); s += pluginFileName; s += USERMSG; if (::MessageBox(NULL, s.c_str(), pluginFilePath, MB_YESNO) == IDYES) { dll2Remove.push_back(pluginFilePath); } delete pi; return -1; } catch (...) { generic_string msg = TEXT("Failed to load"); msg += TEXT("\n\n"); msg += pluginFileName; msg += USERMSG; if (::MessageBox(NULL, msg.c_str(), pluginFilePath, MB_YESNO) == IDYES) { dll2Remove.push_back(pluginFilePath); } delete pi; return -1; } }