#include <iostream>
#include <cstring>
using namespace std;
using OLECHAR = wchar_t;
using BSTR = OLECHAR*;
using UINT = unsigned int;
UINT SysStringLen(BSTR str)
{
return (str) ? *(reinterpret_cast<UINT*>(str) - 1) : 0;
}
BSTR SysAllocStringLen(const OLECHAR *strIn, UINT ui)
{
char *res = new char[sizeof(UINT) + ((ui + 1) * sizeof(OLECHAR))];
*(reinterpret_cast<UINT*>(res)) = ui;
BSTR ptr = reinterpret_cast<BSTR>(res + sizeof(UINT));
if (strIn) memcpy(ptr, strIn, sizeof(OLECHAR) * ui);
ptr[ui] = L'\0';
return ptr;
}
BSTR SysAllocString(const OLECHAR *psz)
{
if (!psz) return nullptr;
const OLECHAR *ptr = psz;
UINT len = 0;
while (*ptr++ != L'\0') ++len;
return SysAllocStringLen(psz, len);
}
void SysFreeString(BSTR str)
{
if (str)
delete[] reinterpret_cast<char*>((reinterpret_cast<UINT*>(str)-1));
}
static BSTR Concatenate2BSTRs(BSTR a, BSTR b)
{
auto lengthA = SysStringLen(a);
auto lengthB = SysStringLen(b);
auto result = SysAllocStringLen(NULL, lengthA + 1 + lengthB);
if (result) {
memcpy(result, a, lengthA * sizeof(OLECHAR));
result[lengthA] = L' ';
memcpy(result + lengthA + 1, b, lengthB * sizeof(OLECHAR));
// no need to null-terminate manually, SysAllocStringLen() already did it...
//result[lengthA + 1 + lengthB] = L'\0';
}
return result;
}
int main()
{
BSTR a = SysAllocString(L"hello");
BSTR b = SysAllocString(L"world");
BSTR c = Concatenate2BSTRs(a, b);
wcout << SysStringLen(a) << L' ' << a << endl;
wcout << SysStringLen(b) << L' ' << b << endl;
wcout << SysStringLen(c) << L' ' << c << endl;
SysFreeString(a);
SysFreeString(b);
SysFreeString(c);
return 0;
}