DRAWFUNC

OllyDbg Plugin API

DRAWFUNC

Type of pointer to callback function that prepares data for painting in table windows. Given line and column, function must prepare ASCII or UNICODE string that will be displayed on their intersection. If string contains graphical symbols, or when it uses different colors, function must fill mask with individual graphical attributes for each character. Function returns number of characters (UNICODE: wide characters) in prepared string. String is not necessarily null-terminated.

For standard table windows (bit TABLE_USERDEF in t_table.mode is cleared), parameter ps points directly to the element of sorted data.

For user-defined table window (TABLE_USERDEF is set), ps is a pointer to the structure t_table that describes this window. Before OllyDbg calls DRAWFUNC, it sets t_table.offset to the index of currently processed line in table window (topmost displayed line has index 0) and sets table.data.n to the total number of completely or partially visible lines. Drawing function is called once for every crossing of visible row with visible column. Individual decoding of each item may impose severe overhead and make drawing slow. So OllyDbg sets table.data.net only once at the beginning of the sequence. Drawing function may use it as a command to prepare the entire block of requested data in some static buffer and then reset n to 0. It is guaranteed that sequence of calls to DRAWFUNC will not be interrupted by call with different t_table.

To implement scrolling in custom window, its window procedure must process several custom messages.

typedef int DRAWFUNC(char *s,char *mask,int *select,t_sortheader *ps,int column);

Parameters:

s - pointer to buffer for output string of size at least 2*TEXTLEN characters. Length of returned string must not exceed TEXTLEN ASCII or UNICODE characters. If function returns UNICODE string, it must set bit DRAW_UNICODE in *select. String is not necessarily null-terminated;

mask - array of individual graphical attributes for every character in output string. OllyDbg uses mask only if DRAWFUNC sets bit DRAW_MASK in *select. Each byte of the mask is a combination of bits DRAW_xxx, see detailed description below;

select - pointer to graphical attributes common to all characters in output string. *select is a combination of bits DRAW_xxx, see detailed description below;

ps - for standard table windows (without attribute TABLE_USERDEF), pointer to the element of sorted data to be decoded. For custom (user-defined) windows, cast ps to pointer to structure t_table that describes custom window, see detailed description above;

column - zero-based index of the processed column. Note that if column is not visible at all, OllyDbg does not call DRAWFUNC.

Meaning of bits DRAW_xxx

Mask and select consist of combination of bits DRAW_xxx. They are summarized in the table below. Note that bits which are not allowed in the mask may have values that don't fit into byte:

Bit allowed in: select mask  
DRAW_NORMAL * * normal plain text
DRAW_GRAY * * grayed text
DRAW_HILITE * * highlighted text
DRAW_UL   * underlined text
DRAW_SELECT * * selected background
DRAW_EIP * * inverted normal text/background
DRAW_BREAK * * breakpoint background
DRAW_GRAPH   * graphical symbol, see below
DRAW_DIRECT   * direct text and background colour indices
DRAW_MASK *   use individual mask attributes for each symbol
DRAW_EXTSEL *   extend selection from last mask till end of column
DRAW_UNICODE *   text is in UNICODE
DRAW_TOP *   draw top half of the text shifted 1/2 row down
DRAW_BOTTOM *   draw bottom half of the text shifted 1/2 row up

If entire string has same highlight and selection attributes, don't set DRAW_MASK. OllyDbg ignores mask and uses only attributes from *select. Attributes DRAW_NORMAL, DRAW_GRAY and DRAW_HILITE are mutually exclusive. You cannot set DRAW_EIP together with either DRAW_SELECT or DRAW_BREAK. If bits DRAW_BREAK and DRAW_SELECT are set simultaneously, background corresponds to that of conditional breakpoint.

To highlight and select each character individually, set DRAW_MASK in *select and fill in the mask with combination of bits describing corresponding character in output string. Bit DRAW_HILITE in the mask has priority over *select. Bits DRAW_GRAY, DRAW_SELECT, DRAW_EIP and DRAW_BREAK in *select have priority over remaining bits in mask. Mask also allows to draw pseudographical characters. If DRAW_GRAPH bit is set, character is decoded in a special way:

Symbol Char Meaning
D_SPACE 'N' space
D_SEP ' ' thin vertical separating line
D_POINT '.' point
D_BEGIN 'B' begin of procedure, loop or stack scope
D_BODY 'I' body of procedure, loop or stack scope
D_ENTRY 'J' loop entry point
D_LEAF 'K' Intermediate leaf on a tree
D_END 'E' end of procedure, loop or stack scope
D_SINGLE 'S' scope consisting of single line
D_ENDBEG 'T' begin and end of stack scope
D_JMPUP 'U' small thin arrow upstairs (jump upstairs)
D_JMPOUT '<' short dash (jump to different module)
D_JMPDN 'D' small thin arrow downstairs (jump downstairs)
D_PATHUP 'u' start of highlighted jump path upstairs
D_GRAYUP 'v' start of grayed jump path upstairs
D_PATHDN 'd' start of highlighted jump path downstairs
D_GRAYDN 'e' start of grayed jump path downstairs
D_PATH 'i' body of highlighted jump path
D_GRAYPATH 'j' body of grayed jump path
D_PATHUPEND 'r' end of highlighted jump path upstairs
D_GRAYUPEND 's' end of grayed jump path upstairs
D_PATHDNEND 'f' end of highlighted jump path downstairs
D_GRAYDNEND 'g' end of grayed jump path downstairs
D_PATHPTUP 'a' jump entry upstairs (highlighted)
D_PATHPTDN 'h' jump entry downstairs (highlighted)
D_PATHEND 'z' two-sided end of jump (highlighted)
D_SWTOP 't' start of switch
D_SWBODY 'b' switch body
D_CASE 'c' intermediate switch case
D_LASTCASE 'l' last switch case

Any other character is displayed as space.

OllyDbg allows direct setting of foreground and background colour for each character in the string. To use this feature, allow mask in *select and fill corresponding mask bytes with the following data:

DRAW_DIRECT ORed with background colour ORed with foreground colour,

where backgrond colour is one of BKxxx constants defined in plugin.h (BKTRANSP for default background), and foreground colour is any colour in range 0..15. Colours 16 to 19 are not supported. You can't combine DRAW_DIRECT with any other DRAW_xxx flags in the mask.

If bit BAR_SHIFTSEL is set for the actual column, background will be shifted 1/2 character to the left. This is a nice trick allowing better highlighting. In this case assure that last highlighted character is a space.

OllyDbg's Register window is also a custom table window. Please have a close look on EIP and EFL: they are shifted down by 1/2 line! How is it possible? Well, here I use another trick: I draw these lines twice, first time with bit DRAW_TOP and second time with bit DRAW_BOTTOM. However, this trick is relatively time-consuming, and mouse will select within each complete line. I do not recommended it for the future.