c++variantbstr

Can't get exact position of BSTR data in VARIANT struct


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:

enter image description here

Question:

Why wide doesn't point to the BSTR's exact position? What is the error in my code and how to fix it?


Solution

  • 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.