In the following code, RegSetValueEx is only writing the first letter of my string. I've tried changing the sizes to just about anything I can think of, and I only ever get the first string. Any help is appreciated.
LPCWSTR path = L"Test String";
size_t size = wclsen(path) * sizeof(wchar_t);
DWORD dwResult = RegSetValueEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\My App",
0,
REG_SZ,
(LPBYTE)path,
test);
I've tried using path.size() * sizeof(wchar_t) and any number of other sizes I could think of, but nothing seems to work right. Any ideas?
RegSetValueEx() expects REG_SZ data to be provided as const TCHAR*, which in your case is const CHAR* per your compiler settings - as evident by the fact that you are able to pass a char* to the second parameter, which means you are actually calling RegSetValueExA(). Since you are providing a const WCHAR* to RegSetValueExA(), the first 0x00 byte gets interpreted as a null terminator, hence only a single character value gets written.
Your options are:
RegSetValueExW(..., (const BYTE*) path, ...
CString sPath(path); RegSetValueEx(..., (const BYTE*) (LPCTSTR) sPath, ...
Switch project settings to Unicode build
Sounds like you haven't defined UNICODE/_UNICODE before compiling, so the zero-byte in your wide string is being interpreted as signaling the end of the string.
Try using RegSetValueExW (and L"SOFTWARE\\My App") instead.
Related
I'm completely new to C++. In my program there's a function which has to take a LPCTSTR as a parameter. I want to convert it into a char*. What I tried is as follows,
char* GetChar(LPCTSTR var){
char* id = (char*)var;
.....
}
But while debugging I noticed that only first letter of var is assigned to id.
What have I done wrong?
(I tried various answers in StackOverflow about converting LPCTSTR to char* before coming to this solution. None of them worked for me.)
UPDATE
What i want is to get full string pointed by var to be treated as char*
It is much more useful to just pick a character set (wchar_t, or char), and just stick to it, in your application, since trying to use TCHAR, when trying to support both, may cause you some headaches. To be fair, today, you can just, safely, use wchar_t (or WCHAR, since from the current types you are using, I suspect that you are using Windows headers).
The problem that you have, is because casting a pointer does not have any impact on its contents. And, since, typically wchar_t is 2 bytes in size, while char is 1 byte in size, storing the value, that fits inside a char, in wchar_t, leaves 2nd byte of wchar_t set to \0. And when you try to print null(\0)-terminated string of wchar_ts as a string of chars, the printing function reaches the \0 character after reading the first symbol, and assumes it is the end of the string. \0 character in wchar_t is 2 bytes long.
For example, the string
LPCWSTR test = L"Hi!";
is stored in memory as:
48 00 69 00 21 00 00 00
If you want to convert between the wchar_t version of the string to char version, or vice-versa, there exist some functions, that can do the conversion, and since I noticed that you probably are using Windows headers (from LPCTSTR define), those functions are WideCharToMultiByte/ MultiByteToWideChar.
You may now start to think: I am not using wchar_t! I am using TCHAR!
Typically TCHAR is defined in the following way:
#ifdef UNICODE
typedef WCHAR TCHAR;
#else
typedef char TCHAR;
#endif
So you could do similar handling in your conversion code:
template<int N>
bool GetChar(LPCTSTR var, char (&out)[N])){
#ifdef UNICODE
return WideCharToMultiByte (CP_ACP, 0, var, -1, out, N, NULL, NULL) != 0;
#else
return strcpy_s (out, var) == 0;
#endif
}
Note, the return value of GetChar function is true if the function Succeeds; false - otherwise.
You code has told the compiler to convert var (which is a pointer) into a pointer to a character and then assign that converted value to id. The only thing it converts is the pointer value. It doesn't make any changes to the thing var points to, copy it, or convert it. So you haven't done anything to the string var points to.
It's not clear what you're trying to do. But your code doesn't really do anything but convert a pointer value without changing or affecting the thing pointed to in any way.
When you convert a LPCTSTR (a long pointer to a const tchar string) to a char*, you get a char* that points to a CTSTR (a const tchar string). What use is that? What sense does that make?
Most probaby LPCTSTR is const wchar_t*, so if you cast it to char* (which is Undefined Behaviour - as var could point to literal), the LSB byte (wchar_t under Visual Studio is 16bits) of *var is zero so it is treated as '\0' - which indicates end of string. So in the end you get only one char.
To convert LPCTSTR to char* you can use wsctombs for example, see here: Convert const wchar_t* to const char*.
Here's an easy solution I found based on other answers given here.
char* GetChar(LPCTSTR var){
char id[30];
int i = 0;
while (var[i] != '\0')
{
id[i] = (char)var[i];
i++;
}
id[i] = '\0';
UPDATE
As mentioned in comments this is not a good way to solve this problem. But if someone has the same problem and cannot understand any other solution, this will help a bit.
Therefore I won't remove this answer.
I want to use the Win API CreateProcess for which accepts 2nd parameter as "LPTSTR".
But I've the path to my exe in a char array. My VS2013 project (static library) is Unicode encoding type.
Code snippert below.
IN this line
"appPath = (LPTSTR)TestEXEPath;"
of the below code snippet where the type cast is happening, I see that the characters in "appPath" gets converted to some junk characters whereas the RHS of this expression "TestEXEPath" does have valid characters.
However tehre is no compilation error here. It is at run time this characters get corrupted in "appPath".
I know this typecast is creating this problem. But how do I solve this, how do I type cast this char array to LPTSTR typr which is needed by "CreateProcess() API.
Or is there any better way of doing this so as to avoid the char array itself.
LPTSTR appPath;
char cwd[_MAX_PATH];
getcwd(cwd, _MAX_PATH);
char TestEXEPath[_MAX_PATH];
strcpy(TestEXEPath, cwd);
strcat(TestEXEPath, "\\pwrtest.exe /sleep /c:1");
appPath = (LPTSTR)TestEXEPath; // The characters in this gets converted to some junk characters.
.......................
......................
CreateProcess(NULL, appPath, NULL, NULL, FALSE, 0, NULL, workingDir, &sI, &pI))
You are compiling for Unicode, so LPTSTR expands to wchar_t*. But you have ANSI data, char*. In that case it is simplest to call CreateProcessA and pass the ANSI data.
BOOL retval = CreateProcessA(..., TestExePath, ...));
If you want to avoid using ANSI functions then you can stick to wchar_t arrays.
whar_t exepath[MAX_PATH + 100]; // enough room for cwd and the rest of command line
GetCurrentDirectory(MAX_PATH, exepath);
wcscat(exepath, L"\\pwrtest.exe /sleep /c:1");
BOOL retval = CreateProcess(..., exepath, ...);
Note that I switched from getcwd to GetCurrentDirectory in order to get a wide char version of the working directory.
Note also that your code should check for errors. I neglected to do that here due to laze. But in your real code, you should not be as lazy as I have been.
The fact that you had to cast should have set off warning signals for you. Well, judging from the question, it probably did. When you write:
appPath = (LPTSTR)TestEXEPath;
That simply tells the compiler to treat TestEXEPath as LPTSTR whether or not it really is. And the fact that the program won't compile without the cast tells you that TestEXEPath is not LPTSTR. The cast does not change that reality, it merely shuts the compiler up. Always a bad move.
With unicode, LPTSTR points to an array of wchar_t and not an array of char.
Here some additional explantions.
Try with:
TCHAR TestExePath[_MAX_PATH];
And use wcscat() and wcscpy() and the other wide c-string handling functions in <cwchar>.
Also take a look at the very convenient ATL conversion classes here: http://msdn.microsoft.com/en-us/library/87zae4a3.aspx
LPTSTR str = CA2T(TestEXEPath);
Or even easier just
CreateProcess(NULL, CA2T(TestEXEPath), NULL, NULL, FALSE, 0, NULL, workingDir, &sI, &pI))
No destruction is needed.
I tried to use this code:
USES_CONVERSION;
LPWSTR temp = A2W(selectedFileName);
but when I check the temp variable, just get the first character
thanks in advance
If I recall correctly, CString is typedef'd to either CStringA or CStringW, depending on whether you're building Unicode or not.
LPWSTR is a "Long Pointer to a Wide STRing" -- aka: wchar_t*
If you want to pass a CString to a function that takes LPWSTR, you can do:
some_function(LPWSTR str);
// if building in unicode:
some_function(selectedFileName);
// if building in ansi:
some_function(CA2W(selectedFileName));
// The better way, especially if you're building in both string types:
some_function(CT2W(selectedFileName));
HOWEVER LPWSTR is non-const access to a string. Are you using a function that tries to modify the string? If so, you want to use an actual buffer, not a CString.
Also, when you "check" temp -- what do you mean? did you try cout << temp? Because that won't work (it will display just the first character):
char uses one byte per character. wchar_t uses two bytes per character. For plain english, when you convert it to wide strings, it uses the same bytes as the original string, but each character gets padded with a zero. Since the NULL terminator is also a zero, if you use a poor debugger or cout (which is uses ANSI text), you will only see the first character.
If you want to print a wide string to standard out, use wcout.
In short: You cannot. If you need a non-const pointer to the underlying character buffer of a CString object you need to call GetBuffer.
If you need a const pointer you can simply use static_cast<LPCWSTR>(selectedFilename).
I know this is a decently old question, but I had this same question and none of the previous answers worked for me.
This, however, did work for my unicode build:
LPWSTR temp = (LPWSTR)(LPCWSTR)selectedFileName;
LPWSTR is a "Long Pointer to a Wide String". It is like wchar*.
CString strTmp = "temp";
wchar* szTmp;
szTmp = new WCHAR[wcslen(strTmp) + 1];
wcscpy_s(szTmp, wcslen(strTmp) + 1, strTmp);
I am trying to convert a program for multibyte character to Unicode.
I have gone through the program and preceded the string literals with L so they look like L"string".
This has worked but I am now left with a C style string that won't conform. I have tried the L and putting it in TEXT() but the L gets added to the variable name -- not the string -- if I use TEXT().
I have tried making it a TCHAR but then it complains that it cannot convert a TCHAR to a char *.
What options am I left with?
I know C and C++ are different. It is an old in-house C library that has been used in C++ projects for several years now.
The std::mbstowcs function is what you are looking for:
char text[] = "something";
wchar_t wtext[20];
mbstowcs(wtext, text, strlen(text)+1);//Plus null
LPWSTR ptr = wtext;
for strings,
string text = "something";
wchar_t wtext[20];
mbstowcs(wtext, text.c_str(), text.length());//includes null
LPWSTR ptr = wtext;
--> ED: The "L" prefix only works on string literals, not variables. <--
The clean way to use mbstowcs is to call it twice to find the length of the result:
const char * cs = <your input char*>
size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);
// error if wn == size_t(-1)
wchar_t * buf = new wchar_t[wn + 1](); // value-initialize to 0 (see below)
wn = mbsrtowcs(buf, &cs, wn + 1, NULL);
// error if wn == size_t(-1)
assert(cs == NULL); // successful conversion
// result now in buf, return e.g. as std::wstring
delete[] buf;
Don't forget to call setlocale(LC_CTYPE, ""); at the beginning of your program!
The advantage over the Windows MultiByteToWideChar is that this is entirely standard C, although on Windows you might prefer the Windows API function anyway.
I usually wrap this method, along with the opposite one, in two conversion functions string->wstring and wstring->string. If you also add trivial overloads string->string and wstring->wstring, you can easily write code that compiles with the Winapi TCHAR typedef in any setting.
[Edit:] I added zero-initialization to buf, in case you plan to use the C array directly. I would usually return the result as std::wstring(buf, wn), though, but do beware if you plan on using C-style null-terminated arrays.[/]
In a multithreaded environment you should pass a thread-local conversion state to the function as its final (currently invisible) parameter.
Here is a small rant of mine on this topic.
I'm using the following in VC++ and it works like a charm for me.
CA2CT(charText)
This version, using the Windows API function MultiByteToWideChar(), handles the memory allocation for arbitrarily long input strings.
int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW>0)
{
output = new wchar_t[lenW];
::MultiByteToWideChar(CP_ACP, 0, input, lenA, output, lenW);
}
You may use CString, CStringA, CStringW to do automatic conversions and convert between these types. Further, you may also use CStrBuf, CStrBufA, CStrBufW to get RAII pattern modifiable strings
Im creating a DLL that shares memory between different applications.
The code that creates the shared memory looks like this:
#define NAME_SIZE 4
HANDLE hSharedFile;
create(char[NAME_SIZE] name)
{
hSharedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, (LPCSTR)name);
(...) //Other stuff that maps the view of the file etc.
}
It does not work. However if I replace name with a string it works:
SharedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, (LPCSTR)"MY_TEST_NAME");
How can I get this to work with the char array?
I have a java background where you would just use string all the time, what is a LPCSTR? And does this relate to whether my MS VC++ project is using Unicode or Multi-Byte character set
I suppose you should increase NAME_SIZE value.
Do not forget that array must be at least number of chars + 1 to hold \0 char at the end, which shows the end of the line.
LPCSTR is a pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters and defined as follows:
LPCSTR defined as typedef __nullterminated CONST CHAR *LPCSTR;
For example even if you have "Hello world" constant and it has 11 characters it will take 12 bytes in the memory.
If you are passing a string constant as an array you must add '\0' to the end like {'T','E','S','T', '\0'}
If you look at the documentation, you'll find that most Win32 functions take an LPCTSTR, which represents a string of TCHAR. Depending on whether you use Unicode (the default) or ANSI, TCHAR will expand to either wchar_t or char. Also, LPCWSTR and LPCSTR explicitly represent Unicode and ANSI strings respectively.
When you're developing for Win32, in most cases, it's best to follow suit and use LPCTSTR wherever you need strings, instead of explicit char arrays/pointers. Also, use the TEXT("...") macro to create the correct kind of string literals instead of just "...".
In your case though, I doubt this is causing a problem, since both your examples use only LPCSTR. You have also defined NAME_SIZE to be 4, could it be that your array is too small to hold the string you want?