mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-13 08:54:38 +02:00
686 lines
21 KiB
C++
686 lines
21 KiB
C++
// This file is part of Notepad++ project
|
|
// Copyright (C)2003 Don HO <don.h@free.fr>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// Note that the GPL places important restrictions on "derived works", yet
|
|
// it does not provide a detailed definition of that term. To avoid
|
|
// misunderstandings, we consider an application to constitute a
|
|
// "derivative work" for the purpose of this license if it does any of the
|
|
// following:
|
|
// 1. Integrates source code from Notepad++.
|
|
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
|
|
// installer, such as those produced by InstallShield.
|
|
// 3. Links to a library or executes a program that does any of the above.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
#include <shlwapi.h>
|
|
#include <DbgHelp.h>
|
|
#include <algorithm>
|
|
#include "PluginsManager.h"
|
|
#include "resource.h"
|
|
|
|
using namespace std;
|
|
|
|
const TCHAR * USERMSG = TEXT(" is not compatible with the current version of Notepad++.\n\n\
|
|
Do you want to remove this plugin from the plugins directory to prevent this message from the next launch?");
|
|
|
|
#ifdef _WIN64
|
|
#define ARCH_TYPE IMAGE_FILE_MACHINE_AMD64
|
|
const TCHAR *ARCH_ERR_MSG = TEXT("Cannot load 32-bit plugin.");
|
|
#else
|
|
#define ARCH_TYPE IMAGE_FILE_MACHINE_I386
|
|
const TCHAR *ARCH_ERR_MSG = TEXT("Cannot load 64-bit plugin.");
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bool PluginsManager::unloadPlugin(int index, HWND nppHandle)
|
|
{
|
|
SCNotification scnN;
|
|
scnN.nmhdr.code = NPPN_SHUTDOWN;
|
|
scnN.nmhdr.hwndFrom = nppHandle;
|
|
scnN.nmhdr.idFrom = 0;
|
|
_pluginInfos[index]->_pBeNotified(&scnN);
|
|
|
|
//::DestroyMenu(_pluginInfos[index]->_pluginMenu);
|
|
//_pluginInfos[index]->_pluginMenu = NULL;
|
|
|
|
if (::FreeLibrary(_pluginInfos[index]->_hLib))
|
|
{
|
|
_pluginInfos[index]->_hLib = nullptr;
|
|
printStr(TEXT("we're good"));
|
|
}
|
|
else
|
|
printStr(TEXT("not ok"));
|
|
|
|
//delete _pluginInfos[index];
|
|
// printInt(index);
|
|
//vector<PluginInfo *>::iterator it = _pluginInfos.begin() + index;
|
|
//_pluginInfos.erase(it);
|
|
//printStr(TEXT("remove"));
|
|
return true;
|
|
}
|
|
|
|
static WORD GetBinaryArchitectureType(const TCHAR *filePath)
|
|
{
|
|
WORD machine_type = IMAGE_FILE_MACHINE_UNKNOWN;
|
|
HANDLE hMapping = NULL;
|
|
LPVOID addrHeader = NULL;
|
|
|
|
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
goto cleanup;
|
|
|
|
hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
|
|
if (hMapping == NULL)
|
|
goto cleanup;
|
|
|
|
addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
|
if (addrHeader == NULL)
|
|
goto cleanup; // couldn't memory map the file
|
|
|
|
PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader);
|
|
if (peHdr == NULL)
|
|
goto cleanup; // couldn't read the header
|
|
|
|
// Found the binary and architecture type
|
|
machine_type = peHdr->FileHeader.Machine;
|
|
|
|
cleanup: // release all of our handles
|
|
if (addrHeader != NULL)
|
|
UnmapViewOfFile(addrHeader);
|
|
|
|
if (hMapping != NULL)
|
|
CloseHandle(hMapping);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFile);
|
|
|
|
return machine_type;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
bool PluginsManager::loadPlugins(const TCHAR *dir)
|
|
{
|
|
if (_isDisabled)
|
|
return false;
|
|
|
|
vector<generic_string> dllNames;
|
|
vector<generic_string> dll2Remove;
|
|
NppParameters * nppParams = NppParameters::getInstance();
|
|
generic_string nppPath = nppParams->getNppPath();
|
|
generic_string pluginsFullPathFilter = (dir && dir[0])?dir:nppPath;
|
|
|
|
pluginsFullPathFilter += TEXT("\\plugins\\*.dll");
|
|
|
|
WIN32_FIND_DATA foundData;
|
|
HANDLE hFindFile = ::FindFirstFile(pluginsFullPathFilter.c_str(), &foundData);
|
|
if (hFindFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
generic_string plugins1stFullPath = (dir && dir[0])?dir:nppPath;
|
|
plugins1stFullPath += TEXT("\\plugins\\");
|
|
plugins1stFullPath += foundData.cFileName;
|
|
dllNames.push_back(plugins1stFullPath);
|
|
|
|
while (::FindNextFile(hFindFile, &foundData))
|
|
{
|
|
bool isInBlackList = nppParams->isInBlackList(foundData.cFileName);
|
|
if (!isInBlackList)
|
|
{
|
|
generic_string fullPath = (dir && dir[0])?dir:nppPath;
|
|
fullPath += TEXT("\\plugins\\");
|
|
|
|
fullPath += foundData.cFileName;
|
|
dllNames.push_back(fullPath);
|
|
}
|
|
PluginList & pl = nppParams->getPluginList();
|
|
pl.add(foundData.cFileName, isInBlackList);
|
|
}
|
|
::FindClose(hFindFile);
|
|
|
|
|
|
for (size_t i = 0, len = dllNames.size(); i < len ; ++i)
|
|
{
|
|
loadPlugin(dllNames[i].c_str(), dll2Remove);
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t j = 0, len = dll2Remove.size() ; j < len ; ++j)
|
|
::DeleteFile(dll2Remove[j].c_str());
|
|
|
|
std::sort(_pluginInfos.begin(), _pluginInfos.end(), [](const PluginInfo *a, const PluginInfo *b) { return a->_funcName < b->_funcName; });
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PluginsManager::loadPluginsV2(const TCHAR* dir)
|
|
{
|
|
if (_isDisabled || !dir || !dir[0])
|
|
return false;
|
|
|
|
NppParameters * nppParams = NppParameters::getInstance();
|
|
|
|
vector<generic_string> dllNames;
|
|
vector<generic_string> dll2Remove;
|
|
|
|
generic_string pluginsFolderFilter = dir;
|
|
PathAppend(pluginsFolderFilter, TEXT("*.*"));
|
|
|
|
WIN32_FIND_DATA foundData;
|
|
HANDLE hFindFolder = ::FindFirstFile(pluginsFolderFilter.c_str(), &foundData);
|
|
HANDLE hFindDll = INVALID_HANDLE_VALUE;
|
|
if (hFindFolder != INVALID_HANDLE_VALUE && (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
generic_string pluginsFullPathFilter = dir;
|
|
PathAppend(pluginsFullPathFilter, foundData.cFileName);
|
|
generic_string pluginsFolderPath = pluginsFullPathFilter;
|
|
PathAppend(pluginsFullPathFilter, TEXT("*.dll"));
|
|
|
|
hFindDll = ::FindFirstFile(pluginsFullPathFilter.c_str(), &foundData);
|
|
if (hFindDll != INVALID_HANDLE_VALUE && !(foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
generic_string pluginsFullPath = pluginsFolderPath;
|
|
PathAppend(pluginsFullPath, foundData.cFileName);
|
|
dllNames.push_back(pluginsFullPath);
|
|
|
|
PluginList & pl = nppParams->getPluginList();
|
|
pl.add(foundData.cFileName, false);
|
|
}
|
|
|
|
while (::FindNextFile(hFindFolder, &foundData))
|
|
{
|
|
|
|
generic_string pluginsFullPathFilter2 = dir;
|
|
PathAppend(pluginsFullPathFilter2, foundData.cFileName);
|
|
generic_string pluginsFolderPath2 = pluginsFullPathFilter2;
|
|
PathAppend(pluginsFullPathFilter2, TEXT("*.dll"));
|
|
|
|
hFindDll = ::FindFirstFile(pluginsFullPathFilter2.c_str(), &foundData);
|
|
if (hFindDll != INVALID_HANDLE_VALUE && !(foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
generic_string pluginsFullPath2 = pluginsFolderPath2;
|
|
PathAppend(pluginsFullPath2, foundData.cFileName);
|
|
dllNames.push_back(pluginsFullPath2);
|
|
|
|
PluginList & pl = nppParams->getPluginList();
|
|
pl.add(foundData.cFileName, false);
|
|
}
|
|
}
|
|
|
|
}
|
|
::FindClose(hFindFolder);
|
|
::FindClose(hFindDll);
|
|
|
|
|
|
for (size_t i = 0, len = dllNames.size(); i < len; ++i)
|
|
{
|
|
loadPlugin(dllNames[i].c_str(), dll2Remove);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// return true if cmdID found and its shortcut is enable
|
|
// false otherwise
|
|
bool PluginsManager::getShortcutByCmdID(int cmdID, ShortcutKey *sk)
|
|
{
|
|
if (cmdID == 0 || !sk)
|
|
return false;
|
|
|
|
const vector<PluginCmdShortcut> & pluginCmdSCList = (NppParameters::getInstance())->getPluginCommandList();
|
|
|
|
for (size_t i = 0, len = pluginCmdSCList.size(); i < len ; ++i)
|
|
{
|
|
if (pluginCmdSCList[i].getID() == (unsigned long)cmdID)
|
|
{
|
|
const KeyCombo & kc = pluginCmdSCList[i].getKeyCombo();
|
|
if (kc._key == 0x00)
|
|
return false;
|
|
|
|
sk->_isAlt = kc._isAlt;
|
|
sk->_isCtrl = kc._isCtrl;
|
|
sk->_isShift = kc._isShift;
|
|
sk->_key = kc._key;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void PluginsManager::addInMenuFromPMIndex(int i)
|
|
{
|
|
vector<PluginCmdShortcut> & pluginCmdSCList = (NppParameters::getInstance())->getPluginCommandList();
|
|
::InsertMenu(_hPluginsMenu, i, MF_BYPOSITION | MF_POPUP, (UINT_PTR)_pluginInfos[i]->_pluginMenu, _pluginInfos[i]->_funcName.c_str());
|
|
|
|
unsigned short j = 0;
|
|
for ( ; j < _pluginInfos[i]->_nbFuncItem ; ++j)
|
|
{
|
|
if (_pluginInfos[i]->_funcItems[j]._pFunc == NULL)
|
|
{
|
|
::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
|
|
continue;
|
|
}
|
|
|
|
_pluginsCommands.push_back(PluginCommand(_pluginInfos[i]->_moduleName.c_str(), j, _pluginInfos[i]->_funcItems[j]._pFunc));
|
|
|
|
int cmdID = ID_PLUGINS_CMD + static_cast<int32_t>(_pluginsCommands.size() - 1);
|
|
_pluginInfos[i]->_funcItems[j]._cmdID = cmdID;
|
|
generic_string itemName = _pluginInfos[i]->_funcItems[j]._itemName;
|
|
|
|
if (_pluginInfos[i]->_funcItems[j]._pShKey)
|
|
{
|
|
ShortcutKey & sKey = *(_pluginInfos[i]->_funcItems[j]._pShKey);
|
|
PluginCmdShortcut pcs(Shortcut(itemName.c_str(), sKey._isCtrl, sKey._isAlt, sKey._isShift, sKey._key), cmdID, _pluginInfos[i]->_moduleName.c_str(), j);
|
|
pluginCmdSCList.push_back(pcs);
|
|
itemName += TEXT("\t");
|
|
itemName += pcs.toString();
|
|
}
|
|
else
|
|
{ //no ShortcutKey is provided, add an disabled shortcut (so it can still be mapped, Paramaters class can still index any changes and the toolbar wont funk out
|
|
Shortcut sc(itemName.c_str(), false, false, false, 0x00);
|
|
PluginCmdShortcut pcs(sc, cmdID, _pluginInfos[i]->_moduleName.c_str(), j); //VK_NULL and everything disabled, the menu name is left alone
|
|
pluginCmdSCList.push_back(pcs);
|
|
}
|
|
::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION, cmdID, itemName.c_str());
|
|
|
|
if (_pluginInfos[i]->_funcItems[j]._init2Check)
|
|
::CheckMenuItem(_hPluginsMenu, cmdID, MF_BYCOMMAND | MF_CHECKED);
|
|
}
|
|
/*UNLOAD
|
|
::InsertMenu(_pluginInfos[i]->_pluginMenu, j++, MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
|
|
::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION, ID_PLUGINS_REMOVING + i, TEXT("Remove this plugin"));
|
|
*/
|
|
}
|
|
|
|
HMENU PluginsManager::setMenu(HMENU hMenu, const TCHAR *menuName)
|
|
{
|
|
if (hasPlugins())
|
|
{
|
|
const TCHAR *nom_menu = (menuName && menuName[0])?menuName:TEXT("&Plugins");
|
|
|
|
if (!_hPluginsMenu)
|
|
{
|
|
_hPluginsMenu = ::CreateMenu();
|
|
::InsertMenu(hMenu, MENUINDEX_PLUGINS, MF_BYPOSITION | MF_POPUP, (UINT_PTR)_hPluginsMenu, nom_menu);
|
|
}
|
|
|
|
for (size_t i = 0, len = _pluginInfos.size() ; i < len ; ++i)
|
|
{
|
|
addInMenuFromPMIndex(static_cast<int32_t>(i));
|
|
}
|
|
return _hPluginsMenu;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void PluginsManager::runPluginCommand(size_t i)
|
|
{
|
|
if (i < _pluginsCommands.size())
|
|
{
|
|
if (_pluginsCommands[i]._pFunc != NULL)
|
|
{
|
|
try
|
|
{
|
|
_pluginsCommands[i]._pFunc();
|
|
}
|
|
catch (std::exception e)
|
|
{
|
|
::MessageBoxA(NULL, e.what(), "PluginsManager::runPluginCommand Exception", MB_OK);
|
|
}
|
|
catch (...)
|
|
{
|
|
TCHAR funcInfo[128];
|
|
generic_sprintf(funcInfo, TEXT("runPluginCommand(size_t i : %d)"), i);
|
|
pluginCrashAlert(_pluginsCommands[i]._pluginName.c_str(), funcInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PluginsManager::runPluginCommand(const TCHAR *pluginName, int commandID)
|
|
{
|
|
for (size_t i = 0, len = _pluginsCommands.size() ; i < len ; ++i)
|
|
{
|
|
if (!generic_stricmp(_pluginsCommands[i]._pluginName.c_str(), pluginName))
|
|
{
|
|
if (_pluginsCommands[i]._funcID == commandID)
|
|
{
|
|
try
|
|
{
|
|
_pluginsCommands[i]._pFunc();
|
|
}
|
|
catch (std::exception e)
|
|
{
|
|
::MessageBoxA(NULL, e.what(), "Exception", MB_OK);
|
|
}
|
|
catch (...)
|
|
{
|
|
TCHAR funcInfo[128];
|
|
generic_sprintf(funcInfo, TEXT("runPluginCommand(const TCHAR *pluginName : %s, int commandID : %d)"), pluginName, commandID);
|
|
pluginCrashAlert(_pluginsCommands[i]._pluginName.c_str(), funcInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PluginsManager::notify(const SCNotification *notification)
|
|
{
|
|
for (size_t i = 0, len = _pluginInfos.size() ; i < len ; ++i)
|
|
{
|
|
if (_pluginInfos[i]->_hLib)
|
|
{
|
|
// To avoid the plugin change the data in SCNotification
|
|
// Each notification to pass to a plugin is a copy of SCNotification instance
|
|
SCNotification scNotif = *notification;
|
|
try
|
|
{
|
|
_pluginInfos[i]->_pBeNotified(&scNotif);
|
|
}
|
|
catch (std::exception e)
|
|
{
|
|
::MessageBoxA(NULL, e.what(), "Exception", MB_OK);
|
|
}
|
|
catch (...)
|
|
{
|
|
TCHAR funcInfo[256];
|
|
generic_sprintf(funcInfo, TEXT("notify(SCNotification *notification) : \r notification->nmhdr.code == %d\r notification->nmhdr.hwndFrom == %p\r notification->nmhdr.idFrom == %d"),\
|
|
scNotif.nmhdr.code, scNotif.nmhdr.hwndFrom, scNotif.nmhdr.idFrom);
|
|
pluginCrashAlert(_pluginInfos[i]->_moduleName.c_str(), funcInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PluginsManager::relayNppMessages(UINT Message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
for (size_t i = 0, len = _pluginInfos.size(); i < len ; ++i)
|
|
{
|
|
if (_pluginInfos[i]->_hLib)
|
|
{
|
|
try
|
|
{
|
|
_pluginInfos[i]->_pMessageProc(Message, wParam, lParam);
|
|
}
|
|
catch (std::exception e)
|
|
{
|
|
::MessageBoxA(NULL, e.what(), "Exception", MB_OK);
|
|
}
|
|
catch (...)
|
|
{
|
|
TCHAR funcInfo[128];
|
|
generic_sprintf(funcInfo, TEXT("relayNppMessages(UINT Message : %d, WPARAM wParam : %d, LPARAM lParam : %d)"), Message, wParam, lParam);
|
|
pluginCrashAlert(_pluginInfos[i]->_moduleName.c_str(), funcInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool PluginsManager::relayPluginMessages(UINT Message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
const TCHAR * moduleName = (const TCHAR *)wParam;
|
|
if (!moduleName || !moduleName[0] || !lParam)
|
|
return false;
|
|
|
|
for (size_t i = 0, len = _pluginInfos.size() ; i < len ; ++i)
|
|
{
|
|
if (_pluginInfos[i]->_moduleName == moduleName)
|
|
{
|
|
if (_pluginInfos[i]->_hLib)
|
|
{
|
|
try
|
|
{
|
|
_pluginInfos[i]->_pMessageProc(Message, wParam, lParam);
|
|
}
|
|
catch (std::exception e)
|
|
{
|
|
::MessageBoxA(NULL, e.what(), "Exception", MB_OK);
|
|
}
|
|
catch (...)
|
|
{
|
|
TCHAR funcInfo[128];
|
|
generic_sprintf(funcInfo, TEXT("relayPluginMessages(UINT Message : %d, WPARAM wParam : %d, LPARAM lParam : %d)"), Message, wParam, lParam);
|
|
pluginCrashAlert(_pluginInfos[i]->_moduleName.c_str(), funcInfo);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool PluginsManager::allocateCmdID(int numberRequired, int *start)
|
|
{
|
|
bool retVal = true;
|
|
|
|
*start = _dynamicIDAlloc.allocate(numberRequired);
|
|
|
|
if (-1 == *start)
|
|
{
|
|
*start = 0;
|
|
retVal = false;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
bool PluginsManager::allocateMarker(int numberRequired, int *start)
|
|
{
|
|
bool retVal = true;
|
|
*start = _markerAlloc.allocate(numberRequired);
|
|
if (-1 == *start)
|
|
{
|
|
*start = 0;
|
|
retVal = false;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
generic_string PluginsManager::getLoadedPluginNames() const
|
|
{
|
|
generic_string pluginPaths;
|
|
for (size_t i = 0; i < _loadedDlls.size(); ++i)
|
|
{
|
|
pluginPaths += _loadedDlls[i]._fileName;
|
|
pluginPaths += TEXT(" ");
|
|
}
|
|
return pluginPaths;
|
|
}
|
|
|