FIX: BSTR Copied into CString Only up to First NULL

ID: Q117381


The information in this article applies to:


SYMPTOMS

When your code calls an MFC object linking and embedding (OLE) Automation method that returns a BASIC string (BSTR), a CString is created that contains only the bytes up to the first NULL in the BSTR.


CAUSE

You can create MFC OLE Automation clients by deriving your class from the class COleDispatchDriver and adding member functions that wrap calls to COleDispatchDriver::InvokeHelper. InvokeHelper then calls InvokeHelperV, which in turn calls IDispatch::Invoke.

COleDispatchDriver::InvokeHelperV, in OLEDISP2.CPP, is responsible for managing input parameters and return values for the call to IDispatch::Invoke. When the string returned from Invoke is a BSTR, it is converted to an MFC CString object by the following code:


   case VT_BSTR:
      if (vaResult.bstrVal == NULL)
         AfxThrowMemoryException();
      *(CString*)pvRet = vaResult.bstrVal;
      SysFreeString(vaResult.bstrVal);
      break; 
Here is the operator= being called:

   const CString& CString::operator=(const char* psz)
   {

      AssignCopy(SafeStrlen(psz), psz);
      return *this;
   } 
SafeStrlen only returns the length up to the first NULL, so that bytes are copied only up to the first NULL.


RESOLUTION

Prototyping the function to return a variant (VT_VARIANT) rather than a BSTR (VT_BSTR) solves this problem. The entire variant returned from Invoke is passed back to the wrapper function in the class derived from COleDispatchDriver. This function can then remove and copy the BSTR manually.


STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug was corrected in Microsoft Visual C++ version 1.51 for Windows.


MORE INFORMATION

The following sample code demonstrates the problem and a workaround.

Sample Code


/* Compile options needed: none
*/ 

// This code will only return the bytes up to the first NULL
// in the BSTR.

   CString MyApplication::GetCaption()
   {
      CString result;
      GetProperty(0x8b, VT_BSTR, (void*)&result);
      return result;
   }

// This code will return the entire BSTR.
// 

   BSTR MyApplication::GetCaption()
   {
      VARIANT result;
      GetProperty(0x8b, VT_VARIANT, (void*)&result);

      ASSERT(result.vt == VT_BSTR);

      ::SysAllocString(va_arg(argList, LPTSTR));

      return result.bstrVal;
   } 

Additional query words: 1.50 2.50


Keywords          : kbole kb16bitonly kbMFC kbVC 
Version           : 1.50
Platform          : WINDOWS 
Issue type        : 

Last Reviewed: July 28, 1999