readme for genwowit.exe This tool generates two source files for wow32, wowit.c and wowit.h, from the input file wow.it. wow.it contains one pseudo-prototype for each API we want to have an interpreted thunk for. The program converts these psuedo-prototypes into interpreted thunk byte streams in wowit.c's InstrSwamp byte array, and entries in wowit.c's IntThunkTable which point to the API and the thunk instruction stream. The psuedo-prototypes can have two names separated by an equals sign, indicating the 16-bit API name on the left is thunked to the 32-bit API name on the right. The bytecode instruction streams consist of 0 or more argument conversion opcodes, which don't have the high bit (0x80) set, followed by a return code conversion opcode, which does have the high bit set. genwowit tries to keep InstrSwamp as small as possible by pointing multiple interpreted thunks at the same instruction stream when they share prototypes (args & retval types). See for example below how UpdateColors, StartPage, EndPage, and GetTextCharacterExtra all use the first instruction stream because they all take a GDI handle and return an int. Further, genwowit will point into the middle of an existing instruction stream if it contains the instruction stream it needs. For example see below how the wowit.c IntThunkTable GetRasterizerCaps entry points to InstrSwamp + 0xb, which is 3 bytes into the instruction stream for TextOut, because ignoring the first three TextOut args they have the same prototype. An example, here's a tiny wow.it and the wowit.h and wowit.c that result. ----- wow.it begin INT UpdateColors(HGDI); INT StartPage(HGDI); INT EndPage(HGDI); DWORD GetFontData(HGDI, DWORD, DWORD, PTR, DWORD); WORD GetRasterizerCaps(PTR, INT); WORD IsGDIObject=GetObjectType(HGDI); WORD GetTextAlign(HGDI); INT GetTextCharacterExtra(HGDI); INT SetTextCharacterExtra(HGDI, INT); DWORD GetTextColor(HGDI); INT GetTextFace(HGDI, INT, PTR); INT SetTextJustification(HGDI, INT, INT); WORD TextOut(HGDI, INT, INT, PTR, INT); ----- wow.it end here's the output genwowit produces on the console: Generated wowit.h and wowit.c from wow.it 13 thunks, 8 unique instruction streams, 29 instruction bytes, 5 max args. And the files: ----- wowit.h begin // // wowit.h generated by genwowit.exe from wow.it, DO NOT EDIT. // #include "intthunk.h" #define MAX_IT_ARGS 5 #define IT_WORD ( (UCHAR) 0x0 ) #define IT_INT ( (UCHAR) 0x1 ) #define IT_DWORD ( (UCHAR) 0x2 ) #define IT_LPDWORD ( (UCHAR) 0x3 ) #define IT_PTR ( (UCHAR) 0x4 ) #define IT_PTRORATOM ( (UCHAR) 0x5 ) #define IT_HGDI ( (UCHAR) 0x6 ) #define IT_HUSER ( (UCHAR) 0x7 ) #define IT_COLOR ( (UCHAR) 0x8 ) #define IT_HINST ( (UCHAR) 0x9 ) #define IT_HICON ( (UCHAR) 0xa ) #define IT_16ONLY ( (UCHAR) 0xb ) #define IT_32ONLY ( (UCHAR) 0xc ) #define IT_RETMASK ( (UCHAR) 0x80 ) #define IT_DWORDRET ( IT_RETMASK | (UCHAR) 0x0 ) #define IT_WORDRET ( IT_RETMASK | (UCHAR) 0x1 ) #define IT_INTRET ( IT_RETMASK | (UCHAR) 0x2 ) #define IT_HGDIRET ( IT_RETMASK | (UCHAR) 0x3 ) #define IT_HUSERRET ( IT_RETMASK | (UCHAR) 0x4 ) #define IT_ZERORET ( IT_RETMASK | (UCHAR) 0x5 ) #define IT_HICONRET ( IT_RETMASK | (UCHAR) 0x6 ) #define IT_ONERET ( IT_RETMASK | (UCHAR) 0x7 ) #define IT_HPRNDWPRET ( IT_RETMASK | (UCHAR) 0x8 ) #define ITID_UpdateColors 0 #define ITID_StartPage 1 #define ITID_EndPage 2 #define ITID_GetFontData 3 #define ITID_GetRasterizerCaps 4 #define ITID_IsGDIObject 5 #define ITID_GetTextAlign 6 #define ITID_GetTextCharacterExtra 7 #define ITID_SetTextCharacterExtra 8 #define ITID_GetTextColor 9 #define ITID_GetTextFace 10 #define ITID_SetTextJustification 11 #define ITID_TextOut 12 #define ITID_MAX 12 ----- wowit.h end ----- wowit.c begin // // wowit.c generated by genwowit.exe from wow.it, DO NOT EDIT. // #include "precomp.h" #pragma hdrstop #define WOWIT_C #include "wowit.h" CONST BYTE InstrSwamp[] = { /* 0 0x0 */ IT_HGDI, IT_INTRET, /* 1 0x2 */ IT_HGDI, IT_DWORD, IT_DWORD, IT_PTR, IT_DWORD, IT_DWORDRET, /* 2 0x8 */ IT_HGDI, IT_INT, IT_INT, IT_PTR, IT_INT, IT_WORDRET, /* 3 0xe */ IT_HGDI, IT_WORDRET, /* 4 0x10 */ IT_HGDI, IT_INT, IT_INTRET, /* 5 0x13 */ IT_HGDI, IT_DWORDRET, /* 6 0x15 */ IT_HGDI, IT_INT, IT_PTR, IT_INTRET, /* 7 0x19 */ IT_HGDI, IT_INT, IT_INT, IT_INTRET, }; INT_THUNK_TABLEENTRY IntThunkTable[] = { /* 0 */ { (FARPROC) UpdateColors, InstrSwamp + 0x0 }, /* 0 */ /* 1 */ { (FARPROC) StartPage, InstrSwamp + 0x0 }, /* 0 */ /* 2 */ { (FARPROC) EndPage, InstrSwamp + 0x0 }, /* 0 */ /* 3 */ { (FARPROC) GetFontData, InstrSwamp + 0x2 }, /* 1 */ /* 4 */ { (FARPROC) GetRasterizerCaps, InstrSwamp + 0xb }, /* 2 + 3 */ /* 5 */ { (FARPROC) GetObjectType, InstrSwamp + 0xe }, /* 3 */ /* 6 */ { (FARPROC) GetTextAlign, InstrSwamp + 0xe }, /* 3 */ /* 7 */ { (FARPROC) GetTextCharacterExtra, InstrSwamp + 0x0 }, /* 0 */ /* 8 */ { (FARPROC) SetTextCharacterExtra, InstrSwamp + 0x10 }, /* 4 */ /* 9 */ { (FARPROC) GetTextColor, InstrSwamp + 0x13 }, /* 5 */ /* 10 */ { (FARPROC) GetTextFace, InstrSwamp + 0x15 }, /* 6 */ /* 11 */ { (FARPROC) SetTextJustification, InstrSwamp + 0x19 }, /* 7 */ /* 12 */ { (FARPROC) TextOut, InstrSwamp + 0x8 }, /* 2 */ }; ----- wowit.c end