Why I can't construct a wstring from char* - c++

According I build fill a char* from this code :
char* pathAppData = nullptr;
size_t sz = 0;
_dupenv_s(&pathAppData, &sz, "APPDATA");
I can easily construct a string with this code and append this string in the future :
std::string sPathAppData(pathAppData);
sPathAppData.append("\\MyApplication");
But I can't create a wstring from this code. Why is so complicated to work with wstring ? I am going crazy with all theses types.
std::wstring wPathAppData(pathAppData); // Impossible

You could use wchar_t directly and use corresponding wchar_t supported API to retrieve data directly to wchar_t and then construct wstring. _dupenv_s function has a wide counterpart - _wdupenv_s.
Your code then would look like this:
wchar_t* pathAppData = nullptr;
size_t sz = 0;
_wdupenv_s(&pathAppData, &sz, L"APPDATA");
std::wstring wPathAppData(pathAppData);
wPathAppData.append(L"\\MyApplication")
Also this could be an interesting read: std::wstring VS std::string

You have to use iterator to make copy. This is how you can do it.
char* pathAppData = nullptr;
size_t sz = 0;
_dupenv_s(&pathAppData, &sz, "APPDATA");
std::string sPathAppData(pathAppData);
sPathAppData.append("\\MyApplication");
std::wstring wPathAppData(begin(sPathAppData), end(sPathAppData));
wcout << wPathAppData << endl;

Related

How convert LPCWSTR to wchar_t*?

I require to convert a LPCWSTR data to wchar_t*. I tried a bunch of methods, and some work, but when I try to get their code page, they are showing different values.
Code overview:
std::string ChineseCharacter(LPCWSTR Data) //Data value: "丂\n"
{
CString sHexValue = "";
std::wstring sData(Data);
wchar_t* str1 = (wchar_t*)Data;
//wchar_t* str2 = (wchar_t*)_wcsdup(sData.c_str());
wchar_t* str3 = (wchar_t*)(L"丂\n"); //u4E02 -- CP 8140 ** CP is needed
for (int i = 0; i < 4; i++)
{
sHexValue2.Format("%02x", str1[i]);//-- 4E02 -- FAIL
//sHexValue2.Format("%02x", str2[i]);//-- 4E02 -- FAIL
sHexValue2.Format("%02x", str3[i]);//-- First loop: 81, second one: 40 -- OK
}
}
According to the watcher, the values are:
str1= L"丂\n"
str3= L"#\n"
My doubt is, how can I pass the value of Data to a wchar_t*, equal as when I hard-code the value?
Reference:
https://uic.io/en/charset/show/gb18030/
LPCWSTR is just an alias for const wchar_t*. To convert that to wchar_t*, you can use const_cast, eg:
wchar_t* str = const_cast<wchar_t*>(Data);
(just make sure you don't write anything to the memory that is pointed at).
However, nothing in the code you have shown requires the use of non-const wchar_t* (or std::wstring, either), so you can simply loop through Data directly, there is no need to convert LPCWSTR to wchar_t* at all, eg:
std::string ChineseCharacter(LPCWSTR Data)
{
CString sHexValue;
for (int i = 0; (i < 4) && (Data[i] != L'\0'); ++i)
{
sHexValue.Format("%02hx", static_cast<unsigned short>(Data[i]));
}
return static_cast<char*>(sHexValue);
}
Alternatively, using just standard C++:
std::string ChineseCharacter(const wchar_t *Data)
{
std::ostringstream sHexValue;
for (int i = 0; (i < 4) && (Data[i] != L'\0'); ++i)
{
sHexValue << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned short>(Data[i]);
}
return sHexValue.str();
}

C++ Unable to convert std::vector<BYTE> to a string or char array

I am currently working with the Registry using this GitHub library:
https://github.com/GiovanniDicanio/WinReg
I am trying to convert this vector<BYTE> to a char array or a string, to make a hash out of it with help of SHA-512. But I am stuck with converting it, I tried different methods. I don´t get any compiler errors, just the app crashes at runtime. I am using a DLL that I load into my process.
RegKey NetworkInterface_key(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}\\0001");
const std::vector<BYTE> InstallTimeStamp = NetworkInterface_key.GetBinaryValue(L"InstallTimeStamp");
MY SOLUTION:
Changed std::vector<BYTE> -> std::vector<unsigned char>
Used this methode:
template <typename T>
std::string to_hex(T data)
{
std::ostringstream result;
result << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast<int>(data);
return result.str();
}
std::string dump(const std::vector<unsigned char>& data)
{
if (data.empty()) return "";
auto size = data.size();
std::ostringstream result;
for(u32 i =0; i < size; i++)
{
result << "0x" + to_hex(data[i]);
if (i != size)
result << " ";
}
return result.str();
}
Credits: U. Bulle -> C++ Converting Vector<BYTE> to string where first vector byte is 0
You don't need that library, just do this:
HKEY key = 0;
BYTE timestamp[16] = { 0 };
LRESULT err = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}\\0001", 0, KEY_READ, &key);
if (err == 0)
{
DWORD dwType = 0;
DWORD dwSize = 16;
::RegQueryValueEx(key, L"InstallTimeStamp", NULL, &dwType, timestamp, &dwSize);
RegCloseKey(key);
}
As for converting those 16 bytes into "string". That doesn't make a lot of sense given that that those 16 bytes are binary data. You could do this:
std::string strTimestamp((char*)timestamp, 16);
But I suspect you just want a pointer to pass to a sha512 function that expects a char* data type. If that's the case, just do this:
const char* ts = (char*)timestamp;
Just remember the length of that array is fixed and is not a null terminated string. So your hash function should take a length parameter as well.
The RegKey::GetBinaryValue() method returns a std::vector<BYTE>. To convert that data to a char[] array, you don't really have to actually convert it at all, you can simply type-cast a pointer to the data instead:
const std::vector<BYTE> InstallTimeStamp = ...;
const char *pInstallTimeStamp = reinterpret_cast<const char*>(InstallTimeStamp.data());
But, if you want to convert the data to a std::string, then std::string has constructors that are appropriate for that purpose, eg:
const std::vector<BYTE> InstallTimeStamp = ...;
std::string sInstallTimeStamp(reinterpret_cast<const char*>(InstallTimeStamp.data()), InstallTimeStamp.size());
const std::vector<BYTE> InstallTimeStamp = ...;
std::string sInstallTimeStamp(InstallTimeStamp.begin(), InstallTimeStamp.end());
However, that being said, hashes operate on bytes, not on characters or strings, so you really should not need to convert the vector data to anything else at all, just hash its contents as-is. Unless you are using a hashing API that requires char/string input (if so, you should find a better hash API), in which case the above should suffice.

How would I read Memory into a wstring?

I already tried using wchar_t and a for-loop to read the Memory wchar by wchar and it worked.
Working code:
int cl = 20;
std::wstring wstr;
wchar_t L;
for (int i = 0; i < cl; i++) {
ReadProcessMemory(ProcHandle, (unsigned char*)Address, &L, 2, NULL);
Address += 2;
wstr.push_back(L);
}
std::wcout << wstr << std::endl;
Now when I try using std::wstring and read directly into it, it fails for whatever reason.
int cl = 20;
std::wstring L;
L.resize(cl); // could use reserve?
ReadProcessMemory(ProcHandle, (unsigned char*)Address, &L, cl*2, NULL);
std::wcout << L << std::endl;
I figured I'd use (cl * 2) as size because wchar_t has 2 chars size.
I would expect it to print the wstring to wcout but instead it errors with something similar to Failed to read sequence
Note: I cannot use wchat_t[20] because I later want cl to be dynamic.
Edit: Forgot to say that I'm on std c++17
std::vector<wchar_t> is more suitable for your case.
&L is the address of the string object, not the string buffer. You wanna use &L[0], the address of the first wchar.

Text from Textbox to char* (converting/marshal)

Currently I'm busy to get some text from the textbox and then convert in into a const char*. I have the following code:
System::String^ host = textBoxHostadres->Text;
const char* host2 = (const char*)(void*)Marshal::StringToHGlobalAnsi(host);
//system(host2); //What to do with this?
Marshal::FreeHGlobal(host2);
It gives a redline (Visual Studio 2012) under Marshal::FreeHGlobal. Can somebody give me a right direction to get the text from the textbox and get it to a const char*? The first line works well and through debugging I see the text get captured.
Update:
System::String^ host = textBoxHostadres->Text;
pin_ptr<const wchar_t> wch = PtrToStringChars(host);
// Convert to a char*
size_t origsize = wcslen(wch) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
strcat_s(nstring, " (char *)");
const char* host2 = (const char*)(void*)Marshal::StringToHGlobalAnsi(host);
system(host2);
traceroute hostAddress(host2);
Here you will find all possible conversion between char *, wchar_t*, _bstr_t, CComBSTR, CString, basic_string, and System.String.
The strings types that are covered include char *, wchar_t*, _bstr_t, CComBSTR, CString, basic_string, and System.String. In all cases, a copy of the string is made when converted to the new type. Any changes made to the new string will not affect the original string, and vice versa.
Regarding the EDITs you've added:
It would be nice if you could at least try to understand the code you are copy-pasting. This line strcat_s(nstring, " (char *)"); adds some characters to your string and mainly (char *) and this is obvious now that your nstring doesn't contain an adress of a file allready, but adress + some trash. Also you don't need this line std::cout << nstring << std::endl; at all.
This is how your implementation should look like.
System::String^ host = textBoxHostadres->Text;
pin_ptr<const wchar_t> wch = PtrToStringChars(host);
// Convert to a char*
size_t origsize = wcslen(wch) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize]; // nstring is an array of chars
wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
// strcat_s(nstring, " (char *)"); this line adds trash to your nstring!!!
traceroute hostAddress(nstring);
You were not type-casting host2 in your call to Marshal::FreeHGlobal():
System::String^ host = textBoxHostadres->Text;
const char* host2 = (const char*)(void*)Marshal::StringToHGlobalAnsi(host);
system(host2);
traceroute hostAddress(host2);
Marshal::FreeHGlobal((IntPtr) host2);

Convert long to char* const

What is the right way to convert long to char* const in C++?
EDIT:
long l = pthread_self();
ThirdPartyFunction("Thread_Id_"+l); //Need to do this
ThirdPartyFunction(char* const identifierString)
{}
EDIT:
The "proper" way to convert an integer to a string, in C++, is to use a stringstream. For instance:
#include <sstream>
std::ostringstream oss;
oss << "Thread_Id_" << l;
ThirdPartyFunction(oss.str().c_str());
Now, that probably won't be the "fastest" way (streams have some overhead), but it's simple, readable, and more importantly, safe.
OLD ANSWER BELOW
Depends on what you mean by "convert".
To convert the long's contents to a pointer:
char * const p = reinterpret_cast<char * const>(your_long);
To "see" the long as an array of chars:
char * const p = reinterpret_cast<char * const>(&your_long);
To convert the long to a string:
std::ostringstream oss;
oss << your_long;
std::string str = oss.str();
// optionaly:
char * const p = str.c_str();
Another possibile "pure" solution is to use snprintf
long number = 322323l;
char buffer [128];
int ret = snprintf(buffer, sizeof(buffer), "%ld", number);
char * num_string = buffer; //String terminator is added by snprintf
long l=0x7fff0000; // or whatever
char const *p = reinterpret_cast<char const *>(l);