Calling a Win32 DLL from an OS/2 Application 
Article ID: Q119217
Revision Date: 21-JUN-1996
 
The information in this article applies to:

 - Microsoft Win32 Software Development Kit (SDK) for Windows NT,
   version 3.5



SUMMARY 
The OS/2 subsystem provides a general mechanism that allows 16-bit OS/2 and PM applications to load and call a Win32 DLL. This feature is useful if you would like to call one of the Win32 APIs without having to spawn a Win32 application to do so; it is also useful if you are porting your OS/2 application to Win32 in stages. A small set of APIs (described in the "MORE INFORMATION" section, below) provides this functionality to your application. 
To take full advantage of this feature, write a small Win32 DLL to provide the thunk. The OS/2 application calls the thunk DLL, which in turn calls the real Win32 API, using the parameters that were passed from the OS/2 application. You could call the Win32 DLL directly, but the OS/2 subsystem thunking mechanism has only one generic pointer parameter. Most Win32 APIs require different numbers or types of parameters, so the thunking layer is required to retrieve the parameters from the parameter pointer. The parameter pointer typically points to a structure that contains the actual parameters. 
You will also need to modify your OS/2 application to call the thunking APIs described below. 

MORE INFORMATION 
The following are the header file, descriptions, and import statements for the 16-bit APIs that are used by the OS/2 application to load and call the thunk DLL. The APIs are defined in the same manner as the OS/2 APIs. 

Header File 

   extern USHORT pascal far
   Dos32LoadModule(PSZ DllName, PULONG pDllHandle);

   extern USHORT pascal far
   Dos32GetProcAddr(ULONG Handle, PSZ pszProcName, PULONG pWin32Thunk);

   extern USHORT pascal far
   Dos32Dispatch(ULONG Win32Thunk, PVOID pArguments, PULONG pRetCode);

   extern USHORT pascal far
   Dos32FreeModule(ULONG DllHandle);

   extern USHORT pascal far
   FarPtr2FlatPtr(ULONG FarPtr, PULONG pFlarPtr);

   extern USHORT pascal far
   FlatPtr2FarPtr(ULONG FlatPtr, PULONG pFarPtr);



API Descriptions 

   Dos32LoadModule
   ---------------

   USHORT pascal far Dos32LoadModule (
      PSZ    DLLName,
      PULONG pDllHandle );

   Purpose:

   Load the Win32 thunk DLL that will intermediate between the OS/2
   application and the Win32 APIs.

   Parameters:

   DLLName    - Name of the thunk DLL.
   pDllHandle - Receives the module handle of the DLL. Used as an
                argument to Dos32GetProcAddr.

   Return:

   If NO_ERROR is returned, the value pointed to by pDllHandle is used for
   other WIN32 thunk APIs as described below. It is invalid for usage with
   regular OS/2 APIs.

   If ERROR_MOD_NOT_FOUND is returned, the value pointed to by pDLLHandle
   is undefined.

   Dos32GetProcAddr
   ----------------

   USHORT pascal far Dos32GetProcAddr (
      ULONG  DllHandle,
      PSZ    pszProcName,
      PULONG pWin32Thunk );

   Purpose:

   Get a flat pointer to a routine in the Win32 thunk DLL previously opened
   by Dos32LoadModule.

   Parameters:

   DllHandle   - Handle obtained through Dos32LoadModule.
   pszProcName - Name of the API to be called.
   pWin32Thunk - Receives pointer to the thunk routine.

   Return:

   If NO_ERROR is returned, then pszProcName is exported by the thunk DLL.

   If ERROR_PROC_NOT_FOUND or ERROR_INVALID_HANDLE is returned, then the
   value pointed to by pWin32Thunk is undefined.

   NOTE: The thunking routine must be declared as _cdecl in order for the
   Dos32GetProcAddr to work.   However, the thunking routine must exit as
   if it's using a _stdcall in order for Dos32Dispatch to return.


