FIX: BSTR Copied into CString Only up to First NULLLast reviewed: September 18, 1997Article ID: Q117381 |
1.50
WINDOWS
kbprg kbfixlist kbbuglist
The information in this article applies to:
SYMPTOMSWhen 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.
CAUSEYou 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.
RESOLUTIONPrototyping 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.
STATUSMicrosoft 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 INFORMATIONThe 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 reference words: 1.50 2.50
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |