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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CrownRockAuthor Commented:
Adjusted points to 250
0
mikeblasCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.