I'm trying to copy a file from resources to %localappdata%. I've something like this:
HINSTANCE hInstance = GetModuleHandle(NULL);
HANDLE hFile = INVALID_HANDLE_VALUE;
HRSRC hrsrc = FindResource(hInstance, MAKEINTRESOURCE(MSIE), RT_RCDATA);
HGLOBAL exeRes = LoadResource(hInstance, hrsrc);
DWORD size = SizeofResource(hInstance, hrsrc);
TCHAR szPath[MAX_PATH];
HANDLE hfile;
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) {
PathAppend(szPath, TEXT("test.exe"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
LPVOID exePtr = LockResource(hrsrc);
DWORD exeWritten = 0;
BOOL writeResult = WriteFile(hFile, exePtr, size, &exeWritten, NULL);
cout << GetLastError() << endl;
BOOL closed = CloseHandle(hFile);
system("PAUSE");
return 0;
I'm able to locate the HRSRC and confirm the size using SizeofResource() just fine. CreateFile is in fact creating the file and returning the handle. GetLastError() reports that there are no errors. The amount of bytes written to disk is exactly right.
The output exe however is corrupted (the version of this file is incompatible with the version of Windows... blah blah) - it's lost its icon and everything. Looking at the original and the output file side-by-side in a hex editor it appears there's random data at the start of file.
What am I missing here?
Your LockResource is not correct. It should be passed the HGLOBAL exeRes you loaded previously.
LockResource(hrsrc);
should be
LockResource(exeRes);
From the MS documentation on LockResource() :
Do not try to lock a resource by using the handle returned by the FindResource or FindResourceEx function. Such a handle points to random data.
And as a side note, you may want to try cleaning up that loaded-and-locked resource when you're through with it.
Related
I'm trying to change the icon of EXE file (path to EXE file is writing from console) by absolute path to image (.ico). Tried this code but nothing changed. Have anybody some ideas how to change the icon? (It`s now taking icon from one EXE and replace to another. Just change the icon of EXE file which path was written before)
HANDLE file = CreateFile(stringEXE, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE icon = CreateFile(stringICO, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD size = GetFileSize(file, NULL);
DWORD sizeICO = GetFileSize(icon, NULL);
DWORD bytesReadFile, bytesReadIco;
PVOID pointer = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
PVOID pIco = VirtualAlloc(NULL, sizeICO, MEM_COMMIT, PAGE_READWRITE);
ReadFile(icon, pIco, sizeICO, &bytesReadIco, NULL);
ReadFile(file, pointer, size, &bytesReadFile, NULL);
CloseHandle(file);
CloseHandle(icon);
HANDLE image = BeginUpdateResource(stringEXE, FALSE); // reading current exe
if (image != NULL) { // if success
if (UpdateResource(image, RT_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPVOID)pIco, bytesReadIco)) { // if updated
std::cout << "Icon has been changed successfully!" << std::endl;
EndUpdateResource(image,FALSE); // then lock it
}
}
Reference is from Microsoft Documentation about updating resources (https://learn.microsoft.com/en-us/windows/win32/menurc/using-resources)
I would like to set the background wallpaper from a resource image. I found and tried this code, but FindResource() can't find anything. Can anybody help me please?
HINSTANCE hInstance = GetModuleHandle(NULL);
std::cout << hInstance << std::endl;
HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(IDB_PNG1), RT_BITMAP);
std::cout << hResInfo<< std::endl;
HGLOBAL hRes = LoadResource(hInstance, hResInfo);
std::cout << hRes << std::endl;
LPVOID memRes = LockResource(hResInfo);
DWORD sizeRes = SizeofResource(hInstance, hResInfo);
std::cout << memRes<< std::endl;
std::cout << sizeRes<< std::endl;
HANDLE hFile = CreateFile("C:\\Users\\Asus\\Desktop\\test.png", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten = 0;
WriteFile(hFile, memRes, sizeRes, &dwWritten, NULL);
CloseHandle(hFile);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) "C:\\Users\\Asus\\Desktop\\test.png", SPIF_UPDATEINIFILE);
resource file
#include "resource.h"
IDI_ICON1 ICON "chrome.ico"
IDB_PNG1 PNG "C:\\Users\\Asus\\Pictures\\jano.png"
resource.h
#define IDI_ICON1 101
#define IDB_PNG1 102
There are two mistakes in your code:
You are creating the IDB_PNG1 resource as type PNG, but you are asking FindResource() to find a resource whose type is BITMAP instead. The types need to match, so replace RT_BITMAP with TEXT("PNG") in the call to FindResource(). Alternatively, use RCDATA instead of PNG in the .rc file, and then use RT_RCDATA instead of RT_BITMAP/"PNG" in the call to FindResource().
you are passing the wrong handle to LockResource(). You are passing in hResInfo that is returned by FindResource(), but you need to instead pass in hRes that is returned by LoadResource().
RCDATA resource stores integers or strings of characters And the data is returned by LoadResource.
With the statement: IDR_PNG1 RCDATA {"pngwing.png"},
LoadResource returns pngwing.png while LockResource retrieves a pointer to the specified resource in memory.
I am trying to download an image onto the user's desktop from a URL using Win32. I have taken care of all the HTTP request stuff and know for a fact that it is all working well. When I go to call CreateFile() the Visual Studios debugger just says "Exception: Application.exe has triggered a breakpoint" and that it will resume on the CreateFile() line. Also there is an error code "Critical error detected c0000374"
Here is my code:
VARIANT varResponse;
VariantInit(&varResponse);
...
hr = pIWinHttpRequest->get_ResponseBody(&varResponse);
...
if (SUCCEEDED(hr)) {
long upperBounds;
long lowerBounds;
unsigned char* buff;
//Make sure that varResponse is an array of unsigned bytes
if (varResponse.vt == (VT_ARRAY | VT_UI1)) {
long Dims = SafeArrayGetDim(varResponse.parray);
//It should only have one dimension
if (Dims == 1) {
//Get Array lower and upper bounds
SafeArrayGetLBound(varResponse.parray, 1, &lowerBounds);
SafeArrayGetUBound(varResponse.parray, 1, &upperBounds);
upperBounds++;
SafeArrayAccessData(varResponse.parray, (void**)&buff);
HANDLE hFile;
DWORD dwBytesWritten;
PWSTR filepath[MAX_PATH];
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &*filepath);
if (SUCCEEDED(hr)) {
//PathCombine(filepathForImage, filepathToDesktop, L"\\todaysDailyImage.jpg");
PathAppend(*filepath, L"todaysDailyImage.jpg");
MessageBox(NULL, *filepath, L"Check if filepath works", MB_OK);
}
hFile = CreateFile(*filepath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//File failed
}
else {
WriteFile(hFile, buff, upperBounds - lowerBounds, &dwBytesWritten, NULL);
//File was written
}
CloseHandle(hFile);
CoTaskMemFree(filepath);
SafeArrayUnaccessData(varResponse.parray);
MessageBox(NULL, L"Everything was cleaned up", L"Update:", MB_OK);
}
}
}
Am I doing anything wrong?
The way you are using filepath is all wrong.
You are declaring it as an array of MAX_PATH (260) number of PWSTR pointers.
When you refer to an array by its name alone, you end up with a pointer to the 1st element of the array. So, &*filepath is the same as &*(&filepath[0]), which is effectively &filepath[0]. And *filepath is the same as *(&filepath[0]), which is effectively filepath[0]. So, as far as SHGetKnownFolderPath() and MessageBox() are concerned, they are only operating on the 1st PWSTR pointer in the array, and the other 259 array elements are ignored. That part is ok, but wasteful.
However, PathAppend() requires a destination buffer that is an array of MAX_PATH number of WCHAR elements. You are appending to the WCHAR[] array that SHGetKnownFolderPath() allocates as its output, which is not large enough to hold the filename you are trying to append to it. So, you are triggering errors because you are trying to modify memory that hasn’t been allocated to hold that modification.
You don’t need the PWSTR array at all. Try something more like this instead:
PWSTR folderpath;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &folderpath);
if (FAILED(hr)) {
// ...
}
else {
PWSTR filepath;
hr = PathAllocCombine(folderpath, L"todaysDailyImage.jpg", 0, &filepath);
if (FAIlED(hr)) {
// ...
}
else {
MessageBoxW(NULL, filepath, L"Check if filepath works", MB_OK);
hFile = CreateFileW(filepath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//File failed
}
else {
WriteFile(hFile, buff, upperBounds - lowerBounds, &dwBytesWritten, NULL);
//File was written
CloseHandle(hFile);
}
LocalFree(filepath);
}
CoTaskMemFree(folderpath);
}
void Extract(WORD wResId , LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId) , RT_RCDATA);
HGLOBAL hLoaded = LoadResource( NULL,hrsrc);
LPVOID lpLock = LockResource( hLoaded);
DWORD dwSize = SizeofResource(NULL, hrsrc);
HANDLE hFile = CreateFile("C://Windows//Darek//mylo.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwByteWritten;
char* cRes = (char*)malloc (dwSize);
memset(cRes,0,dwSize);
memcpy (cRes, cData, dwSize);
cRes[dwSize] = '\0';
FreeResource(hLoaded);
WriteFile(hFile, lpLock , dwSize , &dwByteWritten , NULL);
CloseHandle(hFile);
FreeResource(hLoaded);
}
Ok this creates the file correctly, but the extracted data doesnt seem to extract and write to the textFile,Any problems? i do not seem to understand why it doesnt extract and Write the data to the file.
Please Help.
You are allocating a memory block that is as large as the resource, zeroing it out (which is redundant), and copying something (what is cData pointing at? Maybe you meant lpLock instead?) into that memory, but then you are ignoring the allocated memory and leaking it. You are trying to write the content of lpLock to the file as-is, which is what you should be doing, but you are not doing any error handling at all. Chances are, your resource is missing, or otherwise not available for reading. That would account for your file being empty.
Try this instead:
void Extract(WORD wResId, LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId), RT_RCDATA);
if (!hrsrc)
{
// GetLastError() tells you why it failed...
return;
}
HGLOBAL hLoaded = LoadResource(NULL, hrsrc);
if (!hLoaded)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwSize = SizeofResource(NULL, hrsrc);
if ((dwSize == 0) && (GetLastError() != 0))
{
// GetLastError() tells you why it failed...
return;
}
LPVOID lpLock = LockResource(hLoaded);
if (!lpLock)
{
// GetLastError() tells you why it failed...
return;
}
HANDLE hFile = CreateFileA(lpszOutputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwByteWritten;
if (!WriteFile(hFile, lpLock, dwSize, &dwByteWritten, NULL))
{
// GetLastError() tells you why it failed...
CloseHandle(hFile);
DeleteFileA(lpszOutputPath);
return;
}
CloseHandle(hFile);
}
If I had to guess (and please don't make people guess), FindResource() is most likely returning NULL. Make sure the second parameter actually matches the correct resource type for wResId. You cannot load any arbitrary resource using RT_RCDATA, you have to use the correct resource type. Only resources using the RCDATA type can be accessed using the RT_RCDATA parameter value. String resources might be stored using the RT_MESSAGETABLE or RT_STRING type instead, for instance. You can use EnumResourceTypes() and EnumResourceNames(), or an external resource editor/viewer tool, to find out what type the wResId resource is actually using.
I use this code to load embedded resource (bitmap image)
HRSRC hResInfo = ::FindResource(hInstance, MAKEINTRESOURCE(resourceId), RT_BITMAP);
HGLOBAL hRes = ::LoadResource(hInstance, hResInfo);
LPVOID memRes = ::LockResource(hRes);
DWORD sizeRes = ::SizeofResource(hInstance, hResInfo);
It works fine.
How I can to save it to the file C:\image.bmp?
This code creates only empty file:
HANDLE hFile = ::CreateFile(L"C:\\image.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten = 0;
::WriteFile(hFile, memRes, sizeRes, &dwWritten, NULL);
::CloseHandle(hFile);
SOLUTION:
Create new type "BMP" in resources and place image
HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(resourceId), _T("BMP"));
CreateFile(), WriteFile(), and CloseHandle().
WriteFile() takes a pointer and a size so can write from the locked resource directly.