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.
Related
I'm trying to get the name of processes which have a visible window. For example, if I have Chrome opened, I would like to get the string "chrome.exe", but I only get the init value "unknown" using the code below.
I read around it could be an access rights problem, can you suggest me how to change them in order to get the name of processes?
DWORD idProc = 0; //pointer to the process which created the window
DWORD idThread = GetWindowThreadProcessId(Wnd->get_handle(), &idProc);
Wnd->set_pid(idThread); //Wnd is an object of a class i created, to collect processes info
// Get a handle to the process.
TCHAR szProcessName[DEFAULT_BUFLEN] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, idProc);
if (hProcess!=NULL) {
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
&cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName,
sizeof(szProcessName) / sizeof(TCHAR));
}
}
Wnd->set_processname(szProcessName);
CloseHandle(hProcess);
It works fine for some processes, but it doesn't for many others like Chrome, as I said.
EDIT: I forgot to say, I've just filtered visible windows, so suppose handles are what I need yet.
this question how get process name/path by ID - is many time already answered here.
if you need name only (but not full path) - you can use CreateToolhelp32Snapshot / Process32First / Process32Next
compare PROCESSENTRY32.th32ProcessID with your idProc and use PROCESSENTRY32.szExeFile.
alternate and more effective way use ZwQuerySystemInformation with SystemProcessInformation info class.compare SYSTEM_PROCESS_INFORMATION.UniqueProcessId with your idProc and use SYSTEM_PROCESS_INFORMATION.ImageName. really first way is shell over this method.
if you need not only name, but full path :
if you have SE_DEBUG_PRIVILEGE - you need enable it, open process with PROCESS_QUERY_LIMITED_INFORMATION (vista+) or PROCESS_QUERY_INFORMATION (xp/2003) and use ZwQueryInformationProcess with ProcessImageFileName (return path in NT form) or GetProcessImageFileName (internally it call ZwQueryInformationProcess(,ProcessImageFileName,))
or begin from vista - you can use ProcessImageFileNameWin32 (return win32-path) or QueryFullProcessImageName (again only documented thin shell over this way)
also begin from vista - most effective way query process full path (in NT form) - use ZwQuerySystemInformation with SystemProcessIdInformation info class. this way not require any privileges and open process
use GetProcessImageNamr API instead:
#include <iostream>
using namespace std;
#include <windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
int main()
{
DWORD dwProcessId;
DWORD dwThreadId ;
while(1)
{
Sleep(2000);
HWND hForg = GetForegroundWindow(); // to get the foreground windows' handle window
dwThreadId = GetWindowThreadProcessId(hForg, &dwProcessId); // getting the window's process ID
DWORD dwDesiredAccess =
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
bool bInheritHandle = false;
HANDLE hProcess = OpenProcess(dwDesiredAccess,
bInheritHandle, dwProcessId);
if(INVALID_HANDLE_VALUE == hProcess)
cout << "Failed to open process!" << endl;
HINSTANCE hMod = (HINSTANCE)GetWindowLongPtr(hForg, GWLP_HINSTANCE);
if(!hMod)
cout << "Null Module!" << endl;
char szModFileName[MAX_PATH] = "";
// never use this cause it won't get you what you want
// GetModuleFileNameEx(hProcess, hMod, szModFileName, MAX_PATH);
// use this
GetProcessImageFileName(hProcess, szModFileName, MAX_PATH);
CloseHandle(hProcess);
char szWindowName[MAX_PATH] = "";
GetWindowText(hForg, szWindowName, MAX_PATH);
cout << "Window Name: " << szWindowName << endl;
cout << "Created by: " << szModFileName << endl << endl;
}
cout << endl << endl << endl;
return 0;
}
don't use GetModuleFileNameEx but use GetProcessImageFileName
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'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.
i have loaded an icon ("c:\test.ico") using LoadImage() function
how can i get the size of this icon? (number of bytes in it)
i am using c++ & winapi
HRSRC hRes = LoadImage ( NULL, icon, IMAGE_ICON, 0, 0, LR_LOADFROMFILE );
LPVOID lpResLock = LockResource(hRes);
(more precisely, size of data pointed to by "lpResLock")
========update======
i know about sizeofresource() But the problem is, its to load resource from an executable files. As i shown in my question, i am loading a standalone- local resource from disk file. Second issue is, the hResInfo parameter must have to be created using FindResource function, in my case i am using LoadImage().. So this cant be of help
Google for SizeofResource(). Its a standard win32 API function IIRC
This is the function prototype:
DWORD WINAPI SizeofResource(
_In_opt_ HMODULE hModule,
_In_ HRSRC hResInfo
);
Parameters:
hModule [in, optional] Type: HMODULE
A handle to the module whose executable file contains the resource.
hResInfo [in] Type: HRSRC
A handle to the resource. This handle must be created by using the FindResource or FindResourceEx function.
Update-
Then, the length of resource from a file = sizeof the file.
use: GetFileLength() function coded like this:
DWORD GetFileLength(LPSTR fileName)
{
DWORD len = 0;
OFSTRUCT of;
HFILE hFile = OpenFile(fileName,&of, OF_READ);
GetFileSize(hFile,&len);
CloseHandle(hFile);
return len;
}
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.