There are actually 3 questions here, the ones you explicitly asked, and the one you didn't. Let's get that last one out of the way first, as it tends to cause the most confusion:
What are those _t
-extensions offered by the Microsoft-provided CRT?
They are generic-text mappings, introduced to make it possible to write code that targets both ANSI-based systems (Win9x) as well as Unicode-based systems (Windows NT). They are macros that expand to the actual function calls, based on the _UNICODE
and _MBCS
preprocessor symbols. For example, the symbol _tprintf
expands to either printf
or wprintf
.
Likewise, the Windows API provides both ANSI and Unicode versions of the API calls. They, too, are preprocessor macros that expand to the actual API call, depending on the preprocessor symbol UNICODE
. For example, the CreateFile
symbol expands to CreateFileA
or CreateFileW
.
Generic-text mappings haven't been useful in the past two decades. Today, simply use the Unicode versions of the CRT and API calls (e.g. wprintf
and CreateFileW
). You can define _UNICODE
and UNICODE
for good measure, too, so that you don't accidentally call an ANSI version.
there are also libraries like strsafe.h
which have such functions like StringCchCopy()
, StringCchLength()
Those are safe variants of the CRT string manipulation calls. They are safer than e.g. strcpy
by providing the buffer size of the destination, similar to strncpy
. The latter, however, suffers from an awkward design decision, that causes the destination buffer to not get zero-terminated, in case the source won't fit. StringCchCopy
will always zero-terminate the destination buffer, and thus provides additional safety over the CRT implementations. (Note: C11 introduces safe variants, e.g. strncpy_s
, that will always zero-terminate the destination array, in case the input is valid. They also validate the input, calling the currently installed constraint handler when validation fails, thus providing even stronger safety than the strsafe.h implementations. The bounds-checked implementations are a conditional feature of C11.)
How important is it to use all of these types and special functions which Microsoft has provided on top of standard C when programming with Win32? Is it considered good practice to do away with all standard C functions and types and use entirely Microsoft wrappers?
It is not important at all. You can use whichever is more suitable in your scenario. If in doubt, writing portable (i.e. Standard C) code is generally preferable. You only ever want to call the Windows API calls, if you need the additional control they offer (e.g. HeapAlloc
allows more control over the allocation than malloc
does; likewise CreateFile
provides more options than fopen
).
Is it okay to mix standard C functions in with these Microsoft types and functions? For example, to use malloc()
instead of HeapAlloc()
, or to use printf()
instead of _tprintf()
and etc...?
In general, yes, as long as you match those calls: HeapFree
what you HeapAlloc
, free
what you malloc
. You must not mix HeapAlloc
and free
, for example. In case a Windows API call requires special memory management functions to be used, it is explicitly pointed out in the documentation. For example, if FormatMessage is requested to allocate the buffer to return data, it must be freed using LocalFree
. If you do not request the API to allocate a buffer, you can pass in a buffer allocated any way you like (malloc
, HeapAlloc
, IMalloc::Alloc
, etc.).