Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CreateFile and CreateFileW in Visual C++ 2008 Express Edition

1,350 views
Skip to first unread message

Alistair Harwood

unread,
Mar 21, 2009, 6:21:06 AM3/21/09
to
I'm trying to write a program that can take a disk letter I give it and then
open it using CreateFile but when I pass the variable to it, it complains
about not being a wide char. Does CreateFile default to CreateFileW in
Visual C++ 2008? If so how can i rectify this problem to pass it ordinary
char strings.
Thanks

Norman Bullen

unread,
Mar 21, 2009, 11:49:59 AM3/21/09
to
If you remove UNICODE and _UNICODE from the list of defined pre-compiler
names in your project, your program will use ordinary char strings.
(Remember to make this change for both DEBUG and RELEASE configurations.)

--
Norm

To reply, change domain to an adult feline.

Nathan Mates

unread,
Mar 21, 2009, 3:43:55 PM3/21/09
to
In article <gq2f1k$uc1$1...@aioe.org>,

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

Stefano Altavilla

unread,
Mar 22, 2009, 10:05:18 AM3/22/09
to
"Alistair Harwood" <dinkl...@hotmail.com> ha scritto nel messaggio
news:gq2f1k$uc1$1...@aioe.org...

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


Leslie Milburn

unread,
Mar 30, 2009, 6:35:39 AM3/30/09
to

"Stefano Altavilla" <stefano....@tin.it> wrote in message
news:49c645a7$0$1115$4faf...@reader3.news.tin.it...

Hi Stefano,

What an excellent answer !!!

Leslie.


Stefano Altavilla

unread,
Apr 1, 2009, 5:30:47 PM4/1/09
to
"Leslie Milburn" <CD...@NOSPAM.bigpond.com> ha scritto nel messaggio
news:%f1Al.1566$Bm1...@news-server.bigpond.net.au...

>
> Hi Stefano,
>
> What an excellent answer !!!
>
> Leslie.

Thank you Leslie. Just trying to help out :-)

Bye,

Stefano


0 new messages