Solved

Using LoadLibrary within a 16-bit dll

Posted on 1998-02-23
13
650 Views
Last Modified: 2013-12-03
I am trying to create a 16-bit "cover" dll that will call a 32-bit dll from a Powerbuilder program.  In my 16-bit "cover" dll, I am trying to LoadLibrary ("the name of the 32-bit dll").  When I execute the PB program, I get to my 16-bit dll, but the LoadLibrary fails with a rc of 21 (Application requires Windows 32-bit extensions).  Any ideas on how I  can get this to work?  Really appreciate any help I can get!
0
Comment
Question by:rmmarsh
  • 9
  • 4
13 Comments
 
LVL 4

Expert Comment

by:tflai
ID: 1411485
You need to write generic thunk for to access 32-bit DLL from 16-bit application.
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411486
Microsoft Knowledge Base

SAMPLE: Win16 App (WOW & Win32s) Calling Win32 DLL Code

Last reviewed: April 7, 1997
Article ID: Q114341 1.30 1.30c | 3.51 4.00

WINDOWS    | WINDOWS NT



kbprg kbref

The information in this article applies to:

•Microsoft Win32 Software Development Kit (SDK) for Windows NT, version 3.51, 4.0 •Microsoft Win32s, version 1.30c







SUMMARY

The INTEROP sample demonstrates two general methods for calling routines in a Win32 DLL from a Windows-based application: thunks and SendMessage(). There are two different thunking methods, one for each platform: Generic Thunks on Windows NT and Universal Thunks on Win32s. The message used is WM_COPYDATA, a new message introduced by Windows NT and Win32s. All three methods provide a way to call functions and pass data across the 16-32 boundary, translating any pointers in the process. The advantages of WM_COPYDATA over thunks are that it is fast and the exact same code runs on either platform (the thunk mechanism used will depend on the platform). The disadvantage of WM_COPYDATA is that a method must be devised to get a function return value (other than true or false) back to the calling application.

NOTE: Universal Thunks were designed to work with a Win32-based application calling a 16-bit DLL. The method described here has limitations. Because the application is 16-bit, no 32-bit context is created, so certain calls will not work from the Win32 DLL.

The sample consists of the following source files:



   APP16.C    -  Win16 Application
   DLL16.C    -  16-bit side of Universal Thunk/Generic Thunk
   STUB32.C   -  32-bit stub that loads the 32-bit DLLs on Win32s
   UTDLL32.C  -  32-bit side of the Universal Thunk
   DISP32.C   -  Dispatch calls sent through WM_COPYDATA
   DLL32.C    -  Win32 DLL




This sample is included with the Microsoft Win32 SDK. It is located in the \MSTOOLS\SAMPLES\Q_A\INTEROP directory.



 NOTE: There is also an RPC sample named INTEROP, but it is in a different



directory, (\MSTOOLS\SAMPLES\RPC\INTEROP).





MORE INFORMATION





Generic Thunk

Under Windows NT, it is possible to call routines in a Win32 DLL from a Windows-based application using an interface called Generic Thunks. The Win32 SDK file DOC\SDK\MISC\GENTHUNK.TXT and the Win32 SDK documentation (under the section "Programming and Tools Guides, Programming Techniques, Generic Thunks") describe the interface.

Here is a picture of the way the pieces fit together in INTEROP:



                             dll32
                           ---------
                          |  Win32  |
    32-bit                |   DLL   |
                           ---------
                              /|\
               ----------------|-------
                               |
                ---------     ------------
               | Win 3.1 |<->| 16-bit DLL |
    16-bit     |   app.  |   |   (GT)     |
                ---------     ------------
                  app16           dll16




DLL16 is loaded when APP16 is loaded. If it detects that WOW is present, then it loads DLL32.

WOW presents a few new 16-bit application programming interfaces (APIs) that allow you to load the Win32 DLL, get the address of the DLL routine, call the routine (passing it up to thirty-two 32-bit arguments), convert 16:16 (WOW) addresses to 0:32 addresses (useful if you need to build up a 32-bit structure that contains pointers and pass a pointer to it), and free the Win32 DLL. These functions are:



   DWORD FAR PASCAL LoadLibraryEx32W( LPCSTR, DWORD, DWORD );
   DWORD FAR PASCAL GetProcAddress32W( DWORD, LPCSTR );
   DWORD FAR PASCAL CallProc32W( DWORD, ..., LPVOID, DWORD, DWORD );
   DWORD FAR PASCAL GetVDMPointer32W( LPVOID, UINT );
   BOOL FAR PASCAL FreeLibrary32W( DWORD );




When linking the Win16 application, you need to put the following statements in the .DEF file, indicating that the functions will be imported from the WOW kernel:



   IMPORTS
      kernel.LoadLibraryEx32W
      kernel.FreeLibrary32W
      kernel.GetProcAddress32W
      kernel.GetVDMPointer32W
      kernel.CallProc32W




Note that although these functions are called in 16-bit code, they need to be provided with 32-bit handles, and they return 32-bit handles.

In addition, be sure that your Win32 DLL entry point is declared with the _stdcall convention; otherwise, you will get an access violation.





Universal Thunk

Under Win32s, it is possible to call routines in a Win32 DLL from a Win16 application using an interface called Universal Thunks. The interface is described in the Win32s Programmer's Reference. The sample UTSAMPLE, shows the opposite (and more typical) case, a Win32 application calling 16-bit routines.

