Compiling Flat Thunks

Compile your thunk script using the thunk compiler to create an .ASM file containing the flat thunk. The thunk compiler has the following syntax:

thunk [{-|/}options] infile[.ext]

? Displays the help screen.
h Displays the help screen.
o name Overrides the default output filename.
p n Changes the 16-bit structure alignment (default = 2).
P n Changes the 32-bit structure alignment (default = 4).
t name Overrides the default base name.
Nx name Specifies the name segment or class, where x is either C32 (for 32-bit code segment name) or C16 (for 16-bit code segment name).

The .ASM file produced by the thunk compiler contains code for both sides of the thunk. The 16-bit code in the .ASM file includes a jump table containing the 16:16 address of each function named in the thunk scripts. The 16-bit linker must be able to resolve these references; the functions must either be implemented in the 16-bit DLL or be imported by the DLL. The 32-bit code in the .ASM file contains a WINAPI function for each thunk, which converts its parameters to 16-bit values, then calls the 16-bit target referenced in the jump table. When a Win32-based application uses a 16-bit function through the thunk, it calls these compiler-generated functions directly.

Assemble the resulting .ASM file to create the 16-bit side of the thunk by defining IS_16. For example, using Microsoft MASM version 6.11, you can use the following command line:

ml /DIS_16 /c /W3 /nologo /Fo thk16.obj 16to32.asm
 

Assemble the resulting .ASM file to create the 32-bit side of the thunk by defining IS_32. For example, using Microsoft MASM version 6.11, you can use the following command line:

ml /DIS_32 /c /W3 /nologo /Fo thk32.obj 16to32.asm
 

Create the following declaration for the LineTo function in the thunk script:

typedef bool         BOOL;
typedef unsigned int UINT; 
typedef UINT         HANDLE; 
typedef HANDLE       HDC; 
 
BOOL LineTo(HDC, int, int) 
{ 
} 
 

When the thunk compiler processes the thunk script, it generates the following 16-bit code:

externDef LineTo:far16 
 
FT_gdiTargetTable label word 
    dw    offset LineTo 
    dw       seg LineTo
 

In addition, the thunk compiler generates the following 32-bit code:

public LineTo@12 
LineTo@12: 
    mov    cl,0 
; LineTo(16) = LineTo(32) {} 
; 
; dword ptr [ebp+8]:  param1 
; dword ptr [ebp+12]:  param2 
; dword ptr [ebp+16]:  param3 
; 
public IILineTo@12 
IILineTo@12: 
    call    QT_Entry 
    push    word ptr [ebp+8]     ;param1: dword->word 
    push    word ptr [ebp+12]    ;param2: dword->word 
    push    word ptr [ebp+16]    ;param3: dword->word 
    call    QT_Target_gdi 
    movsx   ebx,ax 
    jmp     QT_Exit12
 

When a Win32-based application calls the LineTo function, it is this routine that is executed. The routine builds a 16-bit call frame, calls a local routine requesting the appropriate address in the jump table, and sign-extends the return value. Each component receives its own set of routines (with the QT_ prefix), which automatically use the correct jump table.