Storing/Retrieving Pointer to std::wstring in char Array - char

I am trying to learn more about C++ memory management and type casting. How can I store and retrieve a std::wstring* in a char array? Code or suggestions about what to read would be appreciated.
Here is what I have tried so far. My definition of "Works" is that the correct string appears in the GUI control. "Does not work" means it compiles and runs but gives me a blank in the GUI control.
I'm really curious about why "Wrapper 2" works but not "Wrapper 1".
Integer example (Works):
int* lInt(new int);
*lInt = 1500000;
char lBuffer[sizeof(void*)];
memcpy(lBuffer, lInt, sizeof(void*));
int* lInt2 = (int*)lBuffer;
Memo->Lines->Append(IntToStr(*lInt2)); //C++Builder GUI control
delete lInt;
std::wstring Example (Does not work):
std::wstring* lMyString = new std::wstring();
*lMyString = L"My Name";
char lBuffer[sizeof(void*)];
memcpy(lBuffer, lMyString, sizeof(void*));
std::wstring* lMyString2 = (std::wstring*)lBuffer;
Memo->Lines->Append(lMyString2->c_str()); //C++Builder GUI control
delete lMyString;
Wrapper 1 (Does not work):
struct MyString
{
std::wstring Text;
};
MyString* lMyString = new MyString();
lMyString->Text = L"My Name";
char lBuffer[sizeof(void*)];
memcpy(lBuffer, lMyString, sizeof(void*));
MyString* lMyString2 = (MyString*)lBuffer;
Memo->Lines->Append(lMyString2->Text.c_str()); //C++Builder GUI control
delete lMyString;
Wrapper 2 (Works):
struct MyString
{
MyString(): Text(new std::wstring()){};
~MyString() {delete Text;};
std::wstring* Text;
};
MyString* lMyString = new MyString();
*lMyString->Text = L"My Name";
char lBuffer[sizeof(void*)];
memcpy(lBuffer, lMyString, sizeof(void*));
MyString* lMyString2 = (MyString*)lBuffer;
Memo->Lines->Append(lMyString2->Text->c_str()); //C++Builder GUI control
delete lMyString;

How can I store and retrieve a std::wstring* in a char array?
The better way is to store it in void*:
std::wstring ws;
void *addr = &ws;
// ...
std::wstring retreived = *static_cast<std::wstring*>(addr);
***** std::wstring Example (Does not work) *****
std::wstring* lMyString = new std::wstring();
// ...
char lBuffer[sizeof(void*)];
memcpy(lBuffer, lMyString, sizeof(void*));
std::wstring* lMyString2 = (std::wstring*)lBuffer;
// ...
memcpy used this way actually copies bytes of the stored std::wstring.
void* memcpy( void* dest, const void* src, std::size_t count );
lMyString is a pointer to allocated std::wstring and memcpy copies bytes from memory src points to. What you actually wanted to do is to copy the pointer itself so you need to take address of the pointer:
memcpy(lBuffer, &lMyString, sizeof(void*));
std::wstring* lMyString2 = (std::wstring*)lBuffer;
This is also wrong. You are converting address of the first character in char[], not the actual bytes that you stored in the char array before. You should memcpy it back:
std::wstring* lMyString2 = nullptr;
std::memcpy(&lMyString2, lBuffer, sizeof(void*));
As I said, use void* instead.

Related

RegGetValueA hard crashing application using luajit ffi

I am trying to use the RegGetValueA() from the Windows API , but so far I've been unable to get any results from it. At best, I get a "file not found" error, and at worst it crashes hard without any error messages at all.
Below is the current code I have; I'm not sure what is and isn't relevant, and what might be causing the problem or not. I've only got a smidge of C knowledge, so please try to keep it simple.
ffi.cdef([[
typedef void * HKEY;
typedef HKEY * PHKEY;
typedef unsigned long DWORD;
int RegGetValueA(HKEY handle, const char* path, const char* value, int filter_flags, void* unused, char *result, DWORD* size);
]])
local size = ffi.new('DWORD[1]')
size = 1024
local data = ffi.new('char['..size..']')
local dptr = ffi.cast('char*', data)
local lenptr = ffi.cast('DWORD*', size)
test = reg.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
When you use ffi.new, what you get is a pointer variable, and you assign the pointer to 1024, and then use ffi.cast to convert to DWORD *, which causes an access address conflict when calling RegGetValueA, so the program crashes.
You only need to modify the code as follows:
local ffi = require("ffi")
ffi.cdef([[
typedef void * HKEY;
typedef HKEY * PHKEY;
typedef unsigned long DWORD;
int RegGetValueA(HKEY handle, const char* path, const char* value, int
filter_flags, void* unused, char *result, DWORD* size);
]])
local size = 1024
local data = ffi.new('char['..size..']')
local dptr = ffi.cast('char*', data)
local lenptr = ffi.new('DWORD[1]', size)
local test = ffi.C.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
print(test)
print(ffi.string(dptr))
I get a "file not found" error
This means "registry key not found".
There are two different registries in 64-bit Windows, you should try reading from both of them:
local ffi = require'ffi'
ffi.cdef"int RegGetValueA(uintptr_t, const char*, const char*, uint32_t, void*, char*, uint32_t*);"
local size = 1024
local pcbData = ffi.new'uint32_t[1]'
local pvData = ffi.new('char[?]', size)
local RRF_SUBKEY_WOW6464KEY = 0x00010000
local RRF_SUBKEY_WOW6432KEY = 0x00020000
for _, WOW64_flag in ipairs{RRF_SUBKEY_WOW6464KEY, RRF_SUBKEY_WOW6432KEY} do
pcbData[0] = size
local errcode = ffi.C.RegGetValueA(
0x80000002, -- HKLM
"SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\MS-Anna-1033-20-DSK",
"CLSID",
0x0000ffff + WOW64_flag,
nil,
pvData,
pcbData
)
if errcode == 0 then
break
end
end
print(ffi.string(pvData))

Extract information from RCDATA resource

I have following code
HINSTANCE hinst = GetModuleHandleW(NULL);
HRSRC hrsrc = FindResourceW(hinst, MAKEINTRESOURCE(IDR_RCDATA), RT_RCDATA);
HGLOBAL hglob = LoadResource(hinst, hrsrc);
void* pMem = LockResource(hglob);
DWORD size = SizeofResource(0, hrsrc);
Rc file contains
IDR_RCDATA RCDATA { "RCDATA content\0" }
Qeustion: How I can get this IDR_RCDATA and put into char array?
You can just cast the result from LockResource to whatever you think it contains, something like this:
char* pMem = (char*)LockResource(hglob);
if it's an ANSI string.

problems with unsigned char

I have using Aaron Liddiment's excellent Ledtext library.
It includes code
unsigned char TxtDemo[] = { EFFECT_HSV "\x10\xff\xff" "TEST" };
ScrollingMsg.SetText((unsigned char *)TxtDemo, sizeof(TxtDemo) - 1);
I have a socket connection which outputs a string. I want to dynamically replace the word "TEST" with this string. I have tried:
unsigned char TxtDemo[] = { EFFECT_HSV "\x00\xff\xff" };
String txt="my text";
strcat( TxtDemo, txt.c_str() );
no good... help please

cannot convert const wchar_t* to const char*

ALL,
Can someone explain to me why this code:
std::wstring query1 = L"SELECT....";
res = mysql_query( m_db, m_pimpl->m_myconv.from_bytes( query1.c_str() ).c_str() );
gives me an error from the subject?
I do have -DUNICODE defined inside C++ options
I guess I just need a pair of fresh eyes.
Thank you.
It is on Gentoo Linux with gcc5.4.
This is a way to convert a unicode wide-character string to a const char*
char query_cstr[100];
size_t charsConverted;
wchar_t* unicode_query = L"SELECT * FROM table;";
wcstombs_s(&charsConverted, query_cstr, unicode_query, wcslen(unicode_query));
const char* query_const = query_cstr;
//Use query_const inside of mysql_query now that it's been converted to a const char*
I've run into trouble using the locale functions for various reasons. wcstombs_s() makes things a bit easier when converting unicode. Using c_str() on a std::wstring object will yield a const wchar_t* string, which is not what you want.

Some warnings being treated as errors while making a modified ver of ext2 kernel module under ubuntu

I have succeeded in making a modified version of ext2 (so called myext2.ko) and tested it for mount and umount, and something else; the problem occurs when I add the following code into my fs/myext2/file.c and tried to implement a simple "encryption" func, that is, negating the last bit of the read-in string :
ssize_t my_new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov; //changed
struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret;
//inserted by adward - begin
size_t i;
char buff[len];
for (i=0;i<len;i++){
buff[i] = buf[i] ^ 1;
}
iov.iov_base = (void __user *)buff;
iov.iov_len = len;
printk("Inside my_new_sync_write");
//inserted by adward - end
init_sync_kiocb(&ki_nbytesocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, WRITE, &iov, 1, len);
ret = filp->f_op->write_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
ssize_t my_new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret;
//inserted by adward - begin
size_t i;
//inserted by adward - end
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, READ, &iov, 1, len);
ret = filp->f_op->read_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
//inserted by adward - begin
for (i=0;i<len;i++){
buf[i] ^= 1;
}
printk("inside my_new_sync_read");
//inserted by adward - end
return ret;
}
The prototype of the above two functions are actually in fs/read_write.c , using by almost all file system types in the kernel code ver 3.17.6; I just copied them into fs/myext2/file.c and make some minor change as commented, so that I can do some test without having to change any Makefile.
But the moment I paste them into my file.c, "sudo make" gives the error message as following:
/home/adward/linux-3.17.6/fs/myext2/file.c:64:15: error: storage size of ‘kiocb’ isn’t known
struct kiocb kiocb;
^
/home/adward/linux-3.17.6/fs/myext2/file.c:65:18: error: storage size of ‘iter’ isn’t known
struct iov_iter iter;
^
and cc1: some warnings being treated as errors
even if I haven't refered to them by changing the func pointers in file_operations in the same source code file, or say, I haven't used them!
P.S.
My file_operation struct now looks like:
const struct file_operations myext2_file_operations = {
.llseek = generic_file_llseek,
.read = new_sync_read, //want to replace with my_new_sync_read
.write = new_sync_write, //want to replace with my_new_sync_write
...
}
Has anyone who have done something similar and crashed into some problems like this one? Please notify me if I have done something remarkable wrong, thanks.
Met the same error before. U should add <linux/aio.h> as ext2 uses asynchronous IO for reading/writing files.
Hope that helps :)

Resources