Results 1 to 40 of 63

Thread: [VB6] Call Functions By Pointer (Universall DLL Calls)

Threaded View

  1. #1

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    [VB6] Call Functions By Pointer (Universall DLL Calls)

    I was recently made aware that a function I've used from time to time for calling virtual functions of COM objects was perfectly adept at calling functions from just about any standard DLL out there. So, I whipped up a 'generic' class that can call both standard DLL functions & COM VTable functions. No thunks are used, just a couple of supporting API calls in the main class, including the low-level core API function: DispCallFunc

    What does this mean for you? Well, it does allow you to call DLL functions from nearly 10 different calling conventions, including the two most common: StdCall & CDecl. It also allows you to call virtual functions from COM objects. And if you wish, it means you do not have to declare a single API function declaration in your VB project. Though, personally, I'd use it for calling DLL conventions other than StdCall.

    I'd consider this topic advanced for one reason only. This is very low level. If you provide incorrect parameter information to the class, your project is likely to crash. For advanced coders, we have no problem doing the research to understand what parameter information is required, be it variable type, a pointer, a pointer to a pointer, function return types, etc, etc. Not-so-advanced coders just want to plug in values & play, but when playing at such a low level, that usually results in crashes, frustration.

    The attachment includes very simple examples of calling DLL functions and calling a COM virtual function. You will notice that the form has no API function declarations, though several DLL functions are called & executed correctly. A sample call to the class might look like:
    Code:
    Debug.Print myClass.CallFunction_DLL("user32.dll", "IsWindowUnicode", STR_NONE, CR_LONG, _
                                            CC_STDCALL, Me.hWnd)
    For DLL calls, the class takes the DLL name and function name to be called. Technically, you aren't passing the function pointer to the class. However, the class does make the call to the pointer, not via declared API functions. Just thought I'd throw this comment in, should someone suggest we aren't really calling functions by pointer. The class is, the user calling the class is not, but can be if inclined to modify the code a bit.

    Limitations: Callbacks from non-StdCall DLLs/functions
    If whatever function you are calling requires a callback pointer, then stack corruption is likely from all calling conventions where you pass a VB function pointer as the callback address. The exceptions are stdCall DLLs and also CDecl calls, if the thunk/patch option in the class is used.

    Tip: If you really like this class, you may want to instantiate one for each DLL you will be calling quite often. This could speed things up a bit when making subsequent calls. As is, the class will load the requested DLL into memory if it isn't already. Once class is called again, for a different DLL, then the previous DLL is unloaded if needed & the new DLL loaded as needed. So, if you created cUser32, cShell32, cKernel32 instances, less code is executed in the class if it doesn't have to drop & load DLLs.
    vb Code:
    1. ' top of form
    2. Private cUser32 As cUniversalDLLCalls
    3. Private cKernel32 As cUniversalDLLCalls
    4. Private cShell32 As cUniversalDLLCalls
    5.  
    6. ' in form load
    7. Set cUser32 = New cUniversalDLLCalls
    8. Set cKernel32 = New cUniversalDLLCalls
    9. Set cShell32 = New cUniversalDLLCalls
    10. ' now use cUser32 for all user32.dll calls, cKernel32 for kernel32, cShell32 for shell32, etc
    Tip: When using the STR_ANSI flag to indicate the passed parameters include string values destined for ANSI functions, the class will convert the passed string to ANSI before calling the function. Doing so, default Locale is used for string conversion. If this is a problem, you should ensure you convert the string(s) to ANSI before passing it to the class. If you do this conversion, use STR_NONE & pass the string via StrPtr(). FYI: strings used strictly as a buffer for return values should always be passed via StrPtr() and the flag STR_NONE used; regardless if destined for ANSI or unicode functions. ANSI strings are never passed to COM interfaces. Always use StrPtr(theString) for any string parameters to those COM methods.
    vb Code:
    1. ' how to have a VB string contain ANSI vs Unicode
    2. myString = StrConv(myString, vbFromUnicode, [Locale ID])
    3. ' how to convert the returned ANSI string to a proper VB string
    4. myString = StrConv(myString, vbUnicode, [Locale ID])
    Tip: If you ever need to call a private COM interface function by its pointer/address, post #24 below shows how that can be done. A slight modification to the attached class is required.

    Change History
    - 28 Nov 2014. Added thunk/patch/workaround for passing a VB function address to a CDECL dll that expects a CDECL callback address. Sample found in post #10 below

    See this thread for more info. Win10 update broke paramarrays in some scenarios. Within the CallFunction_DLL & CallFunction_COM methods of the enclosed class, modify these lines of code in both methods:
    Code:
    Change this:
    vParams() = FunctionParameters()                    ' copy passed parameters, if any
    pCount = Abs(UBound(vParams) - LBound(vParams) + 1&)
    
    To this:
    If UBound(FunctionParameters) <> -1 Then
        vParams() = FunctionParameters()                ' copy passed parameters, if any
        pCount = Abs(UBound(vParams) - LBound(vParams) + 1&)
    End If
    Attached Files Attached Files
    Last edited by LaVolpe; Sep 2nd, 2019 at 10:12 AM. Reason: updated comments
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width