--
Norm
To reply, change domain to an adult feline.
Two ways (1) turn off unicode when building your app. Right click
on your project (not the solution!) in the solution explorer window,
and get properties -> Configuration Properties -> General -> Character
Set : use multi-byte character set.
(2) Call the non-unicode version of the MS function. Basically,
append an 'A' to the function name (e.g. 'CreateFileA(...)') to force
a call to the non-unicode version, whether you're in unicode or
non-unicode builds. Or, append a 'W' (e.g. 'CreateFileW(...)') to
force a call to the unicode version whether you're in unicode or
non-unicode builds.
Nathan Mates
--
<*> Nathan Mates - personal webpage http://www.visi.com/~nathan/
# Programmer at Pandemic Studios -- http://www.pandemicstudios.com/
# NOT speaking for Pandemic Studios. "Care not what the neighbors
# think. What are the facts, and to how many decimal places?" -R.A. Heinlein
Hi, CreateFile (just like most other functions that take a string param) is
nothing more than a macro that during precompilation expands to CreateFileA
or CreateFileW depending on the definition of UNICODE (when UNICODE is
defined it will expand to CreateFileW). If you use Dependency Walker to view
kernel32.dll exports, you'll find two entry points for CreateFile:
CreateFileA and CreateFileW as you might expect (they're really two distinct
functions of the kernel).
To me the best approach here is still using TCHAR strings: TCHAR is itself a
macro that may expand to char or wchar_t depending on the definition of
_UNICODE. Header file tchar.h defines a lot of other useful macros for
string types and for string functions; an example:
...
...
#include <windows.h>
#include <tchar.h>
...
...
LPCTSTR filename = _T("myfile.txt");
CreateFile(filename,...);
...
...
The previous code fragment will be translated in something like the
following if you compile without UNICODE and _UNICODE defined:
...
...
const char *filename = "myfile.txt";
CreateFileA(filename,...);
...
...
and in something like this if you compile with UNICODE and _UNICODE defined:
...
...
const wchar_t *filename = L"myfile.txt";
CreateFileW(filename,...);
...
...
LPCTSTR, LPTSTR and so on are indeed the symbols that you'll find in the
official Microsoft documentation; for example:
HANDLE WINAPI CreateFile(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
);
Using this approach allows you to write code that compiles both with UNICODE
and _UNICODE defined and with UNICODE and _UNICODE undefined.
Sooner or later you will want (or need) to explicitly convert a TCHAR string
into a CHAR or WCHAR string: the most common scenario is (or, at least, was)
invoking an OLE function (OLE functions only exist in their "wide char"
form). Here the problem is that you might already have a wide char string in
your hands, but you might not; testing the size of TCHAR (using sizeof
operator) lets you know at compile time whether you are working with
_UNICODE defined or not.
Care must be taken when deciding what to do in the two cases: when
sizeof(TCHAR) == 1 you don't have much choice, you have to convert your
multi byte string to a wide char string, but when sizeof(TCHAR) > 1 you
might be tempted to simply cast your TCHAR string to a WCHAR string; this
could lead to hard to find bugs since it would subtly change the semantics
of your code: in the first case you are working (after conversion) with a
copy of the original string, but in the second case you are working with the
original string itself (functions you may want to pass it to might as well
overwrite it). My approach is (or, again, was) to make a copy of the string
even in the case in which a conversion is not needed.
Care must be also taken when you dinamically allocate string buffers; for
example if you are using HeapAlloc (that takes the number of bytes, not
characters, you want your buffer large) to allocate a buffer that can
accomodate 100 characters (including the NULL terminator), you'll have to
make a call similar to the following:
HeapAlloc(..., ..., 100 * sizeof(TCHAR));
Bye,
Stefano
Hi Stefano,
What an excellent answer !!!
Leslie.
Thank you Leslie. Just trying to help out :-)
Bye,
Stefano