The following program illustrates how the thunking routine should return using the _stdcall convention: 



 #include <windows.h>
 #include <stdio.h>
 __declspec(dllexport) ULONG Thunk(PVOID pFlatArg);

 __declspec(dllexport) ULONG Thunk(PVOID pFlatArg)
 {¬
ULONG ulRC = 7;


printf("You have successfully called the Thunk function.\n"); /* put the ULONG return value into the EAX register */ 
__asm  mov       eax, ulRC


/* now return as this function were declared as _stdcall */
__asm  pop       edi
__asm  pop       esi
__asm  pop       ebx


__asm  leave
__asm  ret       0004



printf("This should be dead code!!!\n");


return (0);


}


   Dos32Dispatch
   -------------

   USHORT pascal far Dos32Dispatch (
      ULONG  Win32Thunk,
      PVOID  pArguments,
      PULONG pRetCode );

   Purpose:

   Call the thunk routine through the pointer obtained through
   Dos32GetProcAddr.

   Parameters:

   Win32Thunk - Thunk routine obtained through Dos32GetProcAddr.
   pArguments - Argument for thunk routine.
   pRetCode   - Error code returned from the thunk routine.

   The structure pointed to by pArguments is application specific and
   the value is not modified to the OS/2 subsystem.

   On the Win32 side (in the thunk DLL), the thunk looks like:

      ULONG MyFunc (
         PVOID pFlatArg );

   The OS/2 subsystem does translate pArguments from a 16:16 pointer to
   a flat pointer (pFlatArg). To translate pointers inside the structure,
   use FarPtr2FlatPtr.

   Return:

   If NO_ERROR is returned, then pFlatArg is a valid pointer.

   Dos32FreeModule
   ---------------

   USHORT pascal far Dos32FreeModule (
      ULONG DllHandle );

   Purpose:

   Unload the Win32 thunk DLL that is intermediating between the OS/2
   application and the Win32 APIs.

   Parameter:

   DllHandle - Handle obtained through Dos32LoadModule.

   Return:

   If NO_ERROR is returned, then DllHandle corresponds to a Win32 DLL
   previously loaded by Dos32LoadModule. After the call, DllHandle is no
   longer valid. Otherwise, ERROR_INVALID_HANDLE is returned.

   FarPtr2FlatPtr
   --------------

   USHORT pascal far FarPtr2FlatPtr (
      ULONG  FarPtr,
      PULONG pFlatPtr );

   Purpose:

   Translates a segmented far pointer to a flat pointer.

   Parameters:

   FarPtr   - Segmented far pointer.
   pFlatPtr - Points to flat pointer.

   Return:

   If NO_ERROR is returned, FarPtr is a valid 16:16 pointer and pFlatPtr
   contains a valid flat pointer to be used by Win32 code. Otherwise,
   ERROR_INVALID_PARAMETER is returned and pFlatPtr is undefined.

   FlatPtr2FarPtr
   --------------

   USHORT pascal far FlatPtr2FarPtr (
      ULONG  FlatPtr,
      PULONG pFarPtr );

   Purpose:

   Translates a flat pointer to a segmented far pointer.

   Parameters:

   FlatPtr - Flat pointer.
   pFarPtr - Points to a segmented far pointer.

   Return:

   If NO_ERROR is returned, the flat pointer maps to a valid segmented
   pointer in the 16-bit application's context and pFarPtr contains a valid
   segmented pointer to be used by 16-bit OS/2 code. Otherwise,
   ERROR_INVALID_PARAMETER is returned and pFarPtr is undefined.



IMPORTS Section for the Module Definition File 

   IMPORTS
      DOSCALLS.DOS32LOADMODULE
      DOSCALLS.DOS32GETPROCADDR
      DOSCALLS.DOS32DISPATCH
      DOSCALLS.DOS32FREEMODULE
      DOSCALLS.FARPTR2FLATPTR
      DOSCALLS.FLATPTR2FARPTR



Additional reference words: 3.50 OS2


KBCategory: kbprg
KBSubcategory: SubSys


 

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 1996.
