These systems used ASCII as their primary way of working, which means the Windows API used ASCII strings rather than UTF-16. A further complication arises when double-byte encoding was introduced, where each character was one or two bytes in size, losing the advantage of random access.
The net result of all this is that the Windows API contains UTF-16 and ASCII functions for compatibility reasons.
Using the ASCII functions will cause the string to be converted to UTF-16 and then used with the UTF-16 function
*In_opt
, In
*
This may be useful for humans as well as static analysis tools. The C++ compiler currently ignores these annotations, but the static analyzer available in Visual Studio Enterprise editions uses it to detect potential errors before actually running the program
DWORD FormatMessageW(
_In_ DWORD dwFlags,
_In_opt_ LPCVOID lpSource,
_In_ DWORD dwMessageId,
_In_ DWORD dwLanguageId,
_When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) != 0, _At_((LPWSTR*)lpBuf\\
fer, _Outptr_result_z_))
_When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) == 0, _Out_writes_z_(nSiz\\
e))
LPWSTR lpBuffer,
_In_ DWORD nSize,
_In_opt_ va_list *Arguments);
if we specify dwFlags
including FORMAT_MESSAGE_ALLOCATE_BUFFER
flag, then the function will allocate the memory for result and return us the pointer where the string is located in mem
. Hence why we need a pointer to the pointer to LPWSTR which is LPWSTR*
. or
LPWSTR text;
(LPWSTR)&text
Long Pinter Constant T String, where the T is
LPCTSTR is in fact a typedef with one of the following definitions:
So in CreateMutexW it is defined as LPCWSTR.
typedef LPCSTR LPCTSTR; // const char* (UNICODE not defined)
typedef LPCWSTR LPCTSTR; // const wchar_t* (UNICODE defined)
const char name1[] = "Hello"; // 6 bytes (including NULL terminator)
const wchar_t name2[] = L"Hello"; // 12 bytes (including UTF-16 NULL terminat\\
or)