I'm trying to use memcpy to convert a TCHAR array into a BYTE array but the memcpy function is only copying 1 TCHAR from the tchar array into the byte array.
I have no idea why this is happening.
Here is a code snippet.
TCHAR test[] = L"This is a test string, its purpose is to do some testing!";
DWORD testSizeBytes = sizeof(TCHAR) * lstrlen(test);
LPBYTE byteArray = new BYTE[testSizeBytes+1];
memcpy(byteArray,test,testSizeBytes);
If I used this snippet the byteArray would just contain 'T';
Any help would be appreciated.
EDIT: I fixed the issue (It was a typo). The code I wrote here works flawlessly. My compiler is in a windows VM so I had to retype it here and unknowingly fixed the typo.
TCHAR test[] = L"This is a test string, its purpose is to do some testing!";
This is a wide character (wchar_t) string. On Windows, with UNICODE defined, that is UTF-16. In UTF-16, the character 'T' is 2 bytes. The first byte corresponds to the ASCII value of 'T' (decimal 84). The second byte is a 0. So when you copy this over to your byte array, it looks like a null terminated c-string with 1 character. The other characters are there, but they come after the end of the apparent c-string, so your debugger is apparently ignoring them.
As the comment from ajshort mentioned, your debugger probably does not realize you are dealing with an array.
If you can use your debugger to look at memory, try to look at the memory location byteArray + 1 and byteArray + 2, etc.
I am not on Windows, so I cannot tell you how to do that, but the equivalent gdb command would be x byteArray + 1.
Related
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 new to C++. My program is crashing and I am trying to find out why. At some point of the code, I generate a random number and I copy a file with the original filename followed by the number
char CopyPath[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_MYMUSIC, NULL, 0, CopyPath);
int randomNumber = 101 + rand()%1000000000;
char randomBuffer[15];
itoa(randomNumber, randomBuffer, 10);
char computerName[MAX_COMPUTERNAME_LENGTH+1];
DWORD size = MAX_COMPUTERNAME_LENGTH;
if(!GetComputerName(computerName, &size))
strcat(computerName, "FAIL");
strcat(CopyPath,"\\");
strcat(CopyPath, computerName);
strcat(CopyPath, "-");
strcat(CopyPath, randomBuffer);
copyFile(oldpath, CopyPath);
I suspect the crash happens somewhere here. My question is, since I haven't declared all the values of CopyPath, there is a crash. Should i declare it as
char CopyPath[MAX_PATH] = {'\0'}
Could this be the problem??
if(!GetComputerName(computerName, &size))
strcat(computerName, "FAIL");
This should be strcpy, as there's no valid string in computerName to append to.
Also, you probably should be calling SHGetFolderPathA since you are passing a buffer of char (and not TCHAR).
Prefer using std::string than C array for holding string info like that as it provides proper copying and concatenation through = and + operators.
Not sure what causes the crash in your case. My guess that it must be a buffer overrun problem. Do you consider space for the ending \0 character in MAX_PATH constant?
I believe you've understood from other comments that your code is not very good (at least due to style and possible buffer overruns).
Taking into account only your specific question - you are right - problem is in the uninitialized char array, which doesn't represent a C-string because it has to be zero-terminated. As you probably know strcat works on C strings. So changing from:
char CopyPath[MAX_PATH]; // this is not a C-string
to
char CopyPath[MAX_PATH] = {0}; // this is a C-string (empty though)
will fix this particular problem.
EDIT: this approach should be taken with any buffer that you are going to use with strcat as concatenation target, which in your case is computerName
here's what I am trying to do:
typedef uint16_t uchar16_t;
uchar16_t buf[32];
// buf will contain timezone information like GMT-6, Eastern Daylight Time, etc
char * str = "Test";
for (int i = 0; i <= strlen(str); i++)
buf[i] = str[i];
I guess that's not correct since uchar16_t would contain 2 bytes and str contains 1 byte.
What is it that I am supposed to do ?
Strlen? buf[32]? Trying to destroy the universe?
You want to use a wstringstream.
std::wstringstream lols;
lols << "Test";
std::wstring cakes;
lols >> cakes;
Edit#Comment:
You shouldn't use strlen because any decent string system allows embedded zeros, and strlen is seriously slow. In addition, you didn't resize your buffer as needed, so if you had a string of size > 31 you would get a buffer overflow. In addition, you would have to (if you did dynamically size your buffer) manually free it afterwards. Both of these things are serious failings of the C string system. My example code makes your standard library writer do all the work and avoid all these problems for you.
That's actually OK if your string will always be ASCII. To do it correctly, the portable function is mbstowcs which assumes you're converting from the default locale or if you're on Windows then there's API functions that let you specify the source code page explicitly.
Your code will work, as long as str is ASCII; calling strlen() in the loop condition is probably a bad idea, though. It might be easier to just use swprintf() if it's available on your system:
uchar16_t buf[32];
char *str = "Test";
swprintf(buf, sizeof buf, "%s", str);
Have a look here.
Also, is there a good reason you are defining your own type?
If you have a (narrow) char string, you cannot convert it to
a wchar_t string by setting your locale to "C" and then passing
the string through mbstowcs(). That's because the "C" locale specifies
a -particular- character encoding, and that encoding might not match
the encoding of the execution character set, so mbstowcs() might
map the characters to something unexpected, or could even fail
(if the execution character set happened to use encodings that
were incompatible with the encoding structure for the C locale
character set.)
Thus, in order to convert a char
string into a wider string, you have
to copy the chars one by one into an
array of wchar_t . If you need to work
with Unicode or utf-16 or whatever
after that, then wcstombs() is what
you should look at.
I need to convert CString to BYTE array. I don't know why, but everything that I found in internet does not work :(
For example, I have
CString str = _T("string");
I've been trying so
1)
BYTE *pbBuffer = (BYTE*)(LPCTSTR)str;
2)
BYTE *pbBuffer = new BYTE[str.GetLength()+1];
memcpy(pbBuffer, (VOID*)(LPCTSTR)StrRegID, str.GetLength());
3)
BYTE *pbBuffer = (BYTE*)str.GetString();
And always pbBuffer contains just first letter of str
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
is 2
But if I use const string:
BYTE *pbBuffer = (BYTE*)"string";
pbBuffer contains whole string
Where is my mistake?
Your CString is Unicode (two bytes per character) and you try to interpret it as ANSI (one byte per character). This leads to results you don't expect.
Instead of casting the underlying buffer into char* you need to convert the data. Use WideCharToMultiByte() for that.
You are probably compiling with unicode. This means that your CString contains wchar_t instead of char. Converting a wchar_t pointer to a char pointer causes you to interpret the second byte of the first wchar_t as a string terminator (since that by is 0 for the most common characters)
When using visual studio you should always use _T() to declare string literals and TCHAR as your character type. In your case:
BYTE* pBuffer = (BYTE*)(LPCTSTR)str;
You get the buffer, but every other byte is most probably zero.
Use a CStringA if you need an ANSI string. (But then skip the _T() when initializing it)
I'm using VS2005 with "using Unicode Character Set" option
typedef unsigned char BYTE;
typedef unsigned long DWORD;
BYTE m_bGeraet[0xFF];
DWORD m_dwAdresse[0xFF];
How do i make the code work?
MessageBox (m_bGeraet[0], _T("Display Content"));
MessageBox (m_dwAdresse[0], _T("Display Content"));
It looks like you might need some help with the C language itself, and I recommend you find a beginner's book on C that is not about Windows programming.
MessageBox() only displays C-style strings which are arrays of type char which contain a character with ASCII value 0. This zero character is the NUL character, and such strings are said to be "NUL-terminated" or "Zero-terminated." Only the characters prior to the NUL are displayed when the string is printed, or copied when the string is concatenated. However, if there is no NUL character in the array, then the string is not properly terminated and an attempt to display it could lead to a crash, or to "garbage" being displayed, as in: "Can I have a beer?#BT&I10)aaX?.
The szTitle and szText arguments to MessageBox() expect char * which are pointers to this type of string.
If you attempt to pass a BYTE instead of a char *, the value of the BYTE will be mistakenly treated as an address. MessageBox() will attempt to access memory at the value "specified" by the BYTE and an Access Violation will occur.
One solution to this problem is to allocate a buffer of type char and use snprintf_s to transcribe your data values to string representations.
For example:
char output_buffer[1024];
snprintf_s(output_buffer, dimensionof(output_buffer), "Geraet = 0x%02X", m_bGeraet[i]);
MessageBox(hwnd_parent, output_buffer, "Message from me:", MB_OK);
Would display a MessageBox with a message reading something like "Geraet = 0x35".
If it's essential that BYTE is 1-byte then you have to (optionally) convert your byte strings to wide strings using mbstowcs.
//easy way for bytes is to do this
CString sTemp;
sTemp.Format("my byte = %d", bySomeVal);
MessageBox(sTemp);
//for a DWORD try
sTemp.Format("Dword is %lu", dwSomeVal);
MessageBox(sTemp);
if you using MessageBox, i would suggest soetming like AfxMessageBox...