mirror of
https://github.com/Fatmike-GH/Fatpack
synced 2026-06-06 15:44:28 +00:00
229 lines
6.6 KiB
C++
229 lines
6.6 KiB
C++
#include "IconExtractor.h"
|
|
#include "..\..\Shared\ApiCaller\ApiCaller.h"
|
|
|
|
namespace IconExtractor
|
|
{
|
|
#pragma pack(push, 1)
|
|
typedef struct
|
|
{
|
|
BYTE Width, Height, ColorCount, Reserved;
|
|
WORD Planes, BitCount;
|
|
DWORD BytesInRes;
|
|
WORD ID;
|
|
} ICONENTRY;
|
|
|
|
typedef struct
|
|
{
|
|
WORD Reserved, Type, Count;
|
|
ICONENTRY Entries[1]; // Variable length
|
|
} ICONGROUP;
|
|
#pragma pack(pop)
|
|
|
|
IconExtractor::IconExtractor()
|
|
{
|
|
}
|
|
|
|
IconExtractor::~IconExtractor()
|
|
{
|
|
}
|
|
|
|
bool IconExtractor::ExtractAndSetIcon(LPWSTR sourceExe, LPWSTR targetExe)
|
|
{
|
|
HMODULE sourceModuleHandle = LoadLibraryExW(sourceExe, nullptr, LOAD_LIBRARY_AS_DATAFILE);
|
|
if (!sourceModuleHandle)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
LPCWSTR groupIconName = nullptr;
|
|
EnumResourceNames(sourceModuleHandle, RT_GROUP_ICON, EnumResNameProc, (LONG_PTR)&groupIconName);
|
|
|
|
if (!groupIconName)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
HRSRC groupIconHandle = ApiCaller::ApiCaller::Instance().CallFindResourceW(sourceModuleHandle, groupIconName, RT_GROUP_ICON);
|
|
if (!groupIconHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
HGLOBAL groupIconDataHandle = LoadResource(sourceModuleHandle, groupIconHandle);
|
|
if (!groupIconDataHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
LPVOID groupIconData = LockResource(groupIconDataHandle);
|
|
DWORD groupIconSize = SizeofResource(sourceModuleHandle, groupIconHandle);
|
|
|
|
HANDLE updateHandle = BeginUpdateResourceW(targetExe, FALSE);
|
|
if (!updateHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
// Update the icon group resource
|
|
if (!UpdateResource(updateHandle, RT_GROUP_ICON, groupIconName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), groupIconData, groupIconSize))
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
ICONGROUP* iconGroup = (ICONGROUP*)groupIconData;
|
|
for (int i = 0; i < iconGroup->Count; i++)
|
|
{
|
|
WORD iconId = iconGroup->Entries[i].ID;
|
|
HRSRC iconHandle = ApiCaller::ApiCaller::Instance().CallFindResourceW(sourceModuleHandle, MAKEINTRESOURCE(iconId), RT_ICON);
|
|
if (iconHandle)
|
|
{
|
|
HGLOBAL iconDataHandle = LoadResource(sourceModuleHandle, iconHandle);
|
|
if (iconDataHandle)
|
|
{
|
|
LPVOID iconData = LockResource(iconDataHandle);
|
|
DWORD iconSize = SizeofResource(sourceModuleHandle, iconHandle);
|
|
|
|
if (!UpdateResource(updateHandle, RT_ICON, MAKEINTRESOURCE(iconId), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), iconData, iconSize))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Finalize the update
|
|
if (!EndUpdateResource(updateHandle, FALSE))
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
FreeLibrary(sourceModuleHandle);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IconExtractor::ExtractAndSetIconWithCustomIds(LPWSTR sourceExe, LPWSTR targetExe)
|
|
{
|
|
HMODULE sourceModuleHandle = LoadLibraryExW(sourceExe, nullptr, LOAD_LIBRARY_AS_DATAFILE);
|
|
if (!sourceModuleHandle)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
LPCWSTR groupIconName = nullptr;
|
|
EnumResourceNames(sourceModuleHandle, RT_GROUP_ICON, EnumResNameProc, (LONG_PTR)&groupIconName);
|
|
|
|
if (!groupIconName)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return true;
|
|
}
|
|
|
|
// Find and load the RT_GROUP_ICON resource
|
|
HRSRC groupIconHandle = ApiCaller::ApiCaller::Instance().CallFindResourceW(sourceModuleHandle, groupIconName, RT_GROUP_ICON);
|
|
if (!groupIconHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return true;
|
|
}
|
|
|
|
HGLOBAL groupIconDataHandle = LoadResource(sourceModuleHandle, groupIconHandle);
|
|
if (!groupIconDataHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return true;
|
|
}
|
|
|
|
ICONGROUP* groupIcon = (ICONGROUP*)LockResource(groupIconDataHandle);
|
|
DWORD groupIconSize = SizeofResource(sourceModuleHandle, groupIconHandle);
|
|
|
|
// Create a copy of the RT_GROUP_ICON structure to modify it
|
|
DWORD newGroupIconSize = sizeof(ICONGROUP) + (groupIcon->Count - 1) * sizeof(ICONENTRY);
|
|
ICONGROUP* newGroupIcon = (ICONGROUP*)malloc(newGroupIconSize);
|
|
if (!newGroupIcon)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
return false;
|
|
}
|
|
|
|
// Copy original RT_GROUP_ICON data
|
|
memcpy(newGroupIcon, groupIcon, newGroupIconSize);
|
|
|
|
HANDLE updataHandle = BeginUpdateResourceW(targetExe, FALSE);
|
|
if (!updataHandle)
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
free(newGroupIcon);
|
|
return false;
|
|
}
|
|
|
|
// Update the icon group with a new ID
|
|
if (!UpdateResource(updataHandle, RT_GROUP_ICON, MAKEINTRESOURCE(CUSTOM_ICON_GROUP_ID), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newGroupIcon, newGroupIconSize))
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
free(newGroupIcon);
|
|
return false;
|
|
}
|
|
|
|
// Extract and update RT_ICON resources with new IDs
|
|
for (int i = 0; i < groupIcon->Count; i++)
|
|
{
|
|
WORD oldIconId = groupIcon->Entries[i].ID;
|
|
WORD newIconId = CUSTOM_ICON_BASE_ID + i;
|
|
|
|
HRSRC oldIconHandle = ApiCaller::ApiCaller::Instance().CallFindResourceW(sourceModuleHandle, MAKEINTRESOURCE(oldIconId), RT_ICON);
|
|
if (oldIconHandle)
|
|
{
|
|
HGLOBAL oldIconDataHandle = LoadResource(sourceModuleHandle, oldIconHandle);
|
|
if (oldIconDataHandle)
|
|
{
|
|
LPVOID oldIconData = LockResource(oldIconDataHandle);
|
|
DWORD oldIconSize = SizeofResource(sourceModuleHandle, oldIconHandle);
|
|
|
|
if (UpdateResource(updataHandle, RT_ICON, MAKEINTRESOURCE(newIconId), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), oldIconData, oldIconSize))
|
|
{
|
|
// Modify the RT_GROUP_ICON to reference new IDs
|
|
newGroupIcon->Entries[i].ID = newIconId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update RT_GROUP_ICON with corrected icon IDs
|
|
if (!UpdateResource(updataHandle, RT_GROUP_ICON, MAKEINTRESOURCE(CUSTOM_ICON_GROUP_ID), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newGroupIcon, newGroupIconSize))
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
free(newGroupIcon);
|
|
return false;
|
|
}
|
|
|
|
// Finalize the update
|
|
if (!EndUpdateResource(updataHandle, FALSE))
|
|
{
|
|
FreeLibrary(sourceModuleHandle);
|
|
free(newGroupIcon);
|
|
return false;
|
|
}
|
|
|
|
FreeLibrary(sourceModuleHandle);
|
|
free(newGroupIcon);
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL CALLBACK IconExtractor::EnumResNameProc(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
|
|
{
|
|
if (lpType == RT_GROUP_ICON)
|
|
{
|
|
*((LPWSTR*)lParam) = lpName;
|
|
return FALSE; // Stop after finding the first icon
|
|
}
|
|
return TRUE;
|
|
}
|
|
} |