Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save missdeer/9e0d1d5eefe4b04a5a43c63638af9876 to your computer and use it in GitHub Desktop.
Save missdeer/9e0d1d5eefe4b04a5a43c63638af9876 to your computer and use it in GitHub Desktop.
Icon changer
#include <windows.h>
#include <stdio.h>
#pragma pack(push, 2)
#define RT_ICON MAKEINTRESOURCE(3)
#define RT_GROUP_ICON MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
/* Icon file header */
typedef struct
{
WORD Reserved;
WORD ResourceType;
WORD ImageCount;
} IconFileHeader;
/* Icon File directory entry structure */
typedef struct
{
BYTE Width;
BYTE Height;
BYTE Colors;
BYTE Reserved;
WORD Planes;
WORD BitsPerPixel;
DWORD ImageSize;
DWORD ImageOffset;
} IconDirectoryEntry;
/* Group Icon Resource directory entry structure */
typedef struct
{
BYTE Width;
BYTE Height;
BYTE Colors;
BYTE Reserved;
WORD Planes;
WORD BitsPerPixel;
DWORD ImageSize;
WORD ResourceID;
} IconDirResEntry, *PIconDirResEntry;
/* Group Icon Structore (RT_GROUP_ICON) */
typedef struct
{
WORD Reserved;
WORD ResourceType;
WORD ImageCount;
IconDirResEntry Enries[0]; /* Number of these is in ImageCount */
} GroupIcon;
#pragma pack(pop)
BOOL UpdateIcon(LPTSTR ExecutableFileName, LPTSTR IconFileName)
{
HANDLE h = BeginUpdateResource(ExecutableFileName, FALSE);
if (h == INVALID_HANDLE_VALUE)
{
printf("Failed to BeginUpdateResource\n");
return FALSE;
}
/* Read the Icon file */
HANDLE hIconFile = CreateFile(IconFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hIconFile == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Failed to open icon file.\n");
return FALSE;
}
DWORD Size = GetFileSize(hIconFile, NULL);
BYTE* Data = (LPBYTE)LocalAlloc(LMEM_FIXED, Size);
DWORD BytesRead;
if (!ReadFile(hIconFile, Data, Size, &BytesRead, NULL))
{
fprintf(stderr, "Failed to read icon file.\n");
return FALSE;
}
CloseHandle(hIconFile);
IconFileHeader* header = (IconFileHeader*)Data;
IconDirectoryEntry* entries = (IconDirectoryEntry*)(header + 1);
/* Create the RT_ICON resources */
int i;
for (i = 0; i < header->ImageCount; ++i)
{
BOOL b = UpdateResource(h, RT_ICON, MAKEINTRESOURCE(101 + i), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Data + entries[i].ImageOffset, entries[i].ImageSize);
if (!b)
{
fprintf(stderr, "failed to UpdateResource %lu\n", GetLastError());
return FALSE;
}
}
/* Create the RT_GROUP_ICON structure */
DWORD GroupIconSize = sizeof(GroupIcon) + header->ImageCount * sizeof(IconDirectoryEntry);
GroupIcon* gi = (GroupIcon*)LocalAlloc(LMEM_FIXED, GroupIconSize);
gi->Reserved = 0;
gi->ResourceType = header->ResourceType;
gi->ImageCount = header->ImageCount;
for (i = 0; i < header->ImageCount; ++i)
{
IconDirResEntry* e = &gi->Enries[i];
e->Width = entries[i].Width;
e->Height = entries[i].Height;
e->Colors = entries[i].Colors;
e->Reserved = entries[i].Reserved;
e->Planes = entries[i].Planes;
e->BitsPerPixel = entries[i].BitsPerPixel;
e->ImageSize = entries[i].ImageSize;
e->ResourceID = 101 + i;
}
/* Save the RT_GROUP_ICON resource */
BOOL b = UpdateResourceA(h, RT_GROUP_ICON, "MAINICON", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gi, GroupIconSize);
if (!b)
{
fprintf(stderr, "Failed to create group icon.\n");
return FALSE;
}
if (!EndUpdateResource(h, FALSE))
{
fprintf(stderr, "Failed to EndUpdateResource.\n");
return FALSE;
}
return TRUE;
}
int main(int argc, char* argv[])
{
if (argc == 3)
{
if (UpdateIcon(argv[1], argv[2]))
return 0;
else
return -1;
}
else
{
fprintf(stderr, "Usage: edicon.exe <exefile> <icofile>\n");
return -1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment