February 10, 2003

Wide Character String to an ANSI String (ATL 3.0)

To convert a Wide Character String to an ANSI String is by using OLE2A or W2A, and their equivalent Macros.

Unsafe (bad) Code:

BSTR bstrString = SysAllocString (L"Hello World!");
WCHAR* pwszWCharString = L"Hello World!";

USES_CONVERSION;
LPSTR pszCharStringFromBSTR = OLE2A (bstrString);
LPSTR pszCharStringFromLPWSTR = W2A (pwszWCharString);
// ...
SysFreeString (bstrString); // Important


However this is not safest way because OLE2A, W2A causes Stack Overflows (due to _alloca) if you use it in loop. (Note - this issue is resolved in ATL 7.0)

To avoid stack overflow don't use of USES_CONVERSION macro and use WideCharToMultiByte as shown in following examples. Here overflow problem not occurs because 'char*' or 'LPSTR' allocated on the heap/free store .

Code to convert BSTR to LPSTR:

char* ConvertBSTRToLPSTR (BSTR bstrToConvert)
{
LPSTR pszOut = NULL;
if (bstrToConvert != NULL)
{
int nInputStrLen = SysStringLen (bstrToConvert);

// Double NULL Termination
int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, bstrToConvert, nInputStrLen, NULL, 0, 0, 0) + 2;
pszOut = new char [nOutputStrLen];

if (pszOut)
{
memset (pszOut, 0x00, sizeof (char)*nOutputStrLen);
WideCharToMultiByte (CP_ACP, 0, bstrToConvert, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
}
}
return pszOut;
}


Code to covert 'WCHAR' String to 'LPSTR':

char* ConvertLPWSTRToLPSTR (LPWSTR lpwszToConvert)
{
LPSTR pszOut = NULL;
if (lpwszToConvert != NULL)
{
int nInputStrLen = wcslen (lpwszToConvert);

// Double NULL Termination
int nOutputStrLen = WideCharToMultiByte (CP_ACP, 0, lpwszToConvert, nInputStrLen, NULL, 0, 0, 0) + 2;
pszOut = new char [nOutputStrLen];

if (pszOut)
{
memset (pszOut, 0x00, nOutputStrLen);
WideCharToMultiByte(CP_ACP, 0, lpwszToConvert, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
}
}
return pszOut;
}