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 typedef
s:
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
Restrict C++ Template Parameter to Subclass
What Is a Void Pointer and What Is a Null Pointer
Performance Cost of Passing by Value VS. by Reference or by Pointer
Difference in Behavior While Using Dynamic_Cast with Reference and Pointers
Error: Could Not Resolve Sdk Path for 'Macosx10.8'
So Why Is I = ++I + 1 Well-Defined in C++11
How to Make G++ Preprocessor Output a Newline in a MACro
What Is the Meaning of Numeric_Limits<Double>::Digits10
X86 Mul Instruction from VS 2008/2010
Lambda Capture as Const Reference
Why Is Std::Fill(0) Slower Than Std::Fill(1)
What Is Wrong with Using Inline Functions
Is the Ranged Based for Loop Beneficial to Performance
Class Template Argument Deduction Not Working with Alias Template