we can use CreateIconFromResourceEx instead gdi++ . example of convert base64 to HICON (assumed that wholea icon file is converted to base64)
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?
DWORD dwImageOffset; // where in the file is this image
};
struct ICONDIR
{
WORD NotInFile; // not in file
WORD Reserved; // Reserved
WORD Type; // resource type (IMAGE_ICON for icons)
WORD Count; // how many images?
ICONDIRENTRY Entries[]; // the entries for each image
};
HICON LoadIcon(_In_ ICONDIR* pid, _In_ ULONG cb, _In_ ULONG cxDesired, _In_ ULONG cyDesired)
{
if (cb < sizeof(ICONDIR) || pid->Type != IMAGE_ICON)
{
return 0;
}
if (ULONG Count = pid->Count)
{
if (cb < sizeof(ICONDIR) + Count * sizeof(ICONDIRENTRY))
{
return FALSE;
}
ICONDIRENTRY* Entry = pid->Entries;
do
{
if (Entry->bWidth == cxDesired && Entry->bHeight == cyDesired)
{
if (Entry->wPlanes != 1)
{
return 0;
}
switch (Entry->bColorCount)
{
case 0:
case 1:
case 4:
case 8:
case 16:
case 24:
case 32:
break;
default:
return 0;
}
DWORD dwImageOffset = Entry->dwImageOffset + FIELD_OFFSET(ICONDIR, Reserved);
if (cb < dwImageOffset)
{
return 0;
}
DWORD dwBytesInRes = Entry->dwBytesInRes;
if (cb - dwImageOffset < dwBytesInRes)
{
return 0;
}
return CreateIconFromResourceEx((PBYTE)pid + dwImageOffset, dwBytesInRes, TRUE, 0x00030000, cxDesired, cyDesired, 0);
}
} while (Entry++, --Count);
}
return 0;
}
HICON LoadIcon(_In_ PSTR psz, _In_ ULONG cch, _In_ int cxDesired, _In_ int cyDesired)
{
ULONG cb = 0;
PUCHAR pb = 0;
PUCHAR buf = 0;
HICON hi = 0;
while (CryptStringToBinaryA(psz, cch, CRYPT_STRING_BASE64, pb, &cb, 0, 0))
{
if (pb)
{
hi = LoadIcon((ICONDIR*)buf, cb + FIELD_OFFSET(ICONDIR, Reserved), cxDesired, cyDesired);
break;
}
if (cb < sizeof(ICONDIR))
{
break;
}
if (!(buf = new UCHAR[cb + FIELD_OFFSET(ICONDIR, Reserved)]))
{
break;
}
pb = buf + FIELD_OFFSET(ICONDIR, Reserved);
}
if (buf) delete [] buf;
return hi;
}
for convert icon file to base 64 can use next code:
BOOL IsValidIcon(_In_ ICONDIR* pid, _In_ ULONG cb)
{
if (cb < sizeof(ICONDIR) || pid->Type != IMAGE_ICON)
{
return FALSE;
}
if (ULONG Count = pid->Count)
{
if (cb < sizeof(ICONDIR) + Count * sizeof(ICONDIRENTRY))
{
return FALSE;
}
ICONDIRENTRY* Entry = pid->Entries;
do
{
if (Entry->wPlanes != 1)
{
return FALSE;
}
switch (Entry->bColorCount)
{
case 0:
case 1:
case 4:
case 8:
case 16:
case 24:
case 32:
break;
default:
return FALSE;
}
DWORD dwImageOffset = Entry->dwImageOffset + FIELD_OFFSET(ICONDIR, Reserved);
if (cb < dwImageOffset)
{
return FALSE;
}
DWORD dwBytesInRes = Entry->dwBytesInRes;
if (cb - dwImageOffset < dwBytesInRes)
{
return FALSE;
}
} while (Entry++, --Count);
}
return FALSE;
}
BOOL mi(_In_ PCWSTR lpIconName, _Out_ PSTR* ppsz, _Out_ ULONG* pcch)
{
HANDLE hFile = CreateFileW(lpIconName, FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL f = FALSE;
FILE_STANDARD_INFO fsi;
if (GetFileInformationByHandleEx(hFile, FileStandardInfo, &fsi, sizeof(fsi)))
{
if ((ULONG64)fsi.EndOfFile.QuadPart - 1 < 0x100000)
{
if (PBYTE buf = new UCHAR[fsi.EndOfFile.LowPart + FIELD_OFFSET(ICONDIR, Reserved)])
{
PBYTE pb = buf + FIELD_OFFSET(ICONDIR, Reserved);
if (ReadFile(hFile, pb, fsi.EndOfFile.LowPart, &fsi.EndOfFile.LowPart, 0) &&
IsValidIcon((ICONDIR*)buf, fsi.EndOfFile.LowPart) + FIELD_OFFSET(ICONDIR, Reserved))
{
ULONG cch = 0;
PSTR psz = 0;
while (CryptBinaryToStringA(pb, fsi.EndOfFile.LowPart, CRYPT_STRING_BASE64|CRYPT_STRING_NOCRLF, psz, &cch))
{
if (psz)
{
*pcch = cch, *ppsz = psz, psz = 0, f = TRUE;
break;
}
if (!(psz = new CHAR[cch]))
{
break;
}
}
if (psz)
{
delete [] psz;
}
}
delete [] buf;
}
}
}
CloseHandle(hFile);
return f;
}
for test icon:
ULONG cch;
PSTR psz;
if (mi(L"...ico", &psz, &cch))
{
HICON hi = LoadIcon(psz, cch, 48, 48);
delete [] psz;
if (hi)
{
TASKDIALOGCONFIG TaskConfig = {
sizeof(TaskConfig), 0, 0, TDF_USE_HICON_MAIN, TDCBF_CLOSE_BUTTON, 0, {hi}
};
TaskDialogIndirect(&TaskConfig, 0, 0, 0);
DestroyIcon(hi);
}
}