Tables may be grouped together in one window as resizable panes or frames (like CPU), or as the tab collection where only one table is visible at once (Search). Both are described by the structure t_frame.
Frame windows
The layout of the frame window is defined by the linked tree of structures of type t_block:
typedef struct t_block { // Block descriptor
int index; // Index of pos record in the .ini file
int type; // One of BLK_xxx
int percent; // Percent of block in left/top subblock
int offset; // Offset of dividing line, pixels
struct t_block *blk1; // Top/left subblock, NULL if leaf
int minp1; // Min size of 1st subblock, pixels
int maxc1; // Max size of 1st subblock, chars, or 0
struct t_block *blk2; // Bottom/right subblock, NULL if leaf
int minp2; // Min size of 2nd subblock, pixels
int maxc2; // Max size of 2nd subblock, chars, or 0
t_table *table; // Descriptor of table window
wchar_t tabname[SHORTNAME]; // Tab (tab window only)
wchar_t title[TEXTLEN]; // Title (tab window) or speech name
wchar_t status[TEXTLEN]; // Status (tab window only)
} t_block;
Each node in the tree describes either a separator (horizontal BLK_HDIV or vertical (BLK_VDIV) or a table (BLK_TABLE). Table is always a leaf node. Separator points to two other nodes, blk1 and blk2, which may itself be separators, tables, or a mix of two.
Let's have a look on the tree that describes the layout of the CPU window:
t_block cpu[] = {
{ 0, BLK_HDIV, 60, 0, cpu+1, 6, 0, cpu+3, 3, 0, NULL, L"", L"", L"" },
{ 1, BLK_VDIV, 65, 0, cpu+2, 3, 0, cpu+6, 3, 0, NULL, L"", L"", L"" },
{ 2, BLK_HDIV, 50, 0, cpu+4, 3, 0, cpu+5, 3, NINFO, NULL, L"", L"", L"" },
{ 3, BLK_VDIV, 50, 0, cpu+7, 3, 0, cpu+8, 3, 0, NULL, L"", L"", L"" },
{ 4, BLK_TABLE, 0, 0, NULL, 0, 0, NULL, 0, 0, &cpudisasm.table, L"", L"Disassembler", L"" },
{ 5, BLK_TABLE, 0, 0, NULL, 0, 0, NULL, 0, 0, &cpuinfo, L"", L"Info", L"" },
{ 6, BLK_TABLE, 0, 0, NULL, 0, 0, NULL, 0, 0, &cpuregs, L"", L"Registers", L"" },
{ 7, BLK_TABLE, 0, 0, NULL, 0, 0, NULL, 0, 0, &cpudump.table, L"", L"Dump", L"" },
{ 8, BLK_TABLE, 0, 0, NULL, 0, 0, NULL, 0, 0, &cpustack.table, L"", L"Stack", L"" }
};
Here is the same structure, graphically:
Node 0 is a horizontal separator. blk1 (top part) points to the node 1 (Disassembler, Info and Register), blk2 (bottom part) - to the node 3 (Dump and Stack). Default space distribution is set to 60% for the top part and rest for the bottom part. Note that default distribution is important only when OllyDbg starts for the first time because frame window saves its layout to the initialization file (section t_frame.name).
Node 1 is a vertical separator. blk1 (left part) points to the node 2 (Disassembler and Info), blk2 (right part) - to the node 6. Node 6 is a leaf with blk1=blk2=NULL and defined table pointer. Frame has no influence on the properties of this table, it only can resize the window. What will be shown in the window depends on the table, and only on it. In our case, table cpuregs displays the contents of registers.
Nodes 4, 7 and 8 are dumps. Dump descriptor t_dump includes t_table as its member, and frame must address this member. Note that dump tables keep pointer to the original dump descriptor in t_table.customdata.
Member t_block.index is a unique identifier used when saving data to the initialization file. When indices change, previous appearance can't be restored.
If flag TABLE_GRAYTEXT in t_frame.mode is set, all tables except for one with focus are grayed. To prevent this, table must set TABLE_NOGRAY.
Tab collections
Tab collections are described by the linked chain of structures of type t_block. All nodes must be of type BLK_TABLE. Unlike frames, where tables are leafs, tab collections use blk1 to link to the next tab. End of the chain is marked by blk1=NULL. Member t_block.index is ignored and can be reused. For example, Search window sets it to the zero-based sequential number of the tab in the chain.
Tab windows support menu (t_frame.menu) that opens with the right click on the tab itself. Menu function receives fake table descriptor where t_table.custommode is set to the index of clicked tab and t_table.customdata points to t_block.
Frame creation
Before you can create table window, you must prepare all necessary structures:
- Initialize descriptors of all tables that comprise the frame (structures t_table or t_dump)
- Initialize the linked tree of block descriptors (structures t_block). Point t_block.table in leaf nodes to table descriptors
- Fill frame descriptor (structure t_frame) and point t_frame.block to the root node of the tree
Creation of tab collections is similar. You only need to call Createtabwindow() instead of Createframewindow().
API functions:
HWND Createframewindow(t_frame *pf,wchar_t *icon,wchar_t *title);
void Updateframe(t_frame *pf,int redrawnow);
t_table * Getactiveframe(t_frame *pf);
HWND Createtabwindow(t_frame *pf,wchar_t *icon,wchar_t *title);
int Updatetabs(t_frame *pf);
t_table * Getactivetab(t_frame *pf);
int Gettabcount(t_frame *pf,int *index);
int Setactivetab(t_frame *pf,int index);
void Updateframe(t_frame *pf,int redrawnow);
t_table * Getactiveframe(t_frame *pf);
HWND Createtabwindow(t_frame *pf,wchar_t *icon,wchar_t *title);
int Updatetabs(t_frame *pf);
t_table * Getactivetab(t_frame *pf);
int Gettabcount(t_frame *pf,int *index);
int Setactivetab(t_frame *pf,int index);
See also: