Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7418669
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 29, 20262026-05-29T07:55:38+00:00 2026-05-29T07:55:38+00:00

I created an ATL COM server component (exe) some time ago. It exposed a

  • 0

I created an ATL COM server component (exe) some time ago. It exposed a few normal COM APIs (derived from IDispatch) and also fired a few COM events. The event mechanism was implemented using ATL IConnectionPointContainer. This COM server was initially used by a simple C# application, which directly added a reference to the COM server. Everything, the APIs and events, works fine in C# app.

Then came the requirement for the COM server to able to used with javascript in a webpage (IE). I therefore added IProvideClassInfo2, IObjectSafety implementation to the original COM class. However, the COM event never worked. Please refer to the IDL, COM class header file and event firing code below.

IDL:

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    // uuid replaced with dummy
    uuid(00000000-0000-0000-0000-000000000000), 
    dual,
    nonextensible,
    helpstring("ICtrl Interface"),
    pointer_default(unique)
]
interface ICtrl : IDispatch{
    [id(1), helpstring("method CtrlMethod1")] 
    HRESULT CtrlMethod1(void);
    [id(2), helpstring("method CtrlMethod2")] 
    HRESULT CtrlMethod2([in] ULONG Reason);
};


[
    // uuid replaced with dummy
    uuid(00000000-0000-0000-0000-000000000001), 
    version(1.0),
]
library MyControlLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
    [
        // uuid replaced with dummy 
        uuid(00000000-0000-0000-0000-000000000002)   
    ]
    dispinterface _ICtrlEvents
    {
        properties:
        methods:
            [id(1), helpstring("method OnCtrlEvent1")] 
            HRESULT OnCtrlEvent1([in] LONG ErrorCode);
            [id(2), helpstring("method OnCtrlEvent2")] 
            HRESULT OnCtrlEvent2([in] LONG ErrorCode);
    };


    [
        // uuid replaced with dummy
        uuid(00000000-0000-0000-0000-000000000003)       
    ]
    coclass Ctrl
    {
        [default] interface ICtrl;
        [default, source] dispinterface _ICtrlEvents;
    };
};

COM class header:

// CCtrl

class ATL_NO_VTABLE CCtrl :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CCtrl, &CLSID_Ctrl>,
    public IConnectionPointContainerImpl<CCtrl>,
    public CProxy_ICtrlEvents<CCtrl>,
    public IDispatchImpl<ICtrl, &IID_ICtrl, &LIBID_MyControlLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IDispatchImpl<_ICtrlEvents, &__uuidof(_ICtrlEvents), &LIBID_MyControlLib, /* wMajor = */ 1, /* wMinor = */ 0>,
    public IObjectSafetyImpl<CCtrl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
    public IProvideClassInfo2Impl<&CLSID_Ctrl, NULL, &LIBID_MyControlLib>
{
public:
    DECLARE_CLASSFACTORY_SINGLETON(CCtrl)
    CCtrl();


    DECLARE_REGISTRY_RESOURCEID(IDR_CTRL)


    BEGIN_COM_MAP(CCtrl)
        COM_INTERFACE_ENTRY(ICtrl)
        COM_INTERFACE_ENTRY2(IDispatch, ICtrl)
        COM_INTERFACE_ENTRY2(IDispatch, _ICtrlEvents)
        COM_INTERFACE_ENTRY(IConnectionPointContainer)
        COM_INTERFACE_ENTRY(_ICtrlEvents)
        COM_INTERFACE_ENTRY(IObjectSafety)
        COM_INTERFACE_ENTRY(IProvideClassInfo)
        COM_INTERFACE_ENTRY(IProvideClassInfo2)
    END_COM_MAP()

    BEGIN_CONNECTION_POINT_MAP(CCtrl)
        CONNECTION_POINT_ENTRY(__uuidof(_ICtrlEvents))
    END_CONNECTION_POINT_MAP()


    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct();
    void FinalRelease();

public:

    STDMETHOD(CtrlMethod1)(void);
    STDMETHOD(CtrlMethod2)(ULONG Reason);

};

OBJECT_ENTRY_AUTO(__uuidof(Ctrl), CCtrl)

ATL-generated event firing code:

#pragma once

