WideCharToMultiByte
-
Following code gives assertion fail under VS 7 (sometime with 6) void StringFromWide(const wchar_t* pwch, int cch, char *psz, int szLen) { if(cch == 0) { cch = wcslen(pwch); // TODO it will display only first four char } if(cch > szLen) cch = szLen; WideCharToMultiByte(CP_ACP, 0, pwch, cch, psz, cch, NULL, NULL); psz[cch] = '\0'; } As workaround I'm using following code void StringFromWide(const wchar_t* pwch, int cch, char *psz, int szLen) { size_t szt; if(cch == 0) { szt = wcslen(pwch); cch = sizeof(szt) ;// but this will retrieve four chars only } if(cch > szLen) cch = szLen; WideCharToMultiByte(CP_ACP, 0, pwch, cch, psz, cch, NULL, NULL); psz[cch] = '\0'; } What is missing here?
-
Following code gives assertion fail under VS 7 (sometime with 6) void StringFromWide(const wchar_t* pwch, int cch, char *psz, int szLen) { if(cch == 0) { cch = wcslen(pwch); // TODO it will display only first four char } if(cch > szLen) cch = szLen; WideCharToMultiByte(CP_ACP, 0, pwch, cch, psz, cch, NULL, NULL); psz[cch] = '\0'; } As workaround I'm using following code void StringFromWide(const wchar_t* pwch, int cch, char *psz, int szLen) { size_t szt; if(cch == 0) { szt = wcslen(pwch); cch = sizeof(szt) ;// but this will retrieve four chars only } if(cch > szLen) cch = szLen; WideCharToMultiByte(CP_ACP, 0, pwch, cch, psz, cch, NULL, NULL); psz[cch] = '\0'; } What is missing here?
I assume that valid null terminated strings are passed to the functions and that cch is the length (not including the ending NULL) of the original string (0 means compute) and szLen is the buffer size of the output including the room for the NULL terminator. In such case, then if cch is greater or equal to szLen, psz[cch] will write one character after the end of the buffer (it should be psz[cch-1]). Also the alternate code is wrong. The reason why it will often works is because szLen is greater that 4 in your case. Doing a sizeof on the returned size return the size of a variable of type size_t (which is probably an unsigned int or an unsigned long) and not the value hold in the variable. Note that you uses assertion in your code to validate what you are doing. For ex. adding ASSERT(strlen(psz) < szLen) would have typically catch the error after the memory is overwritten but before the application crash so it would then be easy to apply the fix! You should also check the result of the call to WideCharToMultiByte. If it fails (and it can), the output will contains garbage (if it wasn't initialized externally). Also if output is really multibyte, then some UNICODE characters may be converted to 2 multibyte characters and it that case, the code would be incorrect. Finally, it may be easier (and less error-prone) to uses macros like W2A (or classes like _bstr_t, CString, CComBSTR,...) to make conversions if you do not needs the extra functionality accessible only from the API. In a few words: length and size are different... Knows what you are doing. Also, you may allocate a bit more memory than necessary to be on the safe side. Philippe Mori