Extract information from RCDATA resource - winapi

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.

Related

Wide-character string converted from multibyte string using MultiByteToWideChar print and write to file error

I can print the wide-character string correctly, writing to text file is also OK, using the following code:
const wchar_t wcs[] = L"Hello大家好";
_setmode(_fileno(stdout), _O_WTEXT);
wprintf(L"%ls", wcs);
FILE *pf;
const wchar_t _FileName[] = L"wcs.txt";
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", wcs);
fflush(pf);
fclose(pf);
But I need to convert the multibyte string to wide-character string, using MultiByteToWideChar, and than print or write to text file, error occurred, the result displayed or the text file is all messy code. My code is below.
const char cs[] = "Hello大家好";
wchar_t lpWideCharStr[64];
MultiByteToWideChar(CP_ACP, 0, cs, 0, lpWideCharStr, 64);
wprintf(L"%ls", lpWideCharStr);
FILE *pf;
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", lpWideCharStr);
fflush(pf);
fclose(pf);
Can anybody help? Thanks in advance.
This works for me.
#include <Windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
bool ConvertToWideFromUTF8orACP(char* strData, wchar_t* w_strData, int w_strDataLen)
{
int nSize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, strData, -1, w_strData, w_strDataLen);
if (nSize == 0)
{
nSize = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, strData, -1, w_strData, w_strDataLen);
}
return nSize - 1;
}
int main()
{
char cs[] = "Hello大家好";
printf("%s\n", cs);
wchar_t* lpWideCharStr = new wchar_t[sizeof(cs)];
memset(lpWideCharStr, 0, sizeof(cs));
int nSize = ConvertToWideFromUTF8orACP(cs, lpWideCharStr,sizeof(cs));
_setmode(_fileno(stdout), _O_U16TEXT);
if (nSize > 0)
{
wprintf(L"%s", lpWideCharStr);
}
FILE* pf;
pf = _wfopen(_FileName, L"a, ccs=UTF-8");
fwprintf(pf, L"%ls", lpWideCharStr);
delete[] lpWideCharStr;
fflush(pf);
fclose(pf);
}
Thanks #Remy Lebeau for help:)

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

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.

I cant print a number inside a formatted MessageBox

The following code does not work as it should. %i does not connect with its variable.
#include<Windows.h>
#include<stdio.h>
#include<tchar.h>
/* SCREENSIZE.C
This project contains the code that Programming Windows
book by Charles Petzold is using.
*/
int cdecl MessageBoxPrintfW(TCHAR *msgBoxTitle, TCHAR *msgBoxFormat, ...)
{
//define buffer
TCHAR msgBoxBuffer[1024];
//define iteration pointer
va_list argPtr;
//start iteration
va_start(argPtr, msgBoxFormat);
/*int _vsnwprintf_s(
wchar_t *const _Buffer,
const size_t _BufferCount,
const size_t _MaxCount,
const wchar_t *const _Format,
va_list _ArgList)
*/
_vsntprintf_s(msgBoxBuffer, sizeof(msgBoxBuffer) / sizeof(TCHAR), (sizeof(msgBoxBuffer) / sizeof(TCHAR)) - 1, msgBoxFormat, argPtr);
//end iteration
va_end(argPtr);
//Use return type to pass preconfigured MessageBox(0,"Text","Title",MB_OKCANCEL);
//Whe we use L before a string example: L"text" it is considered UNICODE format.
return(MessageBox(0, msgBoxFormat, msgBoxTitle, MB_OKCANCEL));
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int iCmdShow)
{
int cxScreen, cyScreen;
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
MessageBoxPrintfW(TEXT ("SCREENSIZE"), TEXT("The screen is %i pixels wide by %i pixels high."), cxScreen, cyScreen);
return(0);
}
Why does this happen?
Below is the output that I get:
TCHAR msgBoxBuffer[1024];
_vsntprintf_s(msgBoxBuffer,...
...
return(MessageBox(0, msgBoxFormat, msgBoxTitle, MB_OKCANCEL));
Note that you are writting to msgBoxBuffer, but you never use msgBoxBuffer. So your message box doesn't change anything. Try the following instead:
int MessageBoxPrintfW(const TCHAR *msgBoxTitle, const TCHAR* msgBoxFormat, ...)
{
va_list args;
va_start(args, msgBoxFormat);
int len = _vsctprintf(msgBoxFormat, args) + 1; // add terminating '\0'
TCHAR *buf = new TCHAR[len];
_vstprintf_s(buf, len, msgBoxFormat, args);
int result = MessageBox(0, buf, msgBoxTitle, MB_OKCANCEL);
delete[]buf;
return result;
}
For C version use malloc(len * sizeof(TCHAR)) instead of new, and use free instead of delete[]

Concatenation tchar variables

I work with WinAPI and I have a function get_disk_drives() for retrieves available disk drives and a helper function get_current_disk_drive() for retrieves the full path and file name of the specified file.
void get_current_disk_drive(TCHAR dirname[]) {
TCHAR *fileExt = NULL;
TCHAR szDir[MAX_PATH];
GetFullPathName(dirname, MAX_PATH, szDir, &fileExt);
_tprintf(_T("Full path: %s \nFilename: %s\n"), szDir, fileExt);
}
void get_disk_drives() {
DWORD drives_bitmask = GetLogicalDrives();
for (int i = 0; i < 26; i++) {
if ((drives_bitmask >> i) & 1) {
TCHAR drive_name = (char)(65 + i);
TCHAR drive_path[] = drive_name + "\\";
get_current_disk_drive(drive_path);
}
}
}
int _tmain(int argc, _TCHAR* argv[]) {
get_disk_drives();
return 0;
}
Here I can't make concatenation:
TCHAR drive_name = (char)(65 + i);
TCHAR drive_path[] = drive_name + "\\";
get_current_disk_drive(drive_path);
Why? Where is my mistake?
operator+ cannot be used for C-strings, string literals, or characters. The effect (for legal expressions anyway) is pointer arithmetic. For concatenation you have to either explicitly call one of the strcat functions, or use std::basic_string instead:
typedef std::basic_string<TCHAR> tstring;
tstring drive_name;
drive_name += TCHAR( 65 + i );
tstring drive_path = drive_name + _T( '\\' );
You can access a C-string from a std::basic_string by invoking its c_str() member. Since this is a C-string represented as a pointer, you would have to change the signature of get_current_disk_drive to void get_current_disk_drive(const TCHAR* dirname), or pass a const tstring&.
It's also a good idea to stop using Code::Blocks. Defaulting to MBCS character encoding in 2015 is a crime.

Segmentation fault when changing default gateway

I wrote a simple application on Qt4 that modifier network adapter parameters, for that I have a slot called setInterfaceParams, implemented as so:
DWORD WinNetInterface::setInterfaceParams(QString index, QString ip, QString netmask, QString gateway)
{
DWORD res = NULL;
HINSTANCE lib = (HINSTANCE) LoadLibrary((WCHAR *)"iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
//char *szGUID = (char *)index.toStdString().c_str();
QByteArray a = index.toLocal8Bit();
char *szGUID = a.data();
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
// Method 01
res = SetAdapterIpAddress(szGUID,
0,
inet_addr(ip.toStdString().c_str()),
inet_addr(netmask.toStdString().c_str()),
inet_addr(gateway.toStdString().c_str()));
// End of method 01
// Method 02
/*res = SetAdapterIpAddress("{422C5689-A17B-402D-A6A2-22CE13E857B5}",
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));*/
// End of method 02
return res;
}
When I click on button that connected to slot setInterfaceParams, I get segmentation fault. If I comment method01, nothing happen, the some thing happen when I use method02.
I tried this function on a simple c++ application and it is work fine, test on Windows XP SP3.
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <iostream>
typedef DWORD (WINAPI *_SetAdapterIpAddress )(char *szAdapterGUID,
DWORD dwDHCP,
DWORD dwIP,
DWORD dwMask,
DWORD dwGateway);
int main()
{
HINSTANCE lib = (HINSTANCE) LoadLibrary("iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
char szGUID[] = "{422C5689-A17B-402D-A6A2-22CE13E857B5}";
DWORD dwSize = 0;
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
DWORD res = SetAdapterIpAddress(szGUID,
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));
std::cout << res;
return 0;
}
LoadLibrary((WCHAR *)"iphlpapi.dll");
That can't work, the literal string is in 8-bits, casting it without real conversion doesn't make it wide, so the dll loading probably failed.
You should use the TEXT or _T macro around most of the literal strings passed to WinAPI functions to make them regular or wide depending on the compilation options:
LoadLibrary(_T("iphlpapi.dll"));
which will translate to either LoadLibrary("iphlpapi.dll"); or LoadLibrary(L"iphlpapi.dll");.
Also you should always check the value returned by the LoadLibrary and GetProcAddress functions, which return NULL if the call is unsuccessful.

Resources