I have strange problem with reading BSTR
value from a VARIANT
struct.
I use following Javascript code to send data to C++ code:
external.CppCall("zhttShow", 1, "Y");
In an Invoke
function in my C++ code, I tried to access that data:
HRESULT STDMETHODCALLTYPE WebBrowser::Invoke(_In_ DISPID dispIdMember, _In_ REFIID riid, _In_ LCID lcid, _In_ WORD wFlags, _In_ DISPPARAMS *pp, _Out_opt_ VARIANT *pVarResult, _Out_opt_ EXCEPINFO *pExcepInfo, _Out_opt_ UINT *puArgErr)
{
if (dispIdMember == 100)
{
unsigned int k = pp->cArgs;
if (k > 0)
{
VARIANT *vVariant = &pp->rgvarg[k - 1];
if ((vVariant->vt & VT_BSTR) == VT_BSTR && vVariant->pvarVal->bstrVal)
{
wchar_t *wide = (wchar_t*)(vVariant->pvarVal->bstrVal);
// other code
}
}
}
}
In above code, wide
point to undefined position. If I get pointer of vVariant->pvarVal->bstrVal
it point to a position near the BSTR value:
VARIANT *vVariant = &pp->rgvarg[k - 1];
if ((vVariant->vt & VT_BSTR) == VT_BSTR && vVariant->pvarVal->bstrVal)
{
wchar_t *wide = (wchar_t*)(&vVariant->pvarVal->bstrVal);
// other code
}
wide
point to the position behide the BSTR
data 8 bytes, so instead get "zhttShow" string, I only get "Show". If I subtract wide
by 4 I will get desired data.
Bellow is debug screen for the second C++ code:
Why wide
doesn't point to the BSTR's exact position? What is the error in my code and how to fix it?
A BSTR
is not a wchar_t*
. It may look similar, but is not. And more importanlty, a wchar_t*
is definitely not a BSTR
. BSTRs have structure, a header that sits in front of the pointed-to value, so the real BSTR starts few bytes before the address. See BSTR Data Type:
A BSTR is a composite data type that consists of a length prefix, a data string, and a terminator.
This is why you should always use appropriate BSTR specific APIs. Best, use compiler support like _bstr_t
. To extract the BSTR from VARIANT correctly I would use a _variant_t
Extractor. Let the compiler deal with the details.