AXControl Get DisplayName ambient from container

There is a problem retrieving the DisplayName ambient from my control container to my ActiveX control.  The DisplayName is always returned as a null string.  I suspected that the BSTR 16-bit string was not be converted correctly to an 8-bit CString.  This may be the case as VariantChangeType() is not behaving correctly. I found that in COleDipatchDriver::InvokHelper() when the Variant is coorced at VariantChangeType(), the BSTR value (bstrVal) gets replaced with a null string.
Is it just me, or is this a bug?

Background: Platform: NT 4.0 Service Pack 4  Language: VC++ 5.0 Service Pack 3 Applications: MFC (non-unicode)

The ActiveX control detects the change and trys to retrieve the DisplayName:

/// CAlphaCtrl.cpp
void CAlphaCtrl::OnAmbientPropertyChange(DISPID dispid)
{
 switch (dispid)
 {
  case  DSPID_AMBIENT_DISPLAYNAME:
  ASSERT(FALSE);

  // Same results in either call

  m_cszDialogName = AmbientDisplayName();
  GetAmbientProperty(dispid,VT_BSTR,(void *)&csz);

 m_cszDialogName = csz;
 SetModifiedFlag();
 gpclControl->UpdateData(FALSE);
 break;
 }
 COleControl::OnAmbientPropertyChange(dispid);
}


The DisplayName value is forced in my MDI view class as follows.
The BSTR in the variant (pVar) is assigned correctly.

/// CMyView.cpp
BOOL CMyView::OnAmbientProperty(COleControlSite* pSite, DISPID dispid, VARIANT* pvar)
{
 BOOL bRet=FALSE;
 _bstr_t clBstrt;
 CString csz;

 static int iCnt=0;

 iCnt+=1;

 csz.Format("Test %d",iCnt);
 switch (dispid)
 {
  case DISPID_AMBIENT_DISPLAYNAME:
      SysFreeString(V_BSTR(pvar));
      clBstrt = csz;
      V_BSTR(pvar) = SysAllocString(clBstrt);
      bRet = TRUE;
      break;
 }

 if(!bRet)
  bRet = baseCView::OnAmbientProperty(pSite, dispid, pvar);
}




Here the value is passed correctly until VariantChangeType seemingly corrupts it.
(ie. vaResult is correct before VariantChangeType executes).
vtRet is of type VT_BSTR. The return code (sc) is OK (== 0), however at that point vaResult.bstrVal == "";

///OLEDisp2.cpp
void COleDispatchDriver::InvokeHelperV(DISPID dwDispID,
       WORD wFlags, VARTYPE vtRet, void* pvRet, const BYTE*
       pbParamInfo, va_list argList)
{
 USES_CONVERSION;

 ....

 if (vtRet != VT_EMPTY)
 {
 // convert return value
 if (vtRet != VT_VARIANT)
            {
////////////// Here lies the problem em ///////////////////////
  SCODE sc = VariantChangeType(&vaResult, &vaResult, 0, vtRet);
 if (FAILED(sc))
 {
   TRACE0("Warning: automation return value coercion failed.\n");
   VariantClear(&vaResult);

  AfxThrowOleException(sc);
 }
  ASSERT(vtRet == vaResult.vt);
 }

 .....
}
CrownRockAsked:
Who is Participating?
 
mikeblasConnect With a Mentor Commented:
You don't show your code clearly.  Specifically, what data types are you throwing around in void CAlphaCtrl::OnAmbientPropertyChange()?  What data types are cz and m_cszDialogName ?


Meanwhile, your OnAmbientProperty() implementation is pretty broken. (So bad that I'm surprised it compiled--you didn't return a value!) I fixed it up for you; let me know if you have questions about my fixes.

BOOL CMyView::OnAmbientProperty(COleControlSite* pSite, DISPID dispid, VARIANT* pvar)
{
   BOOL bRet = FALSE;

   //REVIEW: I don't know what this is for.
   static int iCnt=0;
   iCnt+=1;

   switch (dispid)
   {
     case DISPID_AMBIENT_DISPLAYNAME:
     {
        ASSESRT(pvar != NULL);

        CString csz;
        csz.Format("Test %d",iCnt);

        VariantClear(pvar);

        V_BSTR(pvar) = csz.AllocSysString();
        V_VT(pvar) = VT_BSTR;
        bRet = TRUE;
        break;
     }
   }

   if(!bRet)
     bRet = baseCView::OnAmbientProperty(pSite, dispid, pvar);

   return bRet;
}

..B ekiM
0
 
CrownRockAuthor Commented:
Adjusted points to 250
0
 
CrownRockAuthor Commented:
Good answer Mike - you're the man.

Unfortunatly, these V_BSTR macros are
new to me and by not including:
 
V_VT(pvar) = VT_BSTR;

pvar obviously wasn't initialized
correctly.

By the way, I look forward to seeing
an updated version of "MFC 4 Programming"
0
 
mikeblasCommented:

 > pvar obviously wasn't initialized
 > correctly.

Right. But you also didn't need to use _bstr_t, and you didn't need to call SysAllocString() on _bstr_t. (If you were using _bstr_t, you'd call it's detach() method.)

 > By the way, I look forward to seeing
 > an updated version of "MFC 4 Programming"

A book about MFC 5 was released about two months ago--maybe a little longer, and a book on VC++ 6.0 came out in June of 1999.

..B ekiM
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.