viral_mutant
viral_mutant

Reputation: 1003

How to use generic function GetDriveType

I have a C app that I need to compile in Windows. And I am really unable to wrap my head around the UNICODE and ANSI concept in Windows

I want to use GetDriveType function and there are 2 variables A and W. There is also a note here saying that GetDriveType is an alias to both and will select either based on some pre-processor.

But how should I call this function ?

This is what I am trying:

const TCHAR* path = "C:\\Users\\";
const TCHAR* trailing_slash = "\\";
size_t requiredSize = mbstowcs(NULL, path, 0);
TCHAR* win_path = (char*)malloc((requiredSize + 2) * sizeof(char));
UINT driveType = 0;
strncpy(win_path, path, requiredSize + 1);
strncat(win_path, trailing_slash, 2);

printf("Checking path: %s\n", win_path);

driveType = GetDriveType(win_path);
wprintf(L"Drive type is: %d\n", driveType);
if (driveType == DRIVE_FIXED)
    printf("Success\n");
else
    printf("Failure\n");
return 0;

It produces the result

Checking path: C:\Users\
Drive type is: 1
Failure

If I replace GetDriveType with GetDriveTypeA it returns the correct value 3 and succeeds.

I tried another variant too

size_t requiredSize = mbstowcs(NULL, path, 0);
uint32_t drive_type = 0;
const wchar_t *trailing_slash = L"\\";

wchar_t *win_path = (wchar_t*) malloc((requiredSize + 2) * sizeof(wchar_t));

/* Convert char* to wchar* */
size_t converted = mbstowcs(win_path, path, requiredSize+1);

/* Add a trailing backslash */
wcscat(win_path, trailing_slash);

/* Finally, check the path */
drive_type = GetDriveType(win_path);

I see this warning:

'function' : incompatible types - from 'wchar_t *' to 'LPCSTR'

So, which one to use ? How is it generic ? The path I will be reading is from an environment variable on Windows

What is TCHAR and wchar_t etc. ? I found this post, but could not understand much

This Microsoft post says

Depending on your preference, you can call the Unicode functions explicitly, such as SetWindowTextW, or use the macros

So is it Ok to use wchar_t everywhere and call GetDriveTypeW directly ?

Upvotes: 0

Views: 519

Answers (1)

Anders
Anders

Reputation: 101666

Back in the mid-90s you had Windows 95/98/ME that did not support Unicode and NT4/2000/XP that did. You could create source code that could compile with or without Unicode support just by changing the UNICODE define.

This type of code looks like this:

UINT type = GetDriveType(TEXT("c:\\"));

There is no function named GetDriveType, 99% of all functions that take a string parameter in Windows have two versions, in this case GetDriveTypeA and GetDriveTypeW.

Inside the Windows header files you have code that looks like this:

#ifdef UNICODE
#define GetDriveType GetDriveTypeW
#else
#define GetDriveType GetDriveTypeA
#endif

If UNICODE is defined before including windows.h the above code expands to:

UINT type = GetDriveTypeW(L"c:\\");

and if not:

UINT type = GetDriveTypeA("c:\\");

These days most applications should use Unicode. Whether you should use wchar_t/WCHAR and call GetDriveTypeW directly or still rely on the defines is a style question. There might be situations where you need to force the A or W function and that is OK as well.

The same applies to the C library with the _TEXT macro and the _tcs functions except that those are controlled by the _UNICODE define.

If you get a warning about incompatible string types then you are calling the wrong function or you have not added #define UNICODE (and _UNICODE). If you are compiling cross platform code intended for Unix you might have to convert from char* to a wide string in some places.

See also:

Upvotes: 2

Related Questions