template<class T>
class CProxy_ICtrlEvents :
    public ATL::IConnectionPointImpl<T, &__uuidof(_ICtrlEvents)>
{
public:

    HRESULT OnCtrlEvent1(LONG ErrorCode)
    {
        HRESULT hr = S_OK;
        T * pThis = static_cast<T *>(this);
        int cConnections = m_vec.GetSize();

        for (int iConnection = 0; iConnection < cConnections; iConnection++)
        {
            pThis->Lock();
            CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
            pThis->Unlock();

            IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

            if (pConnection)
            {
                CComVariant avarParams[1];
                avarParams[0] = ErrorCode;
                avarParams[0].vt = VT_I4;
                CComVariant varResult;

                DISPPARAMS params = { avarParams, NULL, 1, 0 };
                hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
            }
        }
        return hr;
    }
    HRESULT Fire_OnCtrlEvent2(LONG ErrorCode)
    {
        HRESULT hr = S_OK;
        T * pThis = static_cast<T *>(this);
        int cConnections = m_vec.GetSize();

        for (int iConnection = 0; iConnection < cConnections; iConnection++)
        {
            pThis->Lock();
            CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
            pThis->Unlock();

            IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

            if (pConnection)
            {
                CComVariant avarParams[1];
                avarParams[0] = ErrorCode;
                avarParams[0].vt = VT_I4;
                CComVariant varResult;

                DISPPARAMS params = { avarParams, NULL, 1, 0 };
                hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
            }
        }
        return hr;
    }
};

In the javascript code, the COM object is created using

var CtrlObj = new ActiveXObject('ProgID_of_Ctrl')

‘ProgID_of_Ctrl’ is mapped to __uuidof(Ctrl). In the IE debugger, the object created is of the type ICtrl. The COM APIs are visible, but the COM events are not. Any attempt to use CtrlObj.attachEvent() will result in javascript error. I’d expect CtrlObj should be of coclass (Ctrl) type, as was in the case of C# app. Whether there are any errors in COM_MAP section? Any comments and help are appreciated.

