What Does Lpcwstr Stand for and How Should It Be Handled With

What does LPCWSTR stand for and how should it be handled?

LPCWSTR stands for "Long Pointer to Constant Wide String". The W stands for Wide and means that the string is stored in a 2 byte character vs. the normal char. Common for any C/C++ code that has to deal with non-ASCII only strings.=

To get a normal C literal string to assign to a LPCWSTR, you need to prefix it with L

LPCWSTR a = L"TestWindow";

LPCWSTR ERROR C++ argument of type is incompatible with parameter of type

TCHAR is defined as either wchar_t or char, depending on whether UNICODE has been defined or not in your project setup, respectively.

OpenFileMapping() is a TCHAR-based preprocessor macro. It is defined as taking a const TCHAR* pointer to a null-terminated string in its 3rd parameter.

In reality, what happens is that OpenFileMapping() maps to either the OpenFileMappingA() (ANSI) or OpenFileMappingW() (Unicode) function, depending on whether UNICODE is defined:

// in winbase.h
WINBASEAPI
__out
HANDLE
WINAPI
OpenFileMappingA(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in LPCSTR lpName
);
WINBASEAPI
__out
HANDLE
WINAPI
OpenFileMappingW(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in LPCWSTR lpName
);
#ifdef UNICODE
#define OpenFileMapping OpenFileMappingW
#else
#define OpenFileMapping OpenFileMappingA
#endif // !UNICODE

Most legacy Win32 APIs that deal with character data are separated into A and W versions like this. Newer APIs introduced in recent years tend to be Unicode-only.

In your case, UNICODE is defined, so you are trying to pass a narrow string literal (const char[]) where a Unicode string (const wchar_t*) is expected. That is why you are getting a type mismatch error.

When using character/string literals with TCHAR-based APIs, use the TEXT() macro to ensure the literal uses the correct character type that TCHAR actually maps to, eg:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME TEXT("$pcars2$") // <-- HERE

void main(int argc, char* argv[])
{
HANDLE fileHandle = OpenFileMapping(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

Which is effectively doing the following when UNICODE is defined:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME L"$pcars2$"

void main(int argc, char* argv[])
{
HANDLE fileHandle = OpenFileMappingW(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

And doing this when UNICODE is not defined:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME "$pcars2$"

void main(int argc, char* argv[])
{
HANDLE fileHandle = OpenFileMappingA(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

However, modern coding practices should not rely on TCHAR APIs at all. They are meant for backwards compatibility with legacy Win9x/ME code during Microsoft's push to migrate users to adopt Unicode in the early 2000s. You should use the ANSI or Unicode functions directly instead as needed.

Using std::filesystem output as LPCWSTR

LPCWSTR is Microsoft's obfuscation of the const wchar_t* type, and filesystem paths conveniently have a wstring() member function. As you may recall, C++ strings give you access to their character buffer, too, via c_str().

So, entry.path().filename().wstring().c_str() is a LPCWSTR you can use (ugh!). Be careful to use that immediately, or store the result of wstring() somewhere for as long as you need the LPCWSTR to survive, because wstring() returns by value and you don't want a dangling pointer.

// Untested, but a logical adaptation of your code
const std::string path = "C:\\Programs";
std::experimental::filesystem::recursive_directory_iterator it(path);
for (const auto& entry : it)
{
const std::wstring filename = entry.path().filename().wstring();

FtpPutFile(
hIConnect,
filename.c_str(),
filename.c_str(),
FTP_TRANSFER_TYPE_BINARY,
0
);
}

Visual C++: Convert data type PCSTR to LPCWSTR

pHttpContext->GetRequest()->GetHeader("Accept", NULL);   

returns a PCSTR data type.

But I need to feed the WriteEventViewerLog with header as a
LPCWSTR, since one of the functions that I use inside the methods
only accepts the string in that format.

First, let's clarify the meaning of these "obscure" Windows API string typedefs:

PCSTR:   const char *    
LPCWSTR: const wchar_t *

So, both are pointers to read-only NUL-terminated C-style strings.

The difference is that PCSTR points to a char-based string; LPCWSTR points to a wchar_t-based string.

char-based strings can be of several "forms" (or encodings), e.g. simple ASCII, or Unicode UTF-8, or other "multi-byte" encodings.

In case of your header string, I assume it can be simple ASCII, or UTF-8 (note that ASCII is a proper subset of UTF-8).

wchar_t-based strings in Visual C++ are Unicode UTF-16 strings (and this is the "native" Unicode encoding used by most Win32 APIs).

So, what you have to do is to convert from a char-based string to a wchar_t-based one. Assuming that your char-based string represents a Unicode UTF-8 string (of which pure ASCII is a proper subset), you can use the MultiByteToWideChar() Win32 API to do the conversion.

Or you can use some helper classes to simplify the conversion task, for example ATL conversion helpers. In particular, the CA2W helper with the CP_UTF8 conversion flag can come in handy in your case:

#include <atlconv.h>  // for CA2W
...

// Get the header string in Unicode UTF-8
PCSTR header = pHttpContext->GetRequest()->GetHeader("Accept", nullptr);

// Convert the header string from UTF-8 to Unicode UTF-16
WriteEventViewerLog( CA2W(header, CP_UTF8) );

LPCSTR, LPCTSTR and LPTSTR

To answer the first part of your question:

LPCSTR is a pointer to a const string (LP means Long Pointer)

LPCTSTR is a pointer to a const TCHAR string, (TCHAR being either a wide char or char depending on whether UNICODE is defined in your project)

LPTSTR is a pointer to a (non-const) TCHAR string

In practice when talking about these in the past, we've left out the "pointer to a" phrase for simplicity, but as mentioned by lightness-races-in-orbit they are all pointers.

This is a great codeproject article describing C++ strings (see 2/3 the way down for a chart comparing the different types)



Related Topics



Leave a reply



Submit