Here is a picture of the way the pieces fit together in INTEROP:



                         stub           utdll32         dll32
                      -----------     -----------     ---------
                     |   Win32   |-->| Win32 DLL |<->|  Win32  |
    32-bit           |    EXE    |   |    (UT)   |   |   DLL   |
                      -----------     -----------     ---------
                              /|\      /|\
             ------------------|--------|-------------------------
                               |       \|/
                ---------     ------------
               | Win 3.1 |<->| 16-bit DLL |
    16-bit     |   app.  |   |   (UT)     |
                ---------     ------------
                  app16           dll16




The load order is as follows: The Windows 3.1 application loads the 16-bit DLL. The 16-bit DLL checks to see whether the 32-bit side has been initialized. If it has not been initialized, then the DLL spawns the 32-bit .EXE (stub), which then loads the 32-bit DLL that sets up the Universal Thunks with the 16-bit DLL. Once all of the components are loaded and initialized, when the Windows 3.x application calls an entry point in the 16-bit DLL, the 16-bit DLL uses the 32-bit Universal Thunk callback to pass the data over to the 32-bit side. Once the call has been received on the 32- bit side, the proper Win32 DLL entry point can be called.





WM_COPYDATA

The wParam and lParam for this message are as follows:



   wParam = (WPARAM) (HWND) hwndFrom;   /* handle of sending window */
   lParam = (LPARAM) (PCOPYDATASTRUCT) pcds;




Where hwndFrom is the handle of the sending window and COPYDATASTRUCT is defined as follows:



   typedef struct tagCOPYDATASTRUCT {
       DWORD dwData;
       DWORD cbData;
       PVOID lpData;
   } COPYDATASTRUCT;




The INTEROP sample uses dwData as a function code, indicating which Win32 DLL entry point should be calling and lpData to contain a pointer to the data structure to be passed to the function.

Here is a picture of the way the pieces fit together in INTEROP:



                         disp           dll32
                      -----------     ---------
                     |   Win32   |-->|  Win32  |
    32-bit           |    EXE    |   |   DLL   |
                      -----------     ---------
                              /|\
             ------------------|----------------------------------
                               |
                ---------     ------------
               | Win 3.1 |<->| 16-bit DLL |
    16-bit     |   app.  |   |  (THUNK)   |
                ---------     ------------
                  app16           dll16




DLL16 is loaded when APP16 is loaded. DISP is spawned to handle WM_COPYDATA messages, regardless of platform. DISP dispatches the calls to DLL32, marshaling the arguments.




------------------------------------------------------------------------



0
 

Author Comment

by:rmmarsh
ID: 1411487
Is a generic thunk the ONLY way?  The Watcom C++ Programmers Guide shows a Windows 3.x example that uses LoadLibrary().  Is the generic thunk a Windows 95 anomaly?
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411488
Also check out June 1994's issue of MSJ.  There is an article by James Finnegan, titled "Test Drive Win32® from 16-bit Code Using the Windows NT ™ WOW Layer and Generic Thunk".
(You can get it through web page, "http://www.microsoft.com/msj/backissuesindex.htm")
0
 

Author Comment

by:rmmarsh
ID: 1411489
BTW, this 16-bit program which calls the 16-bit dll (which in turn calls the 32-bit dll) run under Windows 95.  Does this change anything?
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411490
Generic thunk is one of the way to access 32-bit from 16-bit code.  Another way is to write OLE wrapper on both sides.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 4

Expert Comment

by:tflai
ID: 1411491
No matter what calls what, whenever there is a change, from 16-bit to 32-bit, or from 32-bit to 16-bit, you need something like thunking.
(Generic thunk, 16-bit to 32-bit, Windows 95 & NT)
(Flat thunk, 32-bit to 16-bit, Windows 95 only)
0
 
LVL 4

Accepted Solution

by:
tflai earned 200 total points
ID: 1411492
That was suppose to be an ANSWER.
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411493
Hi rmmarsh,
So, how's your 16-to-32 thunk layer DLLs coming along?  Let me know how's your progress.  Thanks.
0
 

Author Comment

by:rmmarsh
ID: 1411494
Well, I have written a flat thunk; both sides are written and linked, but when the 16-bit dll calls the 32-bit dll, the system crashes somewhere within the bowels of Windows 95.  I think I might not be passing some of the parameters properly (ie strings), so I am going to look into that on Monday.  In the mean time, I need to know how to turn on kernel debugging mode WITHOUT the aid of the Win95 SDK (since I don't have a copy of it).  Can you answer that for the same 200 points or do I have to increase it?  I really appreciate you pointing me in the right direction in the beginning... now I am fast becoming a mini-expert in thunking!
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411495
From my experience, debugging through the thunk layers is very difficult.  In fact, Microsoft has a check list of possible problems causing the thunk layers not to function properly.  And I strongly suggest that you go through the items in the check list one by one first before try to debug it in kernel mode.  By the way, do you have Soft-Ice?  It can be EXTREMELY USEFUL.
0
 
LVL 4

Expert Comment

by:tflai
ID: 1411496
Hmm...  By the way, I hope you meant to say "Generic Thunk" and not "Flat Thunk", since your direction of calling is from 16-bit to 32-bit.
0
 

Author Comment

by:rmmarsh
ID: 1411497
Thanks for the reply... I'll look into Soft-Ice... and no, I do not mean "generic" thunk; I am unable to modify the 32-bit dll, so I had to go with a "flat thunk"... and I do have the MS Knowledge base article on "How to debug flat thunks"... I'll keep you posted...
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now