Calling 16-bit Code from Win32-based Apps in Windows 95 
Article ID: Q125715
Revision Date: 25-SEP-1995
 
The information in this article applies to:

 - Microsoft Win32 Application Programming Interface (API) included with:

    - Microsoft Windows 95 version 4.0



SUMMARY 
As a developer, you may need to access the functionality provided by a 16- bit DLL from your Win32-based applications. 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 Win32-based DLLs can call Windows-based DLLs. The mechanism is called a thunk and the method implemented under Windows 95 is called a flat thunk. 

The three major steps in writing the thunk code are:

1. Creating the Thunk Script
2. Building the Win32-based DLL
3. Building the Windows-based DLL



MORE INFORMATION 
The recommended way to design a thunk call is to isolate all thunk specific code in DLLs (a 16-bit DLL and a 32-bit DLL, to provide both sides of the thunk). That way, you can install certain DLLs on one platform and replace them on another platform, for portability. 
Designing a new flat thunk involves creating a thunk script (.THK file). This script is compiled with the Thunk Compiler into an assembly file. This file is assembled using two different flags: -DIS_32 and -DIS_16. This allows you to create both the 16-bit and 32-bit object modules. These object modules are linked in the Windows-based and Win32-based DLLs, respectively. The following diagram summarizes the files involves in building the DLLs. 

                         +------------+
                         | 32to16.THK |
                         +------------+
                               |
                         +------------+
                         | 32to16.ASM |
                         +------------+
                            /       \
                  +-----------+ +-----------+
                  | 32THK.OBJ | | 16THK.OBJ |
                  +-----------+ +-----------+
                        /                 \
        +-------+    +-------+             +-------+
        | APP32 | -> | DLL32 | -- THUNK -- | DLL16 |
        +-------+    +-------+             +-------+




Creating the Thunk Script 
You need to create a script that will be used by the thunk compiler to create a thunk. A thunk script contains the function prototype and a specification for the input and output values. You need to include the following statement to create a 32-bit to 16-bit thunk call: 

   enablemapdirect3216 = true;


The following is an example of a simple thunk script for a function that has no input and output: 

   enablemapdirect3216 = true;

   void MyThunk16()
   {
   }


The following is an example of script that takes two parameters and returns a value. The second parameter is an output parameter and contains a pointer that is passed back to the Win32-based DLL. 

   enablemapdirect3216 = true;

   typedef int   BOOL;
   typedef char *LPSTR;

   BOOL MyThunk32(LPSTR lpstrInput, LPSTR lpstrOutput)
   {
      lpstrOutput = output;
   }


The following thunk script uses more complex parameter types, such as structures. This example also shows how to specify input and output parameters. 

   enablemapdirect3216 = true;

   typedef int BOOL;
   typedef unsigned int UINT;
   typedef char *LPSTR;

   typedef struct tagPOINT {
      INT  x;
      INT  y;
   } POINT;
   typedef POINT *LPPOINT;

   typedef struct tagCIRCLE {
      POINT center;
      INT   radius;
   } CIRCLE;
   typedef 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. 

The thunk compiler usage is as follows:

   thunk.exe /options <inputfile> -o <outputfile>


The following command line shows how to create a 16-bit thunk code. 

   thunk -t thk 32to16.thk -o 32to16.asm


The "-t thk" option tells the thunk compiler to prefix the thunk functions in the assembly language file with "thk_." This will create an assembly language file. 

Building the Win32-based DLL (DLL32) 

1. In the DllEntryPoint function (DllMain if you're using the Microsoft
   C Run-time libraries) in your Win32-based DLL, you must make a call
   to the imported function thk_ThunkConnect32, as shown here:

      BOOL WINAPI DllMain(HINSTANCE hDLLInst,
                          DWORD  fdwReason,
                          LPVOID lpvReserved)
      {
         if (!thk_ThunkConnect32("DLL16.DLL",
                                 "DLL32.DLL",
                                 hDLLInst,
                                 fdwReason))
         {
            return FALSE;
         }
         switch (fdwReason)
         {
            case DLL_PROCESS_ATTACH:
               break;

            case DLL_PROCESS_DETACH:
               break;

            case DLL_THREAD_ATTACH:
               break;

            case DLL_THREAD_DETACH:
               break;
         }
         return TRUE;
      }

2. Include the following lines in the EXPORT section of the module
   definition (DEF) file for DLL32.

      thk_ThunkData32

3. Export the function that you are thunking to.

4. Assemble the assembly language file produced by the thunk compiler as a
   32-bit object module. The following line shows an example:

      ml /DIS_32 /c /W3 /nologo /coff /Fo thk32.obj 32to16.asm

5. Link this object module as part of the Win32-based DLL (DLL32).



Building the Windows-based DLL (DLL16) 

1. The Windows-based DLL must export a function named "DllEntryPoint". This
   function must make a call to an imported function thk__ThunkConnect16.

      BOOL FAR PASCAL __export DllEntryPoint(DWORD dwReason,
                                             WORD  hInst,
                                             WORD  wDS,
                                             WORD  wHeapSize,
                                             DWORD dwReserved1,
                                             WORD  wReserved 2)
      {
         if (!thk_ThunkConnect16("DLL16.DLL",
                                 "DLL32.DLL",
                                 hInst,
                                 dwReason))
         {
            return FALSE;
         }
         return TRUE;
      }

2. Include the following lines in the IMPORTS section of the module
   definition (DEF) file for DLL16:

      C16ThkSL01      = KERNEL.631
      ThunkConnect16  = KERNEL.651

3. Include the following lines in the EXPORTS section of the module
   definition (DEF) file for DLL16. The THK_THUNKDATA16 is defined in the
   object file that is assembled from the output of the thunk compiler.

      THK_THUNKDATA16 @1  RESIDENTNAME
      DllEntryPoint   @2  RESIDENTNAME

4. Once you have done that you need to assemble the assembly language
   file produced by the thunk compiler as a 16-bit object module. The
   following line shows an example:

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

5. Link this object module as part of the 16-bit DLL (DLL16) object file.

6. Mark the Windows-based DLL as version 4.0. To do this you can use the
   resource compiler (RC.EXE). The following line shows the syntax:

      rc -40 <DLL file>

   This -40 option is available in the resource compiler that is provided
   with the Windows 95 SDK and later SDKs.

   NOTE: Be sure to use the RC.EXE in the BINW16 directory so that the
   application is marked with version 4.0. There is another RC.EXE, but it
   will not mark the application with version 4.0.



Additional reference words: 4.00 95 flat thunk win16


KBCategory: kbprg
KBSubcategory: SubSys BseMisc


 

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS
PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.  MICROSOFT DISCLAIMS
ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.  SOME STATES DO NOT ALLOW THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES
SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1995.
