Results 1 to 10 of 10

Thread: COM dynamic proxy

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,296

    COM dynamic proxy

    I had a little fun with chatgpt this week. C dll is a dynamic proxy that wraps an arbitrary inner COM object. Lets you override methods or add new methods to an existing object. Wanted this for a looongg time and chatgpt pulled if off with some coercion.

    we are basically creating our own IDispatchEx interface in about 600 lines of pure C++ for languages which don't support it. Final release dll with /MT is about 130kb

    C Dll debug messages are output to Elroys: http://www.vbforums.com/showthread.p...g-Print-Window

    You can find a compiled copy and maybe more up to date source here:

    https://github.com/dzzie/js4vb/tree/master/dynproxy

    Note: more stuff has been added to this as js4vb grew such as a custom CallByNameEx and event sink code.

    Readme below.

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


    # dynproxy — Dynamic COM Proxy for VB6 (and beyond)

    > *The missing dynamic layer VB6 never had.*
    > A raw C++ COM proxy that turns VB6 into a dynamic runtime.

    ---

    ## What This Does

    dynproxy.dll lets **VB6 (or any COM client)** create objects that respond to *any* property or method call dynamically — even ones that don’t exist.

    It acts like a **programmable middle-man** between VB6 and COM:

    - Intercepts every IDispatch::Invoke and GetIDsOfNames.
    - Can forward to a real inner COM object or fake a response.
    - Lets your **VB6 class** decide in real time what happens.

    **No ATL. No MFC. Pure COM.**

    ---

    ## Why It Exists

    No good reason..just a wish list

    dynproxy fixes that: it lets you build **dynamic COM façades** that VB6 treats as real.

    Now you can:
    - Build **synthetic COM trees** (o.Kitty.Meow = 12).
    - **Mock** sprawling APIs (Acrobat, Office, etc.).
    - **Log or reroute** calls before they hit the real object.
    - **Bridge** VB6 to scripting engines or remote APIs.
    - Turn VB6 into something approaching Python or JavaScript’s Proxy.

    ---

    ## How It Works

    ### The Proxy Pipeline

    text

    VB6 Runtime
    (calls o.SomeMethod)

    IDispatch::Invoke("SomeMethod")


    ProxyDispatch
    (dynproxy.dll)


    1 Inner object Forward call

    2 Resolver class
    • Call VB6: ResolveGetID / ResolveInvoke
    • Pass name, args, and DISPATCH_ flags

    3 Neither Invent a DISPID and let resolver fake it


    ### Call Flow Details

    1. **VB6** late-bound calls always go through IDispatch::Invoke.
    2. The proxy catches that and checks a cache (name DISPID).
    3. If unknown, it calls:

    * inner->GetIDsOfNames() first (default), or
    * resolver->ResolveGetID() first if resolver-wins mode is active.
    4. The final Invoke routes accordingly:

    * Forward to the inner COM object, **or**
    * Call your resolver’s ResolveInvoke(name, flags, args()).

    ---

    ## VB6 Resolver Interface

    Your resolver implements two public methods:

    Code:
    Public Function ResolveGetID(ByVal name As String) As Long
        ' Return non-zero to claim this name
        ' Return 0 to let the inner object handle it
    End Function
    
    Public Function ResolveInvoke(ByVal name As String, _
                                  ByVal flags As Long, _
                                  args() As Variant) As Variant
        ' Handle the call
    End Function
    ### flags meanings

    | Flag | Hex | Meaning |
    | ---- | --- | ------------------------------ |
    | 1 | 0x1 | DISPATCH_METHOD (Sub/Function) |
    | 2 | 0x2 | DISPATCH_PROPERTYGET |
    | 4 | 0x4 | DISPATCH_PROPERTYPUT |
    | 8 | 0x8 | DISPATCH_PROPERTYPUTREF |

    ---

    ## Example: Dynamic Tree

    Code:
    ' --- CResolver.cls ---
    Option Explicit
    Private m_children As Object, m_props As Object
    
    Private Sub Class_Initialize()
        Set m_children = CreateObject("Scripting.Dictionary")
        Set m_props = CreateObject("Scripting.Dictionary")
    End Sub
    
    Public Function ResolveGetID(ByVal name As String) As Long
        Select Case LCase$(name)
            Case "kitty", "meow": ResolveGetID = -30000
            Case Else: ResolveGetID = 0
        End Select
    End Function
    
    Public Function ResolveInvoke(ByVal name As String, ByVal flags As Long, args() As Variant) As Variant
        Dim lname As String: lname = LCase$(name)
    
        ' Property GET
        If (flags And 2) <> 0 Then
            If lname = "kitty" Then
                If Not m_children.Exists("kitty") Then
                    Dim child As CResolver: Set child = New CResolver
                    Dim p As Long: p = CreateProxyForObjectRaw(0&, ObjPtr(child))
                    Dim o As Object: Set o = ObjectFromPtr(p)
                    m_children.Add "kitty", o
                End If
                Set ResolveInvoke = m_children("kitty"): Exit Function
            End If
            If m_props.Exists(lname) Then ResolveInvoke = m_props(lname)
            Exit Function
        End If
    
        ' Property PUT
        If (flags And 4) <> 0 Then
            m_props(lname) = args(0): Exit Function
        End If
    End Function
    Demo:

    Code:
    Dim root As New CResolver
    Dim p As Long: p = CreateProxyForObjectRaw(0&, ObjPtr(root))
    Dim o As Object: Set o = ObjectFromPtr(p)
    
    o.kitty.meow = 12
    Debug.Print o.kitty.meow   '  12
    ---

    ## Key Exports
    Code:
    | Function                                                   | Description                                            |
    | ---------------------------------------------------------- | ------------------------------------------------------ |
    | CreateProxyForObjectRaw(inner, resolver)                 | Create proxy with an optional inner and resolver.      |
    | CreateProxyForObjectRawEx(inner, resolver, resolverWins) | Same, but choose resolver-first at creation.           |
    | SetProxyResolverWins(proxy, enable)                      | Toggle resolver-first mode at runtime.                 |
    | ClearProxyNameCache(proxy)                               | Clear cached DISPIDs (call after toggling).            |
    | SetProxyOverride(proxy, name, dispid)                    | Force a name to route to resolver.                     |
    | ReleaseDispatchRaw(ptr)                                  | Manual release if you never wrapped the pointer in VB. |
    All exports are stdcall, callable from VB6 directly.

    ---

    ## Build Notes

    * **Language:** C++17
    * **No** ATL or MFC
    * **Link:** oleaut32.lib
    * Build as **Win32 DLL**


    cl /LD /std:c++17 dynproxy.cpp oleaut32.lib /EHsc /Fe:dynproxy.dll


    ## Why It’s Cool

    * Intercepts and rewrites COM calls in real time.
    * Lets VB6 behave like Python or JavaScript — dynamic and late-bound.
    * Mocks any proprietary API instantly (no IDL hell).
    * Enables powerful debugging, scripting, and adapter layers.

    ---

    ## Caveats

    * Works only for **late-bound** (IDispatch) calls.
    * STA threading only (standard VB6 COM).
    * Don’t double-release VB6-wrapped objects.
    * VB6 only runs 32-bit, so the DLL should be x86.

    ---

    ## * Credits & Origin

    Implemented in pure C++ because ATL/MFC got in the way.

    This project turns that pain into power — a *universal COM proxy* that lets old tech do new tricks.

    ---

    **Platform:** Win32 COM
    **Language:** C++ / VB6
    **Keywords:** VB6, COM, IDispatch, dynamic proxy, API mocking, automation, Acrobat



    ---
    Last edited by dz32; Jan 26th, 2026 at 09:46 AM.

  2. #2
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    632

    Re: COM dynamic proxy

    Very interesting.
    This is the part that interests me most.
    Code:
    ---
    
    ## ? Why It’s Cool
    
    * Intercepts and rewrites COM calls in real time.
    * Lets VB6 behave like Python or JavaScript — dynamic and late-bound.
    * Mocks any proprietary API instantly (no IDL hell).
    * Enables powerful debugging, scripting, and adapter layers.
    ---
    I really like interoperability. If you make any more discoveries, I'd love to try them out.

    Best regards

  3. #3
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,541

    Re: COM dynamic proxy

    Is it possible to support events?You develop a 64-bit, then what? Then develop a 32-bit proxy, 32-bit DLL, or control
    This allows both 64-bit vbas to use 32-bit DLLs, OCX.

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,296

    Re: COM dynamic proxy

    I have no idea how late bound events are handled, feed that cpp file into chatgpt and ask if it can add events. it probably can?

    It will compile as an x64 dll so my guess is it will work there.

    This would not be the approach for a 64bit vba to use 32bit dlls, its not that type of proxy.

    https://getyarn.io/yarn-clip/b6ba1c0...2-506130866f56
    Last edited by dz32; Oct 14th, 2025 at 02:01 PM.

  5. #5
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: COM dynamic proxy

    Curious as to what parts necessitated writing in C++? Certainly one could write implementations of IDispatch/IDispatchEx in VB/tB.

    64bit=twinBASIC

  6. #6

  7. #7

    Thread Starter
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,296

    Re: COM dynamic proxy

    You probably could pull it off in vb6 directly with lite weight objects and/or vtable patching.

    In C/C++ this is just very standard COM plumbing though making it a natural choice.

    Personally I rather stay within a languages strength zone. This is also step 1 of where I may take it.
    I have some more ideas where a vb version would not work.

  8. #8
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: COM dynamic proxy

    Quote Originally Posted by wqweto View Post
    I was wondering how many LOC a TB implementation would take for such a dynamic COM proxy. (This one is 600.)
    The functionality should be coverable completely, from what I've shown here, in plain, straight forward VB6-code:
    https://www.vbforums.com/showthread....BaseInterfaces
    (in less than 600 lines, I guess).

    Olaf

  9. #9
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,541

    Re: COM dynamic proxy

    Quote Originally Posted by dz32 View Post
    I have no idea how late bound events are handled, feed that cpp file into chatgpt and ask if it can add events. it probably can?

    It will compile as an x64 dll so my guess is it will work there.

    This would not be the approach for a 64bit vba to use 32bit dlls, its not that type of proxy.

    https://getyarn.io/yarn-clip/b6ba1c0...2-506130866f56
    Can you test how to call net DLL dynamically. And automatically late bind event

    For example, epplus. DLL, nopi. DLL, dynamic call them to create tables, read and fill in the contents of cells.

    Dynamically create. Net CEF. DLL, election. DLL, if it can also support cross-platform.

    A Linux version of the com object wrapper that creates a virtual registry of its own.Or implement it without using the registry.

    How to run com objects on Linux, com + + technology
    Last edited by xiaoyao; Oct 21st, 2025 at 02:51 PM.

  10. #10
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,541

    Re: COM dynamic proxy

    ??wine,I simulated a callback for a mouse event. It turned out that the mobile phone was very hot. I'm running an Android version of winE or something like that.

    It runs very slowly on the computer. The same is true on Android phones, and it consumes a lot of power. But at least it can run, uh, windows programs.

    It would be best if we could get rid of the wine system and directly use C + + to implement com objects on Linux.

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