Created
October 8, 2024 14:49
-
-
Save rbmm/9432ca83e3db17219b46b05262987288 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
}; | |
pv = Base + Entry->OffsetToDirectory; | |
if (Entry->DataIsDirectory) | |
{ | |
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; | |
}; | |
pv = Base + Entry->OffsetToDirectory; | |
if (Entry->DataIsDirectory) | |
{ | |
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