Article ID: 138813
All strings that are passed to and received from 32-bit OLE APIs and interface methods use Unicode. This requires applications that use ANSI strings to convert them to Unicode before passing them to OLE and to convert the Unicode strings that are received from OLE to ANSI. This article demonstrates how these conversions can be done.
Windows NT implements Unicode (or wide character) and ANSI versions of Win32 functions that take string parameters. However Windows 95 does not implement the Unicode version of most Win32 functions that take string parameters. Instead it implements only the ANSI versions of these functions.
A major exception to this rule is 32-bit OLE. 32-bit OLE APIs and interface methods on Windows NT and Windows 95 use Unicode exclusively. ANSI versions of these functions are not implemented either on Windows NT or Windows 95.
This means that a 32-bit application that needs to run on both Windows 95 and Windows NT must use the ANSI versions of the non-OLE Win32 functions and must convert ANSI strings to Unicode before they are passed to OLE.
A 32-bit Unicode application that runs only on Windows NT need not use any ANSI/Unicode conversion functions.
Win32 provides MultiByteToWideChar and WideCharToMultiByte to convert ANSI strings to Unicode and Unicode strings to ANSI. This article provides AnsiToUnicode and UnicodeToAnsi, which uses these functions for ANSI/Unicode conversion.
Sample use of these functions is as follows. CoTaskMemFree is used to free the converted string if CoTaskMemAlloc was used to allocate the string. The converted string must not be freed if it is returned through an out-parameter to another OLE component, because that component is responsible for freeing the string. LPOLESTR is a pointer to a Unicode string.
NOTE: Comments in AnsiToUnicode and UnicodeToAnsi regarding the allocator that is used to allocate the converted string. CoTaskMemAlloc (the OLE allocator) is required to be used only if the resultant string will be passed to another OLE component and if that component can free the string. This means that strings that are passed as in-parameters to OLE interface methods need not use the OLE allocator. Strings that are passed as in-out-parameters or returned through out-parameters or in- out-parameters must be allocated using the OLE allocator.
String constants can be converted to Unicode at compile time by using the OLESTR macro. For example:
Another example of ANSI/Unicode conversion routines can be found in the Microsoft Foundation Classes (MFC) source code which ships with the Visual C++ 4.0 compiler. These routines are described in MFC Technote 59: 'Using MFC MBCS/Unicode Conversion Macros'. The definition these macros OLE2T, T2OLE, OLE2CT, T2COLE, A2W, W2A, A2CW, W2CA and USES_CONVERSION are in \msdev\mfc\include\afxpriv.h. Also see AfxA2WHelper and AfxW2AHelper in the MFC source code in \msdev\mfc\src and the use of OLE2T, T2OLE, OLE2CT and T2COLE in the MFC source code in \msdev\mfc\src. These functions allow code to be compiled either for Unicode or ANSI depending on whether the _UNICODE preprocessor definition has been made. For example, the CreateFileMoniker call in the above example can be made as follows with the MFC macros:
If _UNICODE is defined, T2OLE is defined as follows:
If _UNICODE is not defined, T2OLE is defined as follows:
T in T2OLE indicates that the type being converted to an OLE string (Unicode string) is a Unicode string when _UNICODE is defined and an ANSI string when _UNICODE is not defined. Similarly LPTSTR is defined as a pointer to a Unicode string when _UNICODE is defined and as a pointer to an ANSI string when _UNICODE is not defined. T2OLE doesn't do any conversion when _UNICODE is defined (LPTSTR == LPOLESTR). When Unicode is not defined, A2W is called. A2W converts an ANSI string to Unicode as follows:
AfxA2WHelper uses MultiByteToWideChar to do the conversion.
The MFC conversion macros use _alloca to allocate space from the program stack for the converted string. The space is automatically deallocated when the procedure call has completed. OLE requires the OLE allocator to be used for all strings (data) that will be allocated by one component and freed by another. This means that strings passed through out- parameters and in-out-parameters of OLE interfaces must be allocated with the OLE allocator. In-parameters need not be allocated with the OLE allocator because the caller is responsible for freeing them. Most Linking/Embedding OLE interfaces and API pass strings as in-parameters. Consequently the MFC conversion macros can be used in most cases. The MFC conversion macros cannot be used for in-out parameters or for returning values through out-parameters because they do not allocate space using the OLE allocator. AnsiToUnicode and UnicodeToAnsi can be used in these cases.
Yet another set of Unicode/ANSI conversion routines can be found in Don Box's column on OLE in Microsoft Systems Journal, August 1995, Vol. 10 No. 8, Page 86. Don Box defines a C++ class with a cast operator which will return a Unicode/ANSI converted string. The allocated space is automatically freed when the object goes out of scope. This class can be modified to allocate using the OLE allocator and to not free the allocated space for strings that are passed through in-out or out- parameters.
One of the classes, String16, from Don Box's column which converts an ANSI string to Unicode, follows. Another class, String8, that is similar to this one is used for ANSI to Unicode conversion. The CreateFileMoniker call from the previous example can be made as follows with this class:
In the above code, an instance of String16 is created. The constructor of the class will convert the ANSI string to Unicode. The language implementation will call the cast operator, operator const wchar_t *, to cast this parameter to the type of of CreateFileMoniker's first parameter. The cast operator will return the Unicode string which is passed to CreateFileMoniker. The object will destruct when in goes out of scope.