First menu item unexpectedly being called on startup
-
@ThosRTanner I’ve tested ‘Linter’ with my N++ installation, and I didn’t experience this issue: no window opened before the main N++ window. I can only offer some suggestions. Have you tried deleting the N++ config.xml?
Additionally, I would suggest updating to the 8.5.7 version. -
This post is deleted! -
I took latest version of notepad++, built master branch of linter (in debug mode) and get the same problem.
The call is definitely from notepad++ - not sure where though as I don’t have debug symbols for it.
-
@ThosRTanner said in First menu item unexpectedly being called on startup:
I took latest version of notepad++, built master branch of linter (in debug mode) and get the same problem.
The call is definitely from notepad++ - not sure where though as I don’t have debug symbols for it.
Forgive me if this is a dumb question, but… does the same thing happen with the release DLL from the repository? (It looks like the latest release is up to date with master, so there should be no difference.)
If it happens with the release DLL, it’s probably worth raising an issue in that repository. If it doesn’t, the next thing I’d try is building release mode from source, to see if the problem is specific to debug build.
-
@Coises i tried removing and then installing via plugins admin and it is still happening for me.but @Thomas-Knoefel seems to have it working as normal from his post earlier.
It is very odd. or possibly i have a conflicting plugin. i’d really like to see the call stack explaining where this call is coming from.
-
Well, that was enlightening - sort of.
I deleted config.xml from the notepad++ appdata directory and everything started working again. Of course. all the settings make everything dreadful. So there’s clearly something in the config that causes this. It’d be nice to know what.
Later:
It appears to be the result of having created a docking window somehow. I deleted the docking window info in the config file + 3 others (one called dummy, 2 called notepad++ internal) and it’s fine.
-
On start-up, the data in
config.xml
is marshaled into an instance of thePluginDlgDockingInfo
structure, which is used to recreate any plugin dialog windows that were left open in a previous session. To make the dialogs appear, the application executes the associated function, which is looked up by a numeric index that is parsed from theid
attribute of the XML node at/NotepadPlus/GUIConfigs/GUIConfig[@name="DockingManager"]/PluginDlg[@pluginName="PLUGIN_MODULE_NAME.dll"]
:if (pdi._isVisible && showPanel) { if (isInternalFunc) _internalFuncIDs.push_back(pdi._internalID); else _pluginsManager.runPluginCommand(pdi._name.c_str(), pdi._internalID); }
If
pdi._name
refers to any real module in the load path, andpdi._internalID
is any real index defined in the plugin source code, the function will execute, as long as theisVisible
attribute is"yes"
inconfig.xml
. This also means that a craftedconfig.xml
can make Notepad++ execute potentially any plugin function at start-up. Keep in mind that the plugin must be already in the load path, and the menu ID of the plugin function must be valid and known beforehand.Proof of Concept
- Build a simple plugin from this code:
#define UNICODE #include <windows.h> #define PLUGIN_CMD_ID 0ULL #define NB_PLUGIN_FUNCS 1ULL #define MENU_TITLE_LENGTH 64ULL #define PLUGIN_FUNC extern "C" __declspec(dllexport) typedef void(__cdecl *PFUNCPLUGINCMD)(void); struct NppData { HWND _nppHandle = nullptr; HWND _scintillaMainHandle = nullptr; HWND _scintillaSecondHandle = nullptr; }; struct ShortcutKey { bool _isCtrl = false; bool _isAlt = false; bool _isShift = false; UCHAR _key = 0; }; struct FuncItem { TCHAR _itemName[MENU_TITLE_LENGTH] = { 0 }; PFUNCPLUGINCMD _pFunc = nullptr; int _cmdID = 0; bool _init2Check = false; ShortcutKey *_pShKey = nullptr; }; static FuncItem funcItem[NB_PLUGIN_FUNCS]; static NppData nppData; void surprise(void) { ::MessageBoxW(nppData._nppHandle, L"Surprise!", L"Message from PoC Plugin", MB_OK); } PLUGIN_FUNC void setInfo(NppData data) { nppData = data; lstrcpy(funcItem[PLUGIN_CMD_ID]._itemName, L"Surprise me!"); funcItem[PLUGIN_CMD_ID]._pFunc = surprise; funcItem[PLUGIN_CMD_ID]._init2Check = false; funcItem[PLUGIN_CMD_ID]._pShKey = nullptr; } PLUGIN_FUNC FuncItem *getFuncsArray(int *nbF) { *nbF = (int)NB_PLUGIN_FUNCS; return funcItem; } PLUGIN_FUNC const TCHAR *getName(void) { return L"PoC Npp Plugin"; } PLUGIN_FUNC LRESULT messageProc(UINT /*na*/, WPARAM /*na*/, LPARAM /*na*/) { return 0; } PLUGIN_FUNC BOOL isUnicode(void) { return TRUE; } PLUGIN_FUNC void beNotified(void *) {} BOOL APIENTRY DllMain(HANDLE /*na*/, DWORD /*na*/, LPVOID /*na*/) { return TRUE; }
-
Save the compiled module as
poc_plugin.dll
and copy it to the correct plugin path for the given N++ installation. -
Open the correct
config.xml
configuration file for the given N++ installation. -
Edit
config.xml
by creating the following node under the path/NotepadPlus/GUIConfigs/GUIConfig[@name="DockingManager"]
:
<GUIConfig name="DockingManager" leftWidth="200" rightWidth="200" topHeight="200" bottomHeight="200"> <PluginDlg pluginName="poc_plugin.dll" id="0" curr="1" prev="-1" isVisible="yes" /> <!-- . . . --> </GUIConfig>
When Notepad++ starts, the
surprise()
function will display a message box. This works in any N++ version, including 8.5.7. -
@rdipardo Thanks. That’s helpful to have confirmed. One of those things that should really be in the ‘how to write your own plugin’ documentation or the C++ template doc
-
@ThosRTanner said in First menu item unexpectedly being called on startup:
One of those things that should really be in the ‘how to write your own plugin’ documentation or the C++ template doc
That would be appropriate — if what I described was a deliberate design. My impression is that it’s just an accident of a short-sighted implementation. This may be the first time anyone has ever looked into it. Fortunately it’s no more exploitable than dropping a comprised DLL into the load path (a precondition to making it work). Otherwise it would be irresponsible to publicly document it.
Even the supposed benefit of relaunching dialogs with saved co-ordinates is questionable, given how many times the “Folder as Workspace” or “Find” dialog seems to go missing because the dimensions became negative through naïve rounding or integer overflow:
-
@rdipardo it’s not so much the ability to break/abuse it, it’s the fact that there is a correlation between the order of entries in your plugin menu and the docking dialogue(s) you can open from your plugin.