Menus and shortcuts

OllyDbg offers flexible and powerful system of tightly interconnected menus and shortcuts. In fact, to define a shortcut, you must create the corresponding menu item.

Menu is described by an array of t_menu structures. Each element 
represents menu item or points to submenu. Last element should be zero or forward to another menu. The depth of nesting and total number of elements are limited only by the Windows API.

There is a menu function of type MENUFUNC associated with each menu item:

typedef int MENUFUNC(struct t_table *ptable,wchar_t *name,ulong index,int mode);

Menu function is called twice. First time (mode=MENU_VERIFY) OllyDbg asks menu function to verify whether corresponding menu item applies or not. If necessary, menu function may change menu text (parameter name, up to TEXTLEN UNICODE characters). It must return one of the following codes:

MENU_ABSENT - menu item does not apply and will not appear the menu
MENU_NORMAL - menu item appears in the menu
MENU_CHECKED - menu item appears in the menu and has attached checkmark
MENU_CHKPARENT - menu item appears in the menu and has attached checkmark. Additionally, OllyDbg attaches checkmark to the parent item in the menu on the previous level. This feature does not work in the main menu
MENU_SHORTCUT - menu item is a pure shortcut. It does not appear in the menu but is active and participates in the search for keyboard shortcuts
MENU_GRAYED - item is present in the menu but disabled. This style is not compatible with OllyDbg's look-and-feel, use it only if absolutely necessary due to the menu logic.

When menu item is selected (by mouseclick or using keyboard shortcut),
OllyDbg suspends all threads of the debugged application and calls menu function for the second time (mode=MENU_EXECUTE). This time menu text is undefined. Function must make all necessary actions and return one of the following codes:

MENU_REDRAW - menu action has global impact, all OllyDbg windows must be updated. OllyDbg broadcasts WM_USER_CHGALL
MENU_NOREDRAW - no redrawing is necessary

Afterwards OllyDbg resumes the application. If processing is lengthy and application should continue execution, use Resumeallthreads() at the entry to the MENU_EXECUTE block and Suspendallthreads() on exit. Note that MENU_ABSENT and MENU_NOREDRAW are interchangeable.

It is possible that the state of the running application will change between the first and the second call to menu function. If necessary, menu function should re-check it when called for the second time.

Parameter index is taken from menu descriptor. It allows to use the same menu function with several menu items.

Several combinations of the first characters in t_menu.name are not displayed and have special meaning:

Vertical line (|)  - item will be preceeded by separator line, but only if previous menu item is not a separator. Separator will be inserted even if menu function returns MENU_ABSENT
Double vertical line (||) - item will be preceeded by separator line ("forced separator"). Separator will be inserted even if menu function returns MENU_ABSENT
Exclamation mark (!)  - menu function is an initializator. It must be first in the menu. Initializator is called only during MENU_VERIFY phase; its purpose is to set global variables for other menu functions
Greater-than sign (>) - follower to the standard menu (">STANDARD", ">FULLCOPY" or ">APPEARANCE"), see t_menu for details


Shortcuts

Shorcuts are part of the menu. When user types a shortcut, OllyDbg makes precisely the same steps as if this item is selected from the menu. This includes call to the initialization function, if such function is defined.

Currently there is no way for plugins to determine whether shortcut is already in use or not. Also it's not possible to change plugin shortcuts in the Shortcut editor. However, plugins are free to use predefined local shortcuts (listed as constants K_xxx in the plugin.h), like K_EDIT, K_SEARCHAGAIN or K_BREAK.


Menu embedding

Plugins may embed their own menus into many standard OllyDbg windows, including main menu. When user right clicks in the table or presses a shortcut key, OllyDbg calls ODBG2_Pluginmenu() and passes text string that determines type of the window (PWM_MAIN if this is the main OllyDbg menu). All possible strings are listed in the plugin.h as constants PWM_xxx:

PWM_ATTACH - list of processes in Attach window
PWM_BPHARD - hardware breakpoints
PWM_BPMEM - memory breakpoints
PWM_BPOINT - INT3 breakpoints
PWM_DISASM - CPU Disassembler pane
PWM_DUMP - all dump windows except CPU disassembler and CPU stack
PWM_INFO - CPU Info pane
PWM_LOG - Log window
PWM_MAIN - main OllyDbg menu
PWM_MEMORY - Memory window
PWM_MODULES - Modules window
PWM_NAMELIST - list of names (labels)
PWM_PATCHES - list of patches
PWM_PROFILE - Profile window
PWM_REGISTERS - registers, including CPU pane
PWM_SEARCH - tabs in Search window
PWM_SOURCE - source code window
PWM_SRCLIST - list of source files
PWM_STACK - CPU Stack pane
PWM_THREADS - Threads window
PWM_TRACE - Run trace window
PWM_WATCH - watches
PWM_WINDOWS - list of windows

To display menu, plugin must return pointer to the menu (array of t_menu structures with zero last item). If there is no menu, plugin should return NULL. If menu consists of a single main item, it will be displayed directly. Otherwise, OllyDbg will create main item named by plugin and place returned menu as a submenu of this item.


Example

Suppose that you have the following menu:

t_menu custommenu[] = {
  { L"Item 1",  L"This is item 1",
       KK_DIRECT|KK_CTRL|'A', Menufunction, NULL, 1 },
  { L"|Item 2", L"This is item 2",                     // Separator
       KK_DIRECT|KK_CTRL|'B', Menufunction, NULL, 2 },
  { L"Item 3",  L"This is item 3",
       KK_DIRECT|KK_CTRL|'C', Menufunction, NULL, 3 },
  { L"Item 4",  L"This is item 4",
       KK_DIRECT|KK_CTRL|'D', Menufunction, NULL, 4 },
  { L"|>STANDARD", L"",                                // Forwarder
       K_NONE, NULL, NULL, 0
  }
}

and that Menufunction() returns MENU_NORMAL, MENU_ABSENT, MENU_NORMAL and MENU_CHECKED when called with index=1, 2, 3 and 4, correspondingly. The menu will look as on the following picture:

    Custom menu

See also here



See also:
MENUFUNC, t_menu, t_table