Wednesday, July 20, 2005

Do not treat BSTR as a WCHAR*

Clear and loud - do not treat BSTR as a WCHAR*! For example, if we need to pass a BSTR into a function like the one below:

HRESULT CreateDevice(BSTR bstrDeviceID, IWiaItem **ppWiaItemRoot);

Never, ever do this:

CreateDevice(L"device1", &wiaItem);

By passing a WCHAR* as a BSTR, it may crash the code, because a BSTR also stores the length of the string as an integer immediately before the string buffer, so that if you call SysStringByteLen() on the BSTR, it'll return the number of bytes of the string. If you instead substitute a WCHAR* as BSTR, then SysStringByteLen() will probably fail. So, if the CreateDevice() function above calls SysStringByteLen() to the BSTR passed, the function will fail to work because you are actually passing a WCHAR*, which does not contain string length information before the string buffer.

The RIGHT way to do it is to use SysAllocString() to allocate for a BSTR from a WCHAR*, and then call SysFreeString() when it's done:

BSTR bstr = SysAllocString(L"device1");
CreateDevice(bstr, &wiaItem);
SysFreeString(bstr);

For more information, please consult MSDN Library's documentation for SysAllocString() and SysFreeString() and its associated section.

No comments: