How can I convert PCWSTR to a char[] or wchar_t[] - c++

I'm trying to create a file, where one of the parameters has been passed in to the method and is of the type PCWSTR. My code creates a .url file and saves the Url into the file:
wchar_t array1[] = "[InternetShortcut]\nURL=";
wchar_t array2[] = pdwFavoriteUrl;
wchar_t * DataBuffer = new wchar_t[wcslen(array1) + std::strlen(array2) + 1];
std::strcpy(DataBuffer,array1);
std::strcat(DataBuffer,array2);
// Write data to file
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
bErrorFlag = WriteFile(hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);
if (FALSE == bErrorFlag)
{
// Log error
hr = E_FAIL;
}
else
{
if (dwBytesWritten != dwBytesToWrite)
{
// Log error
hr = E_FAIL;
}
else
{
// Log success
hr = S_OK;
//_tprintf(TEXT("Wrote %d bytes to %s successfully.\n"), dwBytesWritten, argv[1]);
}
}
CloseHandle(hFile);
I am aware that the code will not compile as-is, since there are conflicting versions of unicode and non-unicode string methods. The line of interest is this one:
wchar_t array2[] = pdwFavoriteUrl;
pdwFavoriteUrl is of type PCWSTR and there is no way around it. Please help convert it to wchar_t[] (preferred) or char[].

AFAIK PCWSTR is just an alias for wchar_t* and in case it is null-terminated that the simplest thing to do would be using it to construct an object of type std::wstring. Just pass it to constructor:
PCWSTR wcstr = L"My String";
std::wstring wstr(wcstr);
and work with std::wstring objects instead of doing evil stuff such as:
wchar_t * DataBuffer = new wchar_t[wcslen(array1) + std::strlen(array2) + 1];
which will probably bring you nothing but unpleasant problems and memory leaks.

Remove
wchar_t array2[] = pdwFavoriteUrl;
and change the call to strcat to
std::strcat(DataBuffer, pwdFavoriteUrl);
(and similarly, replace array2 with pwdFavoriteUrl in the call to strlen.)
Note that PCWSTR is just
typedef const wchar_t * PCWSTR;

Related

Registry RegQueryValueExW

Is it possible to read a value in the Registry not to an array of chars but directly to an AnsiString in this case?
LONG result;
wchar_t buf[255] = {0};
DWORD dwBufSize = sizeof(buf);
String d = "Nazwa";
DWORD dwType = REG_SZ;
result = ::RegQueryValueExW( hkSoftware, (LPCWSTR)(d.c_str()), NULL, &dwType, (LPBYTE)&buf, &dwBufSize );
First off, your code example is not using AnsiString. In C++Builder 2009 and later, String is an alias for UnicodeString instead.
And yes, you can use UnicodeString with RegQueryValueExW(), without using a typecast. UnicodeString::c_str() returns a WideChar*, and WideChar is an alias for wchar_t on Windows, so WideChar* (aka wchar_t *) is implicitly convertible to LPCWSTR (aka const wchar_t *), eg:
LONG result;
wchar_t buf[255] = {0};
DWORD dwBufSize = sizeof(buf);
UnicodeString d = L"Nazwa";
DWORD dwType = REG_SZ;
result = ::RegQueryValueExW( hkSoftware, d.c_str(), NULL, &dwType, reinterpret_cast<LPBYTE>(&buf), &dwBufSize );
You can also use UnicodeString as a buffer to receive string data from RegQueryValueExW(), eg:
LONG result;
UnicodeString buf;
buf.SetLength(...);
DWORD dwBufSize = ByteLength(buf);
UnicodeString d = L"Nazwa";
DWORD dwType = REG_SZ;
result = ::RegQueryValueExW( hkSoftware, d.c_str(), NULL, &dwType, reinterpret_cast<LPBYTE>(buf.c_str()), &dwBufSize );
if ( result == 0 ) {
buf.SetLength(dwBufSize/sizeof(WideChar));
...
}
That being said, you should consider using C++Builder's TRegistry class instead of using the Win32 Registry API directly. TRegistry has many methods for reading different kinds of data, including ReadString() for String data, eg:
#include <Registry.hpp>
TRegistry *Reg = new TRegistry;
String buf;
Reg->RootKey = ...;
if (Reg->OpenKeyReadOnly(_D("...")))
{
buf = Reg->ReadString(_D("Nazwa"));
Reg->CloseKey();
}
delete Reg;

how can I allocate an array on the stack if the size is not known at compile time?

I'm writing a c++ program with visual studio and I have written this code
DWORD GetProcIDByName(const char* procName) {
HANDLE hSnap;
BOOL done;
PROCESSENTRY32 procEntry;
ZeroMemory(&procEntry, sizeof(PROCESSENTRY32));
procEntry.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
done = Process32First(hSnap, &procEntry);
do {
/* here */ char file_str[sizeof(procEntry.szExeFile)];
int wc_convert = WideCharToMultiByte(CP_ACP, 0, procEntry.szExeFile, sizeof(procEntry.szExeFile), file_str, sizeof(file_str), NULL, NULL);
if (_strnicmp(file_str, procName, sizeof(file_str)) == 0) {
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnap, &procEntry));
return 0;
}
in order to convert the value procEntry.szExeFile from a WCHAR* (wide unicode character array), to a standard char* to compare, I had to make a char* buffer for it. I wrote the line
char file_str[sizeof(procEntry.szExeFile)];
and realized later that I should use heap memory for this buffer that will change sizes depending on the process name, but I was surprised to see that my visual studio had no problem with this code and I was able to build it with no compiler errors. I haven't run it yet and I probably will not because I imagine if this runs there is a potential for buffer overflow and undefined behaviour
I don't have any issue, but I am curious about why I was able to write this code without getting a compiler error. If the process name is not known at compile time, how can I allocate this buffer on the stack?
The szExeFile field is not dynamic length. It is a fixed-length array of MAX_PATH characters, holding a null-terminated string.
Note that:
sizeof() reports a size in bytes
szExeFile is an array of wchar_t characters, in your case
wchar_t is 2 bytes in size on Windows.
So, when you declare your char[] array as char file_str[sizeof(procEntry.szExeFile)];, it will have a static compile-time size of MAX_PATH*2 chars. Which should be large enough to easily handle most conversions from wchar_t[] to char[] in this case.
BTW, your use of sizeof(procEntry.szExeFile) in the 4th parameter of WideCharToMultiByte() is wrong. That parameter expects a character count, not a byte count. Use lstrlenW(procEntry.szExeFile) or wcslen(procEntry.szExeFile) instead. Or just -1 to let WideCharToMultiByte() count the wide characters for you.
That being said, an easier solution is to use Process32FirstA()/Process32NextA() instead. Or, change your function to take a Unicode wchar_t string as input. Either way, then you won't have to convert the procEntry.szExeFile at all, just use it as-is.
Also, you are leaking the HANDLE from CreateToolhelp32Snapshot(), you need to call CloseHandle() when you are done using it.
Try this:
DWORD GetProcIDByName(const char* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32A procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstA(hSnap, &procEntry);
while (ok) {
if (_stricmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextA(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
Or this:
DWORD GetProcIDByName(const wchar_t* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32W procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstW(hSnap, &procEntry);
while (ok) {
if (_wcsicmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextW(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}

LPSTREAM unable to read into CString

I'm attempting to read text into a CString using an LPSTREAM, but it doesn't seem to be working correctly, here is the code that I'm calling:
static HRESULT UTL_ReadStreamTxt(MyStorage* pSrcStg, const char* pszStream, CString* myCStr, int size)
{
HRESULT hrRet = STG_E_INVALIDPARAMETER;
LPSTREAM lpSrc = NULL;
ULONG ul;
TRY
{
USES_CONVERSION;
HRESULT hrSrc = pSrcStg->GetStg()->OpenStream(CT2COLE(strSrc),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrSrc != NOERROR)
{
hrRet = hrSrc;
}
else
{
hrRet = lpSrc->Read(&myCStr, size, NULL); // Read into CString
}
}
CATCH_ALL(e)
{
hrRet = STG_E_UNKNOWN;
}
END_CATCH_ALL
_AfxRelease((LPUNKNOWN*)&lpSrc);
return hrRet;
}
When it reads into the string, Visual Studio says that the data in the CString is corrupted.
The compound storage's stream contents are the following:
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
I'm not entirely sure I'm using Read() correctly, How do I fix this issue?
The main problem is that you are passing a bad pointer to Read(). You are passing the memory address of the myCStr parameter itself, not the address of the CString being pointed at, or more accurately, the memory address of a character buffer that the CString owns. The code compiles only because Read() takes a simple void* pointer to a buffer, and any pointer is implicitly convertible to void*.
Also note that CString is based on TCHAR, which maps to either char or wchar_t depending on whether you are compiling your project for ANSI/MBCS or Unicode. So, reading from the stream directly into a CString will only work correctly if:
the stream contains ANSI characters and TCHAR maps to char.
the stream contains UTF-16 characters and TCHAR maps to wchar_t.
If the stream's character type does not match the character type used by CString, you would have to first read the stream into an intermediate buffer and then convert that to TCHAR before it can be stored in the CString.
Try something more like this:
static HRESULT UTL_ReadStreamTxt(MyStorage* pSrcStg, const char* pszStream, CString* myCStr, int size)
{
HRESULT hrRet = STG_E_INVALIDPARAMETER;
LPSTREAM lpSrc = NULL;
ULONG ul;
LPVOID buffer;
TRY
{
USES_CONVERSION;
HRESULT hrSrc = pSrcStg->GetStg()->OpenStream(CT2COLE(strSrc),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrSrc != S_OK)
{
hrRet = hrSrc;
}
else
{
// if the stream's character type matches TCHAR...
buffer = myCStr->GetBuffer(size / sizeof(TCHAR));
hrRet = lpSrc->Read(buffer, size, &ul);
myCStr->ReleaseBuffer(ul / sizeof(TCHAR));
// else, if the stream's character type is 'char' and TCHAR is 'wchar_t'...
CStringA tmp;
buffer = tmp.GetBuffer(size);
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul);
*myCStr = CString((LPSTR)tmp, tmp.GetLength());
// else, if the stream's character type is 'wchar_t' and TCHAR is 'char'...
CStringW tmp;
buffer = tmp.GetBuffer(size / sizeof(wchar_t));
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul / sizeof(wchar_t));
*myCStr = CString((LPWSTR)tmp, tmp.GetLength());
// alternatively, you can do the above 2 cases more generically...
typedef CStringT<char or wchar_t> CStreamString;
CStreamString tmp;
buffer = tmp.GetBuffer(size / sizeof(CStreamString::XCHAR));
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul / sizeof(CStreamString::XCHAR));
*myCStr = CString((CStreamString::PXSTR)tmp, tmp.GetLength());
}
}
CATCH_ALL(e)
{
hrRet = STG_E_UNKNOWN;
}
END_CATCH_ALL
_AfxRelease((LPUNKNOWN*)&lpSrc);
return hrRet;
}

How to convert LPWSTR* (or WCHAR*) to LPWSTR

I'm having a difficulty in converting a value to LPWSTR. I'm getting a registry value, and trying to return the result as LPWSTR. It appears the registry call using RegQueryValueExW works with a variety of types going in to store the result, but I can't cast any of them back to LPWSTR.
LPWSTR value;
HKEY hKey;
long result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"RegEntry1", 0, ACCESS|KEY_WOW64_32KEY, &hKey);
if (result == ERROR_SUCCESS)
{
//WCHAR buffer[512];
//TCHAR buffer[512];
LPWSTR buffer[512];
DWORD bufferSize = sizeof(buffer);
ULONG queryVal = 0;
queryVal = RegQueryValueExW(hKey, L"Path", 0, NULL, (LPBYTE)buffer, &bufferSize);
if (queryVal == ERROR_SUCCESS)
{
//Access violation error here; I need some type of conversion.
value = buffer;
}
}
No posts that I've read on here so far have led me to an answer. C++ is not my primary dev language.
UPDATE: None of the proposed answers worked for me. I found an alternative way to do what I needed.
You don't want a buffer of LPWSTR, you want a buffer of wchar_t. A pointer to that will be LPWSTR as it's a typedef for wchar_t *.
These two lines from WinNT.h are relevant:
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
typedef __nullterminated WCHAR *NWPSTR, *LPWSTR, *PWSTR;
Edit: I suspect the problem is with the part of the code you haven't shown us. Are you returning value from a function? If so then the problem is that you're returning a pointer to a buffer that has gone out of scope and been destroyed. I would return a std::wstring or CString instead.
Your buffer variable is declaring an array of 512 wchar_t* pointers when it should be declaring an array of 512 wchar_t characters instead. The first commented-out line of code is the correct code to use:
WCHAR buffer[512];
DWORD bufferSize = sizeof(buffer);
ULONG queryVal = RegQueryValueExW(hKey, L"Path", 0, NULL, (LPBYTE)buffer, &bufferSize);
if (queryVal == ERROR_SUCCESS)
{
//...
}
Keep in mind that the buffer will not be null-terminated if the Registry value was not stored with its own null-terminator, so you should allocate some extra space for your own null terminator, just in case:
WCHAR buffer[512+1];
DWORD bufferSize = (sizeof(buffer) - sizeof(WCHAR));
LONG queryVal = RegQueryValueExW(hKey, L"Path", 0, NULL, (LPBYTE)buffer, &bufferSize);
if (queryVal == ERROR_SUCCESS)
{
buffer[bufferSize / sizeof(WCHAR)] = 0;
//...
}
Alternatively, use RegGetValue() instead, which handles the null terminator for you:
WCHAR buffer[512+1];
DWORD bufferSize = sizeof(buffer);
LONG queryVal = RegGetValueW(hKey, NULL, L"Path", RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ, NULL, buffer, &bufferSize);
if (queryVal == ERROR_SUCCESS)
{
//...
}

string to PCWSTR -> strange return(C++)

i'm really new to C++-programming and i've got an a problem with writing into a xml document.
I'm using a slightly changed example of xml outputter from msdn (http://msdn.microsoft.com/en-us/library/ms766497(VS.85).aspx).
HRESULT CreateAndAddTestMethodNode(string name)
{
HRESULT hr = S_OK;
IXMLDOMElement* pElement = NULL;
CHK_HR(CreateAndAddElementNode(pXMLDom, L"method", L"\n\t", pClass, &pMethod));
CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"name", stringToPCWSTR(name), pMethod));
//more Attribute Nodes (deleted for better overview ;) )
CleanUp:
SAFE_RELEASE(pMethod);
return hr
}
I'm giving a string to CreateAndAddTestMethodNode which convert it with stringtopcwstr to a pcwstr, or should do it.
//convert string to pcwstr
PCWSTR stringToPCWSTR (const std::string& str)
{
int len;
int slength = (int)str.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, buf, len);
std::wstring result(buf);
delete[] buf;
PCWSTR pResult = result.c_str();
return pResult;
}
But it only returns something like
"0x00bb9908 "ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ" which causes an access violation in one of the next methods.
It would be really great if someone could give me clue where i did the failure.
Thank You.
The result of c_str() gets destroyed along with the result string (when it goes out of scope). You will need to explicitly allocate memory for it.
You could make the return type for stringToPCWSTR as a const reference to PCWSTR i.e. const PCWSTR&