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)
Related
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);
}
Recently I posted this question and now I am trying to set a reparse point after a file modification with WordPad app. Currently I checked that the reparse point is a Microsoft tag and I can save the reparse point data in a REPARSE_DATA_BUFFER pointer before the file lose the reparse point. But when I try to set the reparse point to the file, after a file modification, I always get the 395 error with the GetLastError function after call to DeviceIoControl function using the control code FSCTL_SET_REPARSE_POINT. The error 395 doesn't appear in this System Error Codes although I found this error here that has sense. I also removed the discretionary access control list (DACL) from the file, to grants full access to the file by everyone, before try to set the reparse point but I got the same error. Here I put two fragments of my code to get and set the reparse point. I will appreciate any help.
Code to get the reparse point
HANDLE hDevice = CreateFile(
filePath.c_str(), // File path in the computer
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
rdb = (REPARSE_DATA_BUFFER*)malloc(maxReparse); // rdb was declared as: REPARSE_DATA_BUFFER* rdb;
DWORD outBufferSize = maxReparse;
DWORD bytesReturned = 0;
if (DeviceIoControl(hDevice, FSCTL_GET_REPARSE_POINT, NULL, 0, rdb, outBufferSize, &bytesReturned, NULL))
{
if (rdb != NULL)
{
if (IsReparseTagMicrosoft(rdb->ReparseTag))
{
wprintf(L"Is a Microsoft tag.\n");
}
Code to set the reparse point
LPTSTR pszObjName = const_cast<wchar_t*>(filePath.c_str()); // File path in the computer
PACL newDACL = NULL; // NULL discretionary access control list to grant full access to everyone
DWORD secInfo = SetNamedSecurityInfo(pszObjName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newDACL, NULL);
if (secInfo == ERROR_SUCCESS)
{
HANDLE hDevice = CreateFile(filePath.c_str(),
GENERIC_ALL, //GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
DWORD inBufferSize = maxReparse;
if (rdb != NULL)
{
DWORD bytesReturned = 0;
if (!DeviceIoControl(hDevice, FSCTL_SET_REPARSE_POINT, rdb, inBufferSize, NULL, 0, &bytesReturned, NULL))
{
DWORD error = GetLastError(); // Error 395
unsigned long errorUL = error;
wprintf(L"Error %lu in DeviceIoControl method.\n", errorUL);
}
I want to read data from a file (.txt) and push into Edit box.
I'm writing C++ with pure API.
HANDLE hFile;
HANDLE hMapFile;
LPVOID pMemory;
and
case IDM_OPEN:
hFile = CreateFile((LPCWSTR)szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
pMemory = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0,0,0);
FileSize = GetFileSize(hFile, NULL);
SendMessage(hWndEdit, WM_SETTEXT, 0, (LPARAM)(LPCWSTR)pMemory);
MessageBox(hWnd, (LPCWSTR)pMemory, L"Caption", MB_OK);
UnmapViewOfFile(pMemory);
CloseHandle(hMapFile);
CloseHandle(hFile);
break;
Result: Blank, nothing in Edit box
I search some page but not solved.
When I try debug by set breakpoint like this image:
http://i8.upanh.com/2013/1103/02//57993893.untitled.png
(Sorry I can't post image)
hFile is 0xffffffff, so I think error is CreateFile, but I don't understand !!
Please help me solve this. Thanks !!!
hFile = CreateFile((LPCWSTR)szFileName,....
Why the cast to LPCWSTR? If you need that cast you are doing something wrong. Investigate each step with a debugger to learn more about what is wrong.
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 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.