 CALL32: 32-bit DLL Calling Library for Visual Basic
 
 CALL32.DLL is a dynamic-link library (DLL) that can be
 used for calling routines in 32-bit DLLs on the
 Microsoft(R) Windows(R) NT(TM) and Windows95 (TM) operating 
 systems. It cannot be used on Windows(TM) 3.1, Win32s(TM), 
 or other operating systems. 
 
 Using it, a Visual Basic(R) program, running in
 the Win16 subsystem, can declare and call functions in any
 32-bit DLL (including, but not limited to, the system
 DLLs). CALL32.DLL works on both the x86 and MIPS versions
 on Windows NT. It has not been tested on Alpha or other
 versions, but it should work.
 
 To call a function in a 32-bit DLL, follow these steps:
 
 1. Declare the following 2 function as follows (each all on 
    one line):
 
     Declare Function Declare32 Lib "call32.dll" (ByVal Func$, ByVal Library$, ByVal Args$) As Long
     Delcare Sub FreeCall32IDs Lib "call32.dll" ()
 
 2. Next, declare the function you wish to call. Declare it
    in the ordinary fashion, with the following exceptions:
 
 >  Use a library name of "call32.dll"
 >  Use an Alias of "Call32"
 >  Add an additional argument at the end, of type ByVal Long
 
 For example, if you are calling the function:
 
 GetWindowText(HWND hwnd, LPSTR lpsz, int cch)
 
 declare it as follows (remember that ints and all handles
 are 32 bits, so use a Long):
 
 Declare Function GetWindowText Lib "call32.dll" Alias "Call32" (ByVal hwnd As Long, ByVal lpsz As String, ByVal cch As Long, ByVal id As Long) As Long
 
 In the initialization section of your application, declare
 the actual library and name of the function you want to
 call with the Declare32 function. Pass it the name of the
 function, the library, and a string describing the
 argument types. Each letter in the string declares the
 type of one argument, and should be either "i" for a 32-
 bit integer or handle type, "p" for any pointer type, or
 "w" for an HWND parameter to which you want to pass a 16-
 bit HWND and have it be automatically converted to a 32-
 bit HWND. Save the return value of Declare32 in a global
 variable to pass as the last parameter to the function you
 declared earlier. So, in continuing the example, you would
 call:
 
 idGetWindowText = Declare32("GetWindowText", "user32", "wpi")
 
 (As a side note, this more properly would be declared as
 "GetWindowTextA", since this is the real exported name.
 However, Declare32 will automatically add an "A" to the
 end of a function name if necessary.)
 
 To call the function, you would call:
 
 cbCopy = GetWindowText(hwnd, sz, cb, idGetWindowText)
 
 It is important to use the correct data types when calling
 DLL functions. There are two important points to pay
 attention to when using CALL32.DLL.
 
 First, only 32-bit integers can be passed to a DLL
 procedure. Since virtually all 32-bit functions take int,
 UINT, LONG, DWORD, or HANDLE parameters, which are all 32
 bits, this is not a major restriction. However, you must
 remember to always declare function arguments as Long, not
 Integer.
 
 Second, 16-bit handles and 32-bit handles are not
 interchangeable. For example, a 16-bit bitmap handle that
 you get from calling a 16-bit DLL or from the Visual Basic
 environment cannot be passed to a 32-bit function
 expecting a bitmap handle. Similarly, a 32-bit handle
 obtained from a 32-bit function cannot be passed to a 16-
 bit DLL. The only exception is window handles (HWND). If
 you declare a function parameter with the "w" letter in
 the argument description string passed to Declare32, the
 corresponding parameter will be automatically converted
 from a 16-bit HWND to a 32-bit HWND when the call is made.
 You must still declare the argument as a LONG. This is
 convenient, for example, when passing the value returned
 by the "hWnd" property of a control to a 32-bit DLL
 function. Only windows created by your application can be
 translated.
 
 The following is a summary of data types:
 
 C data type       Type specified in Declare   Character for Declare32
   int, UINT          ByVal Long                 i
   LONG, DWORD        ByVal Long                 i
   HANDLE             ByVal Long                 i
   WORD, short        not supported
   HWND               ByVal Long                 w (i for no 16->32 translation)
   LPSTR              ByVal String               p
   LPLONG, LPDWORD,
   LPUINT, int FAR *  Long                       p
   LPWORD             Integer                    p
 
 Note on Declare32 function names: Declare32 will
 automatically try three different names for the function
 name you pass in. First, it uses the exact name you pass
 in. If it doesn't find that function name, it converts the
 name to the stdcall decorated name convention by adding an
 underscore at the beginning and adding "@nn" at the end,
 where "nn" is the number of bytes of arguments. If it
 doesn't find that name, it adds an "A" to the end of the
 original name to try the Win32(R) ANSI function calling
 convention.

 *** NOTE ****
 Before ending your VB programs, call FreeCall32IDs() to free 
 the libraries that were loaded by CALL32.DLL.  If you don't call
 this subroutine the counter that Windows keeps as to how many 
 programs are using a particular .dll will not get decremented.
 The .dlls are only removed from memory when the counter gets
 decremented to 0.  By not calling the FreeCall32IDs() sub, you can
 caused .dlls to remain in memory after your program exits.

 
 This program is in the public domain. Feel free to
 redistribute as you wish. No guarantees are made as to its
 suitability or usefulness.
 
 CALL32 requires either the Microsoft Windows NT or Windows 95 
 operating system to run. For information on run-time errors 
 generated by CALL32, refer to the CALL32.TXT file.
 
 KEYWORDS: CD7