-CodeFarmer

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-29T07:55:39+00:00Added an answer on May 29, 2026 at 7:55 am

    From what I’ve read, you should be using the OBJECT tag and the SCRIPT for tag to hook up ATL/COM events in HTML. Something like this:

    <object
      id="myCtrlObj"
      classid="CLSID:00000000-0000-0000-0000-000000000003"
      height="32"
      width="32"/>
    
    <script language="javascript"
       id="myCtrlHandler1"
       event="OnCtrlEvent1()"
       for="myCtrlObj">
       alert("OnCtrlEvent1 fired");
    </script>
    
    <script language="javascript"
       id="myCtrlHandler2"
       event="OnCtrlEvent2(reason)"
       for="myCtrlObj">
        alert("OnCtrlEvent2 fired with parameter: " + reason.toString());
    </script>
    

    Because you’re using JScript, I sometimes like to cheat and make an IDispatch VARIANT property simulate the behavior of an event. In the following JScript code snippet note how OnCtrlEvent1 and OnCtrlEvent2 are being assigned to functions:

    function tst()
    {
      var ctrl = new ActiveXObject("MyControl.Ctrl");
      ctrl.OnCtrlEvent1 = myevent1;
      ctrl.OnCtrlEvent2 = myevent2;
      ctrl.CtrlMethod1();
      ctrl.CtrlMethod2();
    }
    
    function myevent1()
    {
      alert("Event1");
    }
    
    function myevent2(reason)
    {
      alert("Event2 " + reason.toString());
    }
    

    The trickery is done by handling it as a property in the IDL. Where those JScript functions are being passed to us as VARIANTs containing invokable IDispatch interfaces. Here’s my MyControl.idl:

    import "oaidl.idl";
    import "ocidl.idl";
    
    [
        object,
        // uuid replaced with dummy 
        uuid(00000000-0000-0000-0000-000000000000)  
        dual,
        nonextensible,
        helpstring("ICtrl Interface"),
        pointer_default(unique)
    ]
    interface ICtrl : IDispatch{
        [id(1), helpstring("method CtrlMethod1")] HRESULT CtrlMethod1(void);
        [id(2), helpstring("method CtrlMethod2")] HRESULT CtrlMethod2(void);
        [propget, id(3), helpstring("property OnCtrlEvent1")] HRESULT OnCtrlEvent1([out, retval] VARIANT* pVal);
        [propput, id(3), helpstring("property OnCtrlEvent1")] HRESULT OnCtrlEvent1([in] VARIANT newVal);
        [propget, id(4), helpstring("property OnCtrlEvent2")] HRESULT OnCtrlEvent2([out, retval] VARIANT* pVal);
        [propput, id(4), helpstring("property OnCtrlEvent2")] HRESULT OnCtrlEvent2([in] VARIANT newVal);
    };
    [
        // uuid replaced with dummy 
        uuid(00000000-0000-0000-0000-000000000001),
        version(1.0),
        helpstring("MyControl 1.0 Type Library")
    ]
    library MyControlLib
    {
        importlib("stdole2.tlb");
        [
            // uuid replaced with dummy 
            uuid(00000000-0000-0000-0000-000000000003)
            helpstring("Ctrl Class")
        ]
        coclass Ctrl
        {
            [default] interface ICtrl;
        };
    };
    

    Here’s my Ctrl.h where you see the JScript functions will be saved in VARIANT members:

    class ATL_NO_VTABLE CCtrl :
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CCtrl, &CLSID_Ctrl>,
        public IDispatchImpl<ICtrl, &IID_ICtrl, &LIBID_MyControlLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
    {
    public:
    DECLARE_REGISTRY_RESOURCEID(IDR_CTRL)
    
    BEGIN_COM_MAP(CCtrl)
        COM_INTERFACE_ENTRY(ICtrl)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()
    
    DECLARE_PROTECT_FINAL_CONSTRUCT()
    
        HRESULT FinalConstruct()
        {
            return S_OK;
        }
    
        void FinalRelease()
        {
        }
    
    public:
        STDMETHOD(CtrlMethod1)(void);
        STDMETHOD(CtrlMethod2)(void);
        STDMETHOD(get_OnCtrlEvent1)(VARIANT* pVal);
        STDMETHOD(put_OnCtrlEvent1)(VARIANT newVal);
        STDMETHOD(get_OnCtrlEvent2)(VARIANT* pVal);
        STDMETHOD(put_OnCtrlEvent2)(VARIANT newVal);
    
    private:
        CComVariant m_ctrlEvent1;
        CComVariant m_ctrlEvent2;
    
        STDMETHOD(Invoke_CtrlEvent1)();
        STDMETHOD(Invoke_CtrlEvent2)(LONG nReason);
    };
    
    OBJECT_ENTRY_AUTO(__uuidof(Ctrl), CCtrl)
    

    In Ctrl.cpp the trickery is we look for the JScript function’s IDispatch interfaces in those VARIANTs and with our ‘knowledge’ of the parameters, we invoke each event with the right parameters:

    #include "stdafx.h"
    #include "Ctrl.h"
    
    STDMETHODIMP CCtrl::CtrlMethod1(void)
    {
        Invoke_CtrlEvent1();
        return S_OK;
    }
    
    STDMETHODIMP CCtrl::CtrlMethod2(void)
    {
        Invoke_CtrlEvent2(12345);
        return S_OK;
    }
    
    STDMETHODIMP CCtrl::get_OnCtrlEvent1(VARIANT* pVal)
    {
        VariantInit(pVal);
        return VariantCopy(pVal, &m_ctrlEvent1);
        return S_OK;
    }
    
    STDMETHODIMP CCtrl::put_OnCtrlEvent1(VARIANT newVal)
    {
        m_ctrlEvent1 = newVal;
        return S_OK;
    }
    
    STDMETHODIMP CCtrl::get_OnCtrlEvent2(VARIANT* pVal)
    {
        VariantInit(pVal);
        return VariantCopy(pVal, &m_ctrlEvent2);
    }
    
    STDMETHODIMP CCtrl::put_OnCtrlEvent2(VARIANT newVal)
    {
        m_ctrlEvent2 = newVal;
        return S_OK;
    }
    
    STDMETHODIMP CCtrl::Invoke_CtrlEvent1()
    {
        if (m_ctrlEvent1.vt != VT_DISPATCH)
        {
            return S_OK;
        }
        DISPPARAMS DispParams = { 0, 0, 0, 0 };
        VARIANT Var = { 0 };
        return V_DISPATCH(&m_ctrlEvent1)->Invoke((DISPID) 0, IID_NULL, 0, DISPATCH_METHOD, &DispParams, &Var, NULL, NULL);
    }
    
    STDMETHODIMP CCtrl::Invoke_CtrlEvent2(LONG nReason)
    {
        if (m_ctrlEvent1.vt != VT_DISPATCH)
        {
            return S_OK;
        }
        VARIANTARG    Arg = {0};
        Arg.vt = VT_I4;
        Arg.lVal = nReason;
        DISPPARAMS DispParams = { &Arg, 0, 1, 0 };
        VARIANT Var = { 0 };
        return V_DISPATCH(&m_ctrlEvent2)->Invoke((DISPID) 0, IID_NULL, 0, DISPATCH_METHOD, &DispParams, &Var, NULL, NULL);
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I created ATL COM-server in VC++ 2005. I want to realize some interface defined
Have created a ATL COM project through which I am inserting Menu Items to
I've implemented an IFilter as a native VC++ ATL in-proc COM server. Windows Search
I'm trying to use a COM DLL from VC++ 2005. I created a TestCOMlib.dll
I have a ATL COM service exe (MyService.exe), which compiles and runs fine. If
I have an ATL exe server written with C++ (Visual Studio 2010, with merging
I created a ATL COM dll workspace with VS2008. It has generated MyCom.idl interface.
I have been working 2 days on creating a simple exe COM server, I
I created a dll file built (Project:win32 app, ATL and COM object using Visual
I have a ATL COM component method which has an [out] BSTR* parameter. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.