argument of type "char *" is incompatible with parameter of type "STRSAFE_LPCWSTR

4.5k Views Asked by At

I have the following:

DYNAMIC_TIME_ZONE_INFORMATION dtzRecorder;
GetDynamicTimeZoneInformation(&dtzRecorder);

I normally do the following to copy a new name:

StringCchCopy(dtzRecorder.TimeZoneKeyName, 128, L"GMT Standard Time");

But now I need to do the following:

char tzKey[51];

std::string timezone("someTimeZOneName");
strncpy_s(MyStruct.tzKey, timezone.c_str(), _TRUNCATE);

StringCchCopy(dtzRecorder.TimeZoneKeyName, 128, MyStruct.tzKey); <--Error

But I get the error:

argument of type "char *" is incompatible with parameter of type "STRSAFE_LPCWSTR"

How can I copy this to dtzRecorder.TimeZoneKeyName??

2

There are 2 best solutions below

2
wimh On

The basic problem is that dtzRecorder.TimeZoneKeyName is a wide string (wchar_t[]), but tzKey is a narrow string (char[]).

The easiest way to solve it would be to use wchar_t for tzKey, too:

wchar_t tzKey[51];

std::wstring timezone(L"someTimeZOneName");
wcsncpy_s(MyStruct.tzKey, timezone.c_str(), _TRUNCATE);

StringCchCopy(dtzRecorder.TimeZoneKeyName, 128, MyStruct.tzKey); 
2
kfsone On

LPSTR is Microsoft for "Long Pointer to STRing" or char *, LPWSTR is Microsoft for "Long Pointer to Wide-c STring" or wchar_t *. Additionally LPCSTR and LPCWSTR refer to const variants.

The error you see comes from passing an LPCSTR (const character pointer) to a function expecting an LPWSTR (non-const unicode/wide character pointer).

Wide string constants are denoted with an L prefix (L"wide"), generally have the type wchar_t* and require a variant of std::string called std::wstring.

Which is the default for most Windows system calls is handled by a general project setting "Character Set", if it is "Unicode" then wide strings are required. Support for this is provided by <tchar.h> see https://msdn.microsoft.com/en-us/library/dybsewaf.aspx

#include <tchar.h>

// tchar doesn't help with std::string/std::wstring, so use this helper.
#ifdef _UNICODE
#define TSTRING std::wstring
#else
#define TSTRING std::string
#endif

// or as Matt points out
typedef std::basic_string<_TCHAR> TSTRING;

// Usage
TCHAR tzKey[51];  // will be char or wchar_t accordingly
TSTRING timezone(_T("timezonename")); // string or wstring accordingly
_tscncpy_s(tzKey, timezone.c_str(), _TRUNCATE);

Alternatively you can just be explicit about using wides

wchar_t tzKey[51]; // note: this is not 51 bytes
std::wstring timezone(L"timezonename");
wscncpy_s(tzKey, timezone.c_str(), _TRUNCATE);

As an aside, why not simply do this:

std::wstring timezone(L"tzname");
timezone.erase(50); // limit length

Why waste time copying the value when you could just insert a null-terminator at the limit?