HOWTO: Call 16-bit Code from 32-bit Code on Windows 95Last reviewed: June 10, 1997Article ID: Q155763 |
The information in this article applies to:
- Microsoft Win32 Software Development Kit (SDK) for: - Microsoft Windows 95
SUMMARYAs a developer, you may need to access the functionality provided by a 16- bit dynamic-link library (DLL) from your Win32 application. This is true particularly when you do not have the source code for the DLL so that you can port it to Win32. This article discusses the mechanism by which 32-bit DLLs can call 16-bit DLLs. The mechanism is called a thunk and the method implemented under Windows 95 is called a flat thunk. The following describes the three major steps involved in creating a flat thunk:
MORE INFORMATIONA flat thunk consists of a 32-bit and a 16-bit DLL that work together. A Win32 application calls the 32-bit DLL, and the 32-bit DLL calls an exported function in the 16-bit DLL. When the function in the 16-bit DLL returns, it returns back to the 32-bit DLL, which in turn returns back to the Win32 application. The 32-bit and 16-bit DLLs work by calling the Windows 95 32-bit and 16-bit kernels to handle all of the low-level details necessary to make the transition from 32-bit to 16-bit code and back. Designing a new flat thunk involves creating a thunk script (.thk file). This script is compiled with the Thunk compiler into an assembly- language file, which is then assembled twice; one time with each of two flags of -DIS_32 and -DIS_16. This allows you to create both the 32-bit and 16-bit object modules. These object modules are linked in the 32-bit and 16-bit DLLs, respectively. The following diagram summarizes the files involved in building the DLLs:
+------------+ | 32to16.thk | +------------+ | +------------+ | 32to16.asm | +------------+ / \ -DIS_32 / \ -DIS_16 / \ +-----------+ +-----------+ | 32THK.obj | | 16THK.obj | +-----------+ +-----------+ / \ +-------+ +-------+ +-------+ | APP32 | -> | DLL32 | -- THUNK -- | DLL16 | +-------+ +-------+ +-------+ Tools Needed to Build Flat Thunks
Creating the Thunk ScriptYou need to create a script that can be used by the Thunk compiler to create a thunk. A thunk script is a text file that contains type definitions, the function prototypes of the functions you wish to call via thunks and a specification of the direction of the parameters for each function. For example, some functions require both input and output parameters while others may only require input parameters. Thunk scripts use special syntax to describe whether parameters are input, output, or both input and output. A thunk script for 32->16 thunks begins with the following statement:
enablemapdirect3216 = true;The Thunk compiler expects that the 32-bit side of the thunk is declared as __stdcall, and that the 16-bit side is __far __pascal. (The WINAPI declaration takes care of this on both sides.) The __cdecl and __fastcall calling conventions are not supported by the Thunk compiler. Note, however, that the Thunk compiler does not actually accept the __far, __pascal, or __stdcall keywords; they are assumed. The following example shows a thunk script for a function that has no parameters:
enablemapdirect3216 = true; void MyThunk16() { }The equivalent declaration would be:
C language: void WINAPI MyThunk16(void); C++ language: extern "C" void WINAPI MyThunk16();The following example script describes a function that takes two parameters and returns a value. The second parameter is an output parameter that contains a pointer that is passed back to the 32-bit DLL.
enablemapdirect3216 = true; typedef int BOOL; typedef char *LPSTR; BOOL MyThunk16(LPSTR lpstrInput, LPSTR lpstrOutput) { lpstrInput = input; // optional; input is default lpstrOutput = output; }The statement "lpstrOutput = output" tells the Thunk compiler that the 16-bit function returns an address that needs to be converted from a selector:offset pointer into a 32-bit linear address. The following thunk script uses more complex parameter types such as structures. This example also shows how to specify input and output parameters.
enablemapdirect1632 = true; typedef unsigned int UINT; typedef char *LPSTR; typedef struct _POINT { UINT x; UINT y; }POINT, *LPPOINT; typedef struct _CIRCLE { POINT center; UINT radius; }CIRCLE, *LPCIRCLE; void MyThunk32( LPCIRCLE lpCircleInOut) { lpCircleInOut = inout; }The statement "lpCircleInOut = inout" tells the script compiler that this pointer is going to be used for input and output. This causes the Thunk compiler to convert lpCircleInOut from a 32-bit linear address to a selector:offset pointer when the function is called and then back to a 32-bit linear address when the function returns. The conversion is handled by the thunk created by the Thunk compiler.
Using the Thunk CompilerThe Thunk compiler usage is as follows:
thunk.exe /options <inputfile> -o <outputfile>The following command line shows how to compile a 32->16 thunk script. This line takes a thunk script named 32to16.thk and produces an assembly-language file named 32to16.asm.
thunk -t thk 32to16.thk -o 32to16.asmThe "-t thk" option tells the Thunk compiler to prefix the thunk functions in the assembly-language file with "thk_." This prefix is used when linking multiple thunk scripts into a pair of DLLs, and is useful for creating a pair of DLLs that contain both 32->16 and 16->32 thunks. Each thunk script should have a unique prefix.
Building the 32-bit DLL
Building the 16-bit DLL
REFERENCESFor information about how to debug flat thunks, please refer to the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q133722 TITLE : HOWTO: Debug Flat Thunks |
Additional query words: win95 flat thunk win16 debug
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |