Skip to content

Instantly share code, notes, and snippets.

@rbmm
Created October 8, 2024 14:53
Show Gist options
  • Save rbmm/091daa1a39a7e9c9e95b3d1458da1109 to your computer and use it in GitHub Desktop.
Save rbmm/091daa1a39a7e9c9e95b3d1458da1109 to your computer and use it in GitHub Desktop.
#pragma pack(push, 2 )
struct ICONDIRENTRY
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
WORD nID;
};
struct ICONDIR
{
WORD Reserved; // Reserved
WORD Type; // resource type (IMAGE_ICON for icons)
WORD Count; // how many images?
ICONDIRENTRY Entries[]; // the entries for each image
};
#pragma pack( pop )
struct BestIcon
{
ULONG _M_d = MAXULONG;
WORD _M_wBitCount;
WORD _M_nID;
void ProcessIconDir(ICONDIR* pid, ULONG s, ULONG cxDesired, ULONG bHeight);
void Process(PVOID ImageBase, PBYTE Base, PIMAGE_RESOURCE_DIRECTORY pird, ULONG cxDesired, ULONG cyDesired);
void Process_I(PVOID ImageBase, PBYTE Base, PIMAGE_RESOURCE_DIRECTORY pird, ULONG cxDesired, ULONG cyDesired);
};
void BestIcon::ProcessIconDir(ICONDIR* pid, ULONG s, ULONG cxDesired, ULONG cyDesired)
{
if (sizeof(ICONDIR) < s)
{
if (1 == pid->Type)
{
if (!((s -= sizeof(ICONDIR)) % sizeof(ICONDIRENTRY)))
{
if ((s /= sizeof(ICONDIRENTRY)) == pid->Count)
{
ICONDIRENTRY* Entry = pid->Entries;
do
{
ULONG w = cxDesired - Entry->bWidth;
ULONG h = cyDesired - Entry->bHeight;
if ((w = w*w + h*h) <= _M_d)
{
if (w == _M_d)
{
if (Entry->wBitCount <= _M_wBitCount)
{
continue;
}
}
_M_d = w;
_M_wBitCount = Entry->wBitCount;
_M_nID = Entry->nID;
}
} while (Entry++, --s);
}
}
}
}
}
void BestIcon::Process_I(PVOID ImageBase, PBYTE Base, PIMAGE_RESOURCE_DIRECTORY pird, ULONG cxDesired, ULONG cyDesired)
{
if (ULONG n = pird->NumberOfNamedEntries + pird->NumberOfIdEntries)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pird + 1);
do
{
union {
PBYTE pv;
PIMAGE_RESOURCE_DIRECTORY p;
PIMAGE_RESOURCE_DATA_ENTRY pirde;
};
pv = Base + Entry->OffsetToDirectory;
if (Entry->DataIsDirectory)
{
Process_I(ImageBase, Base, p, cxDesired, cyDesired);
}
else
{
ProcessIconDir((ICONDIR*)RtlOffsetToPointer(ImageBase, pirde->OffsetToData), pirde->Size, cxDesired, cyDesired);
}
} while (Entry++, --n);
}
}
void BestIcon::Process(PVOID ImageBase, PBYTE Base, PIMAGE_RESOURCE_DIRECTORY pird, ULONG cxDesired, ULONG cyDesired)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pird + 1) + pird->NumberOfNamedEntries;
if (ULONG n = pird->NumberOfIdEntries)
{
do
{
if (!Entry->NameIsString && (ULONG_PTR)RT_GROUP_ICON == Entry->Id)
{
union {
PBYTE pv;
PIMAGE_RESOURCE_DIRECTORY p;
PIMAGE_RESOURCE_DATA_ENTRY pirde;
};
if (Entry->DataIsDirectory)
{
pv = Base + Entry->OffsetToDirectory;
Process_I(ImageBase, Base, p, cxDesired, cyDesired);
}
break;
}
} while (Entry++, --n);
}
}
HICON GetIcon(PVOID ImageBase, PBYTE Base, PIMAGE_RESOURCE_DIRECTORY pird, PULONG pu, ULONG n, ULONG cxDesired, ULONG cyDesired)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY Entry;
if (n)
{
Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pird + 1) + pird->NumberOfNamedEntries;
if (ULONG m = pird->NumberOfIdEntries)
{
ULONG nID = *pu++;
do
{
if (!Entry->NameIsString && nID == Entry->Id)
{
union {
PBYTE pv;
PIMAGE_RESOURCE_DIRECTORY p;
PIMAGE_RESOURCE_DATA_ENTRY pirde;
};
if (Entry->DataIsDirectory)
{
pv = Base + Entry->OffsetToDirectory;
return GetIcon(ImageBase, Base, p, pu, n - 1, cxDesired, cyDesired);
}
}
} while (Entry++, --m);
}
return 0;
}
if (pird->NumberOfNamedEntries + pird->NumberOfIdEntries)
{
Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pird + 1);
union {
PBYTE pv;
PIMAGE_RESOURCE_DIRECTORY p;
PIMAGE_RESOURCE_DATA_ENTRY pirde;
};
pv = Base + Entry->OffsetToDirectory;
if (Entry->DataIsDirectory)
{
return GetIcon(ImageBase, Base, p, 0, 0, cxDesired, cyDesired);
}
else
{
return CreateIconFromResourceEx((PBYTE)RtlOffsetToPointer(ImageBase, pirde->OffsetToData),
pirde->Size, TRUE, 0x00030000, cxDesired, cyDesired, 0);
}
}
return 0;
}
void ShowIcon(PCWSTR lpLibFileName, ULONG cxDesired, ULONG cyDesired)
{
if (HMODULE hmod = LoadLibraryExW(lpLibFileName, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE))
{
__try
{
ULONG s;
if (PIMAGE_RESOURCE_DIRECTORY pird = (PIMAGE_RESOURCE_DIRECTORY)
RtlImageDirectoryEntryToData(hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &s))
{
BestIcon bi;
PVOID ImageBase = PAGE_ALIGN(hmod);
bi.Process(ImageBase, (PBYTE)pird, pird, cxDesired, cyDesired);
if (bi._M_d < MAXULONG)
{
ULONG a[] = { (ULONG)(ULONG_PTR)RT_ICON, bi._M_nID };
if (HICON hi = GetIcon(ImageBase, (PBYTE)pird, pird, a, _countof(a), cxDesired, cyDesired))
{
TASKDIALOGCONFIG TaskConfig = {
sizeof(TaskConfig), 0, 0, TDF_USE_HICON_MAIN, TDCBF_CLOSE_BUTTON, 0, { hi }
};
TaskDialogIndirect(&TaskConfig, 0, 0, 0);
DestroyIcon(hi);
}
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
FreeLibrary(hmod);
}
}
ShowIcon(L"notepad.exe", GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment