Link to home
Start Free TrialLog in
Avatar of swh062500
swh062500

asked on

Writing an OLE Automation Container with VC++

I want to access a simple OLE Automation Server I wrote in VB, but I can't get it working. Ok, I am a relative newbie to OLE programming with VC++, but I think I did everything as described in the books (Brockschmidt etc.), but no.

Anyway, here's what I am doing. I'd be very grateful if anybody has an idea what's wrong.

I first initialize OLE, create the object, get its IDispatch interface and the DISPID for a property called 'Color' with the following statements:

    CoInitialize(NULL);

    hr=::CLSIDFromProgID(T2COLE(_T("LayoutServer.Layout")),
                         &CLSID_LayoutServer);

    hr = CoCreateInstance(CLSID_LayoutServer, NULL,                           CLSCTX_LOCAL_SERVER,
                          IID_IDispatch,                           (LPVOID*)&m_pIDispatch);
   
    hr = NameToID(T2OLE(_T("Color")), &m_DILayoutColor);

This seems to work fine (hr is always 0, I deleted these checks here to save some space). The variables used are defined as follows:

        IDispatch* m_pIDispatch;        //Interface we use
        DISPID     m_DILayoutColor;     //long (I4) Prop

        CLSID       CLSID_LayoutServer;

The NameToID function is just a wrapper around GetIDsOfNames without all the parameters of that function to retrieve DISPID's more easily:

   HRESULT CLayoutClientDlg::NameToID(OLECHAR* pszName,                                          DISPID* pDispID)
   {
         HRESULT hr;

         hr = m_pIDispatch->GetIDsOfNames(IID_NULL,                                      &pszName, 1,
                                     LOCALE_SYSTEM_DEFAULT,                                      pDispID);
         return hr;
  }


Now I should be able to get and put the value of this property. I have the following variables to provide the necessary parameters to Invoke:

        HRESULT       hr;
        DISPPARAMS    dp;
        VARIANTARG    va;
        EXCEPINFO     ei;
        unsigned int  uArgErr;

Also two macros to facilitate the setting of parameters:

   #define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \
       {\
       (dp).cArgs=numArgs;\
       (dp).rgvarg=pvArgs;\
       (dp).cNamedArgs=numNamed;\
       (dp).rgdispidNamedArgs=pNamed;\
       }

   #define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL)

To get the value of the color property, I know call Invoke as follows:

        SETNOPARAMS(dp);
        hr = m_pIDispatch->Invoke(m_DILayoutColor,                                   IID_NULL,
                                  LOCALE_SYSTEM_DEFAULT,                                   DISPATCH_PROPERTYGET,                                   &dp, &va, &ei, &uArgErr);

But, the application crashes with an error message "No handle exception in LayoutClient.exe (Oleaut32.dll): 0xC0000005 Access violation" (this is only a translation
of the original japanese message, so it might look somewhat different on an English system). Why?

Setting the property as follows:

        va.vt = VT_I4;
        va.lVal = 255L;

        SETDISPPARAMS(dp, 1, &va, 0, NULL);
        hr = m_pIDispatch->Invoke(m_DILayoutColor,                                   IID_NULL,
                                  LOCALE_SYSTEM_DEFAULT,                                   DISPATCH_PROPERTYPUT,                                   &dp, &va, &ei, &uArgErr);

This produces no error (hr=0), but it doesn't set the value correctly. If I have a VB client reading the value, it is not 255 (some other, non-constant value). 2 VB clients can exchange data this way (one client setting, one reading).

Any help appreciated, thanks.

-Stephan
ASKER CERTIFIED SOLUTION
Avatar of mikeblas
mikeblas

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial