Adding A Plugin Menu

We will first be adding a popup menu to notepad's main menu; this new popup menu will hold the various options for each plugin and will be created at run time via an imported DLL function. Note that plugins will be able to add and modify options in other popup menus as well.

Tools Used

[~] Resource Hacker - For viewing and modifying menu items and properties.
[~] Win32.hlp - Reference for Win32 API functions.
[~] OllyDbg - Debugger.
[~] Dev-C++ - For compiling DLL and EXE files.
[~] WinDowse - For viewing window information (optional).

Statically Changing The Main Menu

ResHack is a utility which allows you to view and modify a program's resources, including menu information. Open up notepad in ResHack and click on 'Menu -> 1 -> 1033':



Notice that it displays each popup menu, its menu items and their ID numbers. It is important to note the ID numbers because our plugin menu items shouldn't have the same ID numbers as the pre-existing options. We can permanently add a plugin menu by adding something like:
POPUP "&Plugins"
{
MENUITEM "&Test", 2001
}



However, this doesn't allow us to dynamically add new plugin options to notepad.

Dynamically Changing The Menu

The windows API provides several functions to add and manipulate a menu's contents such as CreatePopupMenu, AppendMenu, InsertMenu and SetMenu. In order to use these functions, we need to get a handle to the menu we want to manipulate; the following C code creates a program which will add our menu to an instance of notepad which is already running:
***************Begin Code******************
#include <windows.h>
int main()
{
//retrieve the window handle based on notepad's title text
HWND handle=FindWindow(0,"Untitled - Notepad");
//retrieve the menu handle using the window handle
HMENU menu=GetMenu(handle);
//create a new popup menu
HMENU submenu=CreatePopupMenu();
//add the popup menu to notepad's menu bar
InsertMenu(menu,4,MF_BYPOSITION | MF_POPUP,(UINT)submenu,"&Plugins");
//add submenus to the popup menu
AppendMenu(submenu, MF_STRING, 1, "&Test");
AppendMenu(submenu, MF_STRING, 2, "Test &2");
//apply the changes
SetMenu(handle,menu);
return 0;
}
***************End Code******************
We use FindWindow to obtain a handle to notepad's window, GetMenu to obtain a handle to the window's menu. We then create a popup menu, insert it between 'View' and 'Help' (note that we used a position of 4 for InsertMenu to place it between the View and Help popup menus), append two options to the popup menu, and then save our changes via SetMenu. Running this program with an instance of notepad already open results in the addition of a 'Plugins' pop-up menu being added to notepad's menu bar:



However, this method is still unsatisfactory because if the window text is different, or if there are multiple instances of notepad running simultaneously, FindWindow may not retrieve the proper window handle. What we need to do is place this code in an exportable DLL function, then make notepad call that function, passing the window handle to the function.

Finding the Window Handle

First, we need to find where notepad's main window handle is stored so we can pass it to our DLL function. Open notepad in Olly, 'Right Click -> Search for -> All intermodular calls', and set a break point on all calls to CreateWindowExW (there are only three) and run notepad. Olly will break twice; the first time is when the main window is created (this is the one we are looking for), and the second time is when the edit window is created. There are several ways to determine which call is creating which window:

1) Notepad is a simple program, so most likely the first window to be created will be the main window.
2) Looking at the class names passed to CreateWindowExW, the first one is "Notepad" and the second is "Edit".
3) Other API calls in notepad (such as GetMenu) which require the main window handle are passed the handle which is returned by the first call to CreateWindowExW.
4) By using a program such as WinDowse, you can see that there are two windows created: the primary window ("Notepad") and a child window ("Edit").

Looking three instructions below the first call to CreateWindowExW, we see that the handle is stored in two different memory locations (01009830 and 0100A4A4):



Looking elsewhere at Olly's code, the GetMenu API calls are passed the value at address 01009830, so we will pass the handle stored at that address to our function.

The DLL Function

The following code will create an exportable DLL function, NotePlug, which produces our desired results. If you are unfamiliar with DLLs or exportable functions, see my DLL tutorial page. Note that this code is created for Dev-C++, so you may need to change the names of dll.h and DLLIMPORT to suite your compiler:
#include "dll.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

DLLIMPORT int NotePlug(HWND handle)
{
HMENU menu=GetMenu(handle);
HMENU submenu=CreatePopupMenu();
InsertMenu(menu,4,MF_BYPOSITION | MF_POPUP,(UINT)submenu,"&Plugins");
AppendMenu(submenu, MF_STRING, 2001, "&Test");
AppendMenu(submenu, MF_STRING, 2002, "Test &2");
SetMenu(handle,menu);
return 0;
} DLLIMPORT int NotePadCmd(HWND hwnd,int msg,int unknown) { return 0; }

Compile this code as note_plug.dll; this will be our primary DLL file which will implement all the necessary features to support plugin modules. The NotePlug function will be later modified so that the addition of submenus via AppendMenu is conducted by each individual plugin, however this serves its purpose for the time being. The purpose of the NotePadCmd function will be evident in the next tutorial section.

Conclusion

We can now add menu options to notepad's menu bar, allowing the user to interact with any additional functionality via plugin modules. Next we need to modify notepad's assembly code to call our NotePlug function from notepad each time it is run.

Copyright ©2006 craigheffner.com