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.