-2

I need to create a "SAFEARRAY of bytes" from a "BSTR" to pass it to a function.

i have tried following ways to create a BYTE* from BSTR.

Is there any other ways to convert a BSTR to BYTE* which won't lead to lose any data?

BSTR bstr = SysAllocString(L"This is a basic string which encoded in UTF-16!!ɏ");
int len = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL);
BYTE *pByte = new BYTE[len];

if (len > 0)
{
    /*
    for(int i=0; i<len; i++)
    {
        pByte[i] = (BYTE) bstr[i]; //using this way may lead to lose data.
    }
    */
    WideCharToMultiByte(CP_UTF8, 0, bstr, -1, (LPSTR)&pByte[0], len, NULL, NULL);
    //cout << "Byte Array: " << pByte << endl;
}

delete []pByte;
Deadlock
  • 4,211
  • 1
  • 20
  • 25
  • 2
    What isn't working with the second `WideCharToMultiByte` call? A complete, concrete example of when it fails would be helpful. – chris Oct 14 '17 at 03:34
  • Your code has nothing to do with [`SAFEARRAY`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx). `BSTR` is safe. I am guessing that you just want to convert UTF-16 to UTF-8. The wrong Unicode conversion can lead to loss of data. You don't need `BSTR` for that. Put `SysFreeString` to cleanup after `SysAllocString` – Barmak Shemirani Oct 14 '17 at 05:56
  • Please provide a [mcve]. – IInspectable Oct 14 '17 at 08:28

1 Answers1

1

SAFEARRAY and BSTR are both ActiveX/COM automation types. BSTR is the official string type, so why would any COM/Automation function want to take a string as a SAFEARRAY of bytes instead of as a BSTR? Even then, it is possible to pass raw bytes via BSTR using SysAllocStringByteLen() instead of a SAFEARRAY.

Now, to answer your question, simply use SafeArrayCreate() to create the byte array, then you can populate it however you want. For example:

BSTR bstr = SysAllocString(L"This is a basic string which encoded in UTF-16!!ɏ");
int len = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL);
SAFEARRAYBOUND bound;
bound.cElements = len;
bound.lLbound = 0;
SAFEARRAY *sa = SafeArrayCreate(VT_U1, 1, &bound);
if (len > 0) {
    char *data;
    SafeArrayAccessData(sa, (void**)&data);
    WideCharToMultiByte(CP_UTF8, 0, bstr, -1, data, len, NULL, NULL);
    //cout << "Byte Array: " << data << endl;
    SafeArrayUnaccessData(sa);
}
SafeArrayDestroy(sa);
SysFreeString(bstr) ;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770