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();
}
Related
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.
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.
So I am working on a tool that dereferences the values of some addresses, it is in both C and C++, and although I am not familiar with C++ I figured out I can maybe take advantage of the string type offered by C++.
What I have is this:
unsigned char contents_address = 0;
unsigned char * address = (unsigned char *) add.addr;
int i;
for(i = 0; i < bytesize; i++){ //bytesize can be anything from 1 to whatever
if(add.num == 3){
contents_address = *(address + i);
//printf("%02x ", contents_address);
}
}
As you can see what I am trying to do is dereference the unsigned char pointer. What I want to do is have a string variable and concatenate all of the dereferenced values into it and by the end instead of having to go through a for case for getting each one of the elements (by having an array of characters or by just going through the pointers) to have a string variable with everything inside.
NOTE: I need to do this because the string variable is going to a MySQL database and it would be a pain to insert an array into a table...
Try this that I borrowed from this link:
http://www.corsix.org/content/algorithmic-stdstring-creation
#include <sstream>
#include <iomanip>
std::string hexifyChar(int c)
{
std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0') << c;
return ss.str();
}
std::string hexify(const char* base, size_t len)
{
std::stringstream ss;
for(size_t i = 0; i < len; ++i)
ss << hexifyChar(base[i]);
return ss.str();
}
I didn't quite understand what you want to do here (why do you assign a dereferenced value to a variable called ..._address)?.
But maybe what you're looking for is a stringstream.
Here's a relatively efficient version that performs only one allocation and no additional function calls:
#include <string>
std::string hexify(unsigned char buf, unsigned int len)
{
std::string result;
result.reserve(2 * len);
static char const alphabet[] = "0123456789ABCDEF";
for (unsigned int i = 0; i != len)
{
result.push_back(alphabet[buf[i] / 16]);
result.push_back(alphabet[buf[i] % 16]);
{
return result;
}
This should be rather more efficient than using iostreams. You can also modify this trivially to write into a given output buffer, if you prefer a C version which leaves allocation to the consumer.
whats the best way of creating a 'const char*' using available variables? For example, a function requires a const char* as a parameter to locate a file i.e. "invader1.png". If I have 5 different invader images, how can I iterate from 1:5 so "Invader1.png".."Invader2.png..etc etc
so i want "invader" + %d + ".png"
i tried sprintf and casting but to no avail.
I hope my description makes sense, thanks
update with code:
for (int y=0; y<250; y+=50){
stringstream ss;
ss << "invader" << (y/50) << ".png";
const char* rr = ss.str().c_str();
printf("%s", rr);
for (int x=0; x<550;x+=50){
Invader inv(rr, x+50, y+550, 15, 15, 1, false, (y/50 + 50));
invaders[i] = inv;
i++;
}
}
Use std::stringstream. Something like this:
std::stringstream ss;
ss << "invader" << my_int << ".png";
my_func(ss.str().c_str());
Since you're using C++, you can simply use std::string and then use the c_str() function to get a const char* which you can pass to the function. One simple way to construct such strings is to use std::ostringstream from <sstream>:
for (int i = 1; i <= 5; ++i) {
std::ostringstream ss;
ss << "invader" << i << ".png";
foo(ss.str().c_str()); // where foo is the specified function
}
You could also use sprintf() and a character array, but then you need to pay attention to things like the size of the buffer. For the sake of completeness, here's how to do the same with sprintf, but I suggest you go with the std::string approach, which is more C++-like:
for (int i = 1; i <= 5; ++i) {
char buf[13]; // big enough to hold the wanted string
std::ostringstream ss;
sprintf(buf, "invader%d.png", i);
foo(buf); // where foo is the specified function
}
Then i would guess your looking to cast an int variable to char, so you can iterate through your invader%d.png files.
Have you tried itoa function ?
http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/
I am retrieving the environment variables in win32 using GetEnvironmentStrings(). It returns a char*.
I want to search this string(char pointer) for a specific environmental variable (yes I know I can use GetEnvironmentVariable() but I am doing it this way because I also want to print all the environment variables on the console aswell - I am just fiddling around).
So I thought I would convert the char* to an std::string & use find on it (I know I can also use a c_string find function but I am more concerned about trying to copy a char* into a std::string). But the following code seems to not copy all of the char* into the std::string (it makes me think there is a \0 character in the char* but its not actually the end).
char* a = GetEnvironmentStrings();
string b = string(a, sizeof(a));
printf( "%s", b.c_str() ); // prints =::=
Is there a way to copy a char* into a std::string (I know I can use strcpy() to copy a const char* into a string but not a char*).
You do not want to use sizeof() in this context- you can just pass the value into the constructor. char* trivially becomes const char* and you don't want to use strcpy or printf either.
That's for conventional C-strings- however GetEnvironmentStrings() returns a bit of a strange format and you will probably need to insert it manually.
const char* a = GetEnvironmentStrings();
int prev = 0;
std::vector<std::string> env_strings;
for(int i = 0; ; i++) {
if (a[i] == '\0') {
env_strings.push_back(std::string(a + prev, a + i));
prev = i;
if (a[i + 1] == '\0') {
break;
}
}
}
for(int i = 0; i < env_strings.size(); i++) {
std::cout << env_strings[i] << "\n";
}
sizeof(a) in what you have above will return the size of char*, i.e. a pointer (32 or 64bits usually). You were looking for function strlen there. And it's not actually required at all:
std::string b(a);
should be enough to get the first environment variable pair.
The result of GetEnvironmentStrings() points to memory containing all environment strings. Similar to the solution of Puppy it will be put into a vector of string, where each string contains just one environment variable ("key=value")
std::vector<std::string> env_strings;
LPTCH a = GetEnvironmentStrings();
As example we will have 2 environment variables defined:
"A=ABC"
"X=XYZ"
LPTCH a will be:
A=ABC\0X=XYZ\0\0
Each variable is '\0' - terminated and finally the complete environment string (a) will be terminated with an additional '\0'.
strlen will return the size to the first occurrence of the termination character '\0'. The last string will always be empty.
while ((std::size_t len = strlen(a)) > 0)
{
env_strings.push_back(std::string(a, len));
a += len + 1;
}
Multi-byte character
For multi-byte characters it will work as well:
LPTCH a = GetEnvironmentStrings();
std::vector<std::wstring> env_strings;
while ((std::size_t len = wcslen(a)) > 0)
{
env_strings.push_back(std::wstring(a, len));
a += len + 1;
}
FreeEnvironmentStrings(a);
Does the following causes any problems?
char* a = GetEnvironmentStrings();
string b;
b=a;
printf( "%s", b.c_str() );
When you say:
string b = string(a, sizeof(a));
you are getting the size of a, which is a pointer and is probably 4. So you will get the first 4 characters. I'm not sure what you are really trying to do, but you should be able just to say:
string b( a );
char* a = ...;
string str(a);
string b;
b = a;
I assume you mean the Windows API GetEnvironmentStrings function. So, test the result against nullptr and perform simple assignment:
char* env = ::GetEnvironmentStrings();
if (0 != env)
{
std::string senv = env;
// use senv to find variables
}
else
{
// report problem or ignore
}