FIX: BSTR Copied into CString Only up to First NULLID: Q117381
|
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.
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.
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.
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.
The following sample code demonstrates the problem and a workaround.
/* 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