2462 lines
54 KiB
C
2462 lines
54 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
icons.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Icon extraction and manipulation routines
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Jim Schmidt (jimschm) 04-May-1998
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
jimschm 23-Sep-1998 String icon ID bug fixes, error path bug fixes
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "migutilp.h"
|
||
|
|
||
|
#define MAX_RESOLUTIONS 32 // 8 sizes times 4 color palettes
|
||
|
|
||
|
#pragma pack(push)
|
||
|
#pragma pack(2)
|
||
|
|
||
|
typedef struct {
|
||
|
BYTE Width; // Width, in pixels, of the image
|
||
|
BYTE Height; // Height, in pixels, of the image
|
||
|
BYTE ColorCount; // Number of colors in image (0 if >=8bpp)
|
||
|
BYTE Reserved; // Reserved ( must be 0)
|
||
|
WORD Planes; // Color Planes
|
||
|
WORD BitCount; // Bits per pixel
|
||
|
DWORD BytesInRes; // How many bytes in this resource?
|
||
|
DWORD ImageOffset; // Where in the file is this image?
|
||
|
} ICONDIRENTRY, *PICONDIRENTRY;
|
||
|
|
||
|
typedef struct {
|
||
|
WORD Reserved; // Reserved (must be 0)
|
||
|
WORD Type; // Resource Type (1 for icons)
|
||
|
WORD Count; // How many images?
|
||
|
ICONDIRENTRY Entries[1]; // An entry for each image (idCount of 'em)
|
||
|
} ICONDIR, *PICONDIR;
|
||
|
|
||
|
typedef struct {
|
||
|
BYTE Width; // Width, in pixels, of the image
|
||
|
BYTE Height; // Height, in pixels, of the image
|
||
|
BYTE ColorCount; // Number of colors in image (0 if >=8bpp)
|
||
|
BYTE Reserved; // Reserved
|
||
|
WORD Planes; // Color Planes
|
||
|
WORD BitCount; // Bits per pixel
|
||
|
DWORD BytesInRes; // how many bytes in this resource?
|
||
|
WORD ID; // the ID
|
||
|
} GRPICONDIRENTRY, *PGRPICONDIRENTRY;
|
||
|
|
||
|
typedef struct {
|
||
|
WORD Reserved; // Reserved (must be 0)
|
||
|
WORD Type; // Resource type (1 for icons)
|
||
|
WORD Count; // How many images?
|
||
|
GRPICONDIRENTRY Entries[1]; // The entries for each image
|
||
|
} GRPICONDIR, *PGRPICONDIR;
|
||
|
|
||
|
typedef struct {
|
||
|
WORD Reserved; // Reserved (must be 0)
|
||
|
WORD Type; // Resource type (1 for icons)
|
||
|
WORD Count; // How many images?
|
||
|
} GRPICONDIRBASE, *PGRPICONDIRBASE;
|
||
|
|
||
|
#pragma pack( pop )
|
||
|
|
||
|
#define PICONIMAGE PBYTE
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ReadBinaryBlock (
|
||
|
HANDLE File,
|
||
|
PVOID Buffer,
|
||
|
UINT Size
|
||
|
)
|
||
|
{
|
||
|
DWORD BytesRead;
|
||
|
|
||
|
if (!ReadFile (File, Buffer, Size, &BytesRead, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return Size == BytesRead;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pWriteBinaryBlock (
|
||
|
HANDLE File,
|
||
|
PVOID Buffer,
|
||
|
UINT Size
|
||
|
)
|
||
|
{
|
||
|
DWORD BytesWritten;
|
||
|
|
||
|
if (!WriteFile (File, Buffer, Size, &BytesWritten, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return Size == BytesWritten;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
UINT
|
||
|
Power (
|
||
|
UINT x,
|
||
|
UINT e
|
||
|
)
|
||
|
{
|
||
|
UINT r;
|
||
|
|
||
|
r = 1;
|
||
|
|
||
|
while (e > 0) {
|
||
|
r = r * x;
|
||
|
e--;
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
pComputeSizeOfIconImage (
|
||
|
IN PICONIMAGE IconImage
|
||
|
)
|
||
|
{
|
||
|
PBITMAPINFOHEADER Header;
|
||
|
UINT Size;
|
||
|
UINT Bits;
|
||
|
UINT Colors;
|
||
|
UINT BytesInImage;
|
||
|
|
||
|
Header = (PBITMAPINFOHEADER) IconImage;
|
||
|
|
||
|
Size = Header->biSize;
|
||
|
|
||
|
Bits = Header->biBitCount * Header->biPlanes;
|
||
|
if (Bits > 32) {
|
||
|
Bits = 4;
|
||
|
}
|
||
|
|
||
|
Colors = Power (2, Bits);
|
||
|
|
||
|
if (Bits < 24) {
|
||
|
Size += Colors * sizeof (RGBQUAD);
|
||
|
}
|
||
|
|
||
|
BytesInImage = (Header->biWidth + 7) / 8 * (Header->biHeight / 2);
|
||
|
Size += BytesInImage * Bits; // XOR mask
|
||
|
|
||
|
//
|
||
|
// The following computation is very strange, but it was added based on
|
||
|
// test comparisons.
|
||
|
//
|
||
|
|
||
|
if (Header->biWidth == 32) {
|
||
|
Size += BytesInImage; // AND mask
|
||
|
} else {
|
||
|
Size += BytesInImage + Header->biHeight; // AND mask plus who knows what
|
||
|
}
|
||
|
|
||
|
MYASSERT (Size);
|
||
|
|
||
|
return Size;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pAddIconImagesToGrowBuffer (
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE File,
|
||
|
IN PICONDIRENTRY IconDirEntryBase,
|
||
|
IN WORD Count,
|
||
|
IN DWORD Pos,
|
||
|
IN DWORD Size
|
||
|
)
|
||
|
{
|
||
|
WORD w;
|
||
|
PICONDIRENTRY IconDirEntry;
|
||
|
PBYTE Dest;
|
||
|
DWORD Offset;
|
||
|
|
||
|
for (w = 0 ; w < Count ; w++) {
|
||
|
IconDirEntry = &IconDirEntryBase[w];
|
||
|
|
||
|
Offset = IconDirEntry->ImageOffset & 0x0fffffff;
|
||
|
|
||
|
if (Offset < Pos || Offset >= Size) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
SetFilePointer (File, Offset, NULL, FILE_BEGIN);
|
||
|
|
||
|
Dest = GrowBuffer (Buffer, IconDirEntry->BytesInRes);
|
||
|
if (!Dest) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!ReadBinaryBlock (File, Dest, IconDirEntry->BytesInRes)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IconDirEntry->BytesInRes != pComputeSizeOfIconImage (Dest)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromIcoFileExW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE File
|
||
|
)
|
||
|
{
|
||
|
BOOL b = FALSE;
|
||
|
ICONDIR IconDir;
|
||
|
PICONDIRENTRY IconDirEntryBase = NULL;
|
||
|
DWORD Size;
|
||
|
DWORD Pos;
|
||
|
UINT IconDirEntrySize;
|
||
|
|
||
|
Size = GetFileSize (File, NULL);
|
||
|
SetFilePointer (File, 0, NULL, FILE_BEGIN);
|
||
|
|
||
|
Buffer->End = 0;
|
||
|
|
||
|
__try {
|
||
|
if (!ReadBinaryBlock (File, &IconDir, sizeof (WORD) * 3)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
IconDirEntrySize = (UINT) IconDir.Count * sizeof (ICONDIRENTRY);
|
||
|
|
||
|
if (IconDirEntrySize > (UINT) Size) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
IconDirEntryBase = (PICONDIRENTRY) MemAlloc (g_hHeap, 0, IconDirEntrySize);
|
||
|
if (!IconDirEntryBase) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (!ReadBinaryBlock (File, IconDirEntryBase, IconDirEntrySize)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Pos = SetFilePointer (File, 0, NULL, FILE_CURRENT);
|
||
|
|
||
|
if (!pAddIconImagesToGrowBuffer (Buffer, File, IconDirEntryBase, IconDir.Count, Pos, Size)) {
|
||
|
DEBUGMSG ((DBG_WARNING, "Icon file %ls has a bogus offset", ModuleContainingIcon));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
b = TRUE;
|
||
|
}
|
||
|
__finally {
|
||
|
if (IconDirEntryBase) {
|
||
|
MemFree (g_hHeap, 0, IconDirEntryBase);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromIcoFileExA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE File
|
||
|
)
|
||
|
{
|
||
|
PCWSTR UnicodeFileName;
|
||
|
BOOL b;
|
||
|
|
||
|
UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
|
||
|
if (!UnicodeFileName) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = pGetIconImageArrayFromIcoFileExW (UnicodeFileName, Buffer, File);
|
||
|
|
||
|
PushError();
|
||
|
FreeConvertedStr (UnicodeFileName);
|
||
|
PopError();
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromIcoFileW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
HANDLE File;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
File = CreateFileW (ModuleContainingIcon, GENERIC_READ, 0, NULL,
|
||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
if (File == INVALID_HANDLE_VALUE) {
|
||
|
DEBUGMSG ((DBG_WARNING, "%ls could not be opened", ModuleContainingIcon));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
|
||
|
b = pGetIconImageArrayFromIcoFileExW (ModuleContainingIcon, Buffer, File);
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
CloseHandle (File);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromIcoFileA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
PCWSTR UnicodeFileName;
|
||
|
BOOL b;
|
||
|
|
||
|
UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
|
||
|
if (!UnicodeFileName) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = pGetIconImageArrayFromIcoFileW (UnicodeFileName, Buffer);
|
||
|
|
||
|
PushError();
|
||
|
FreeConvertedStr (UnicodeFileName);
|
||
|
PopError();
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromBinaryExW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN PCWSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE Library,
|
||
|
IN HANDLE Library16
|
||
|
)
|
||
|
{
|
||
|
HRSRC ResourceHandle;
|
||
|
HGLOBAL ResourceBlock;
|
||
|
PBYTE ResourceData;
|
||
|
DWORD ResourceSize;
|
||
|
PBYTE Dest;
|
||
|
BOOL b = FALSE;
|
||
|
PGRPICONDIR GroupIconDir;
|
||
|
WORD w;
|
||
|
|
||
|
if (!GroupIconId) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
|
||
|
Buffer->End = 0;
|
||
|
|
||
|
if (Library) {
|
||
|
|
||
|
//
|
||
|
// Get icon from PE file
|
||
|
//
|
||
|
|
||
|
ResourceHandle = FindResourceW (Library, GroupIconId, (PCWSTR) RT_GROUP_ICON);
|
||
|
if (!ResourceHandle) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
ResourceBlock = LoadResource (Library, ResourceHandle);
|
||
|
if (!ResourceBlock) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
GroupIconDir = (PGRPICONDIR) LockResource (ResourceBlock);
|
||
|
if (!GroupIconDir) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (GroupIconDir->Type != 1) {
|
||
|
DEBUGMSGW_IF ((
|
||
|
(UINT_PTR) GroupIconId < 0x10000,
|
||
|
DBG_ERROR,
|
||
|
"icon type for resource %u is not 1 in %s",
|
||
|
GroupIconId,
|
||
|
ModuleContainingIcon
|
||
|
));
|
||
|
DEBUGMSGW_IF ((
|
||
|
(UINT_PTR) GroupIconId >= 0x10000,
|
||
|
DBG_ERROR,
|
||
|
"icon type for resource %s is not 1 in %s",
|
||
|
GroupIconId,
|
||
|
ModuleContainingIcon
|
||
|
));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (GroupIconDir->Count > MAX_RESOLUTIONS) {
|
||
|
DEBUGMSGW ((DBG_ERROR, "%u resolutions found in %s", GroupIconDir->Count, ModuleContainingIcon));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add the ICONIMAGE array to the grow buffer
|
||
|
//
|
||
|
|
||
|
for (w = 0 ; w < GroupIconDir->Count ; w++) {
|
||
|
|
||
|
ResourceHandle = FindResourceW (
|
||
|
Library,
|
||
|
(PCWSTR) (GroupIconDir->Entries[w].ID),
|
||
|
(PCWSTR) RT_ICON
|
||
|
);
|
||
|
|
||
|
if (ResourceHandle) {
|
||
|
ResourceBlock = LoadResource (Library, ResourceHandle);
|
||
|
if (!ResourceBlock) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ResourceData = (PBYTE) LockResource (ResourceBlock);
|
||
|
if (!ResourceData) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ResourceSize = pComputeSizeOfIconImage ((PICONIMAGE) ResourceData);
|
||
|
if (!ResourceSize) {
|
||
|
DEBUGMSG ((DBG_WARNING, "Zero-length icon in %s", ModuleContainingIcon));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (ResourceSize > 0x10000) {
|
||
|
// too big for an icon
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Dest = GrowBuffer (Buffer, ResourceSize);
|
||
|
if (!Dest) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
CopyMemory (Dest, ResourceData, ResourceSize);
|
||
|
}
|
||
|
ELSE_DEBUGMSG ((DBG_WARNING, "Indexed icon could not be loaded from resource"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (Library16) {
|
||
|
//
|
||
|
// Get icon from NE file
|
||
|
//
|
||
|
|
||
|
GroupIconDir = (PGRPICONDIR) FindNeResourceExW (Library16, (PCWSTR) RT_GROUP_ICON, GroupIconId);
|
||
|
if (!GroupIconDir) {
|
||
|
DEBUGMSG ((DBG_WHOOPS, "NE group icon %u not found", GroupIconId));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
DEBUGMSG_IF ((GroupIconDir->Count > MAX_RESOLUTIONS, DBG_WHOOPS, "%u resolutions found in %hs", GroupIconDir->Count, ModuleContainingIcon));
|
||
|
|
||
|
//
|
||
|
// Add the ICONIMAGE array to the grow buffer
|
||
|
//
|
||
|
|
||
|
for (w = 0 ; w < GroupIconDir->Count ; w++) {
|
||
|
|
||
|
ResourceData = FindNeResourceExA (
|
||
|
Library16,
|
||
|
(PCSTR) RT_ICON,
|
||
|
(PCSTR) GroupIconDir->Entries[w].ID
|
||
|
);
|
||
|
|
||
|
if (!ResourceData) {
|
||
|
DEBUGMSG ((DBG_WHOOPS, "NE Icon ID %u not found", GroupIconDir->Entries[w].ID));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
ResourceSize = pComputeSizeOfIconImage ((PICONIMAGE) ResourceData);
|
||
|
if (!ResourceSize) {
|
||
|
DEBUGMSG ((DBG_WARNING, "Zero-length icon in %s", ModuleContainingIcon));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ResourceSize > 0x10000) {
|
||
|
// too big for an icon
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Dest = GrowBuffer (Buffer, ResourceSize);
|
||
|
if (!Dest) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
CopyMemory (Dest, ResourceData, ResourceSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
b = TRUE;
|
||
|
}
|
||
|
__finally {
|
||
|
// empty
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGenerateUnicodeArgs (
|
||
|
IN PCSTR ModuleContainingIcon, OPTIONAL
|
||
|
IN PCSTR GroupIconId, OPTIONAL
|
||
|
OUT PCWSTR *UnicodeFileName, OPTIONAL
|
||
|
OUT PCWSTR *UnicodeGroupIconId OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
if (UnicodeFileName) {
|
||
|
if (ModuleContainingIcon) {
|
||
|
*UnicodeFileName = ConvertAtoW (ModuleContainingIcon);
|
||
|
if (!(*UnicodeFileName)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
*UnicodeFileName = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (UnicodeGroupIconId) {
|
||
|
if (GroupIconId) {
|
||
|
|
||
|
if ((DWORD) GroupIconId & 0xffff0000) {
|
||
|
|
||
|
*UnicodeGroupIconId = ConvertAtoW (GroupIconId);
|
||
|
|
||
|
if (!(*UnicodeGroupIconId)) {
|
||
|
if (UnicodeFileName && *UnicodeFileName) {
|
||
|
FreeConvertedStr (*UnicodeFileName);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
*UnicodeGroupIconId = (PCWSTR) GroupIconId;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
*UnicodeGroupIconId = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DestroyAnsiResourceId (
|
||
|
IN PCSTR AnsiId
|
||
|
)
|
||
|
{
|
||
|
if (HIWORD (AnsiId)) {
|
||
|
FreeConvertedStr (AnsiId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DestroyUnicodeResourceId (
|
||
|
IN PCWSTR UnicodeId
|
||
|
)
|
||
|
{
|
||
|
if (HIWORD (UnicodeId)) {
|
||
|
FreeConvertedStr (UnicodeId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromBinaryExA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN PCSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE Library,
|
||
|
IN HANDLE Library16
|
||
|
)
|
||
|
{
|
||
|
PCWSTR UnicodeFileName;
|
||
|
PCWSTR UnicodeGroupIconId;
|
||
|
BOOL b;
|
||
|
|
||
|
if (!pGenerateUnicodeArgs (
|
||
|
ModuleContainingIcon,
|
||
|
GroupIconId,
|
||
|
&UnicodeFileName,
|
||
|
&UnicodeGroupIconId
|
||
|
)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = pGetIconImageArrayFromBinaryExW (UnicodeFileName, UnicodeGroupIconId, Buffer, Library, Library16);
|
||
|
|
||
|
PushError();
|
||
|
|
||
|
FreeConvertedStr (UnicodeFileName);
|
||
|
DestroyUnicodeResourceId (UnicodeGroupIconId);
|
||
|
|
||
|
PopError();
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromBinaryW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN PCWSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
HANDLE Library;
|
||
|
HANDLE Library16 = NULL;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
Library = LoadLibraryExW (ModuleContainingIcon, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
|
||
|
__try {
|
||
|
if (!Library) {
|
||
|
|
||
|
Library16 = OpenNeFileW (ModuleContainingIcon);
|
||
|
if (!Library16) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
b = pGetIconImageArrayFromBinaryExW (ModuleContainingIcon, GroupIconId, Buffer, Library, Library16);
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
if (Library) {
|
||
|
FreeLibrary (Library);
|
||
|
}
|
||
|
|
||
|
if (Library16) {
|
||
|
CloseNeFile (Library16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromBinaryA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN PCSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
HANDLE Library;
|
||
|
HANDLE Library16 = NULL;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
Library = LoadLibraryExA (ModuleContainingIcon, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
|
||
|
__try {
|
||
|
if (!Library) {
|
||
|
|
||
|
Library16 = OpenNeFileA (ModuleContainingIcon);
|
||
|
if (!Library16) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
b = pGetIconImageArrayFromBinaryExA (ModuleContainingIcon, GroupIconId, Buffer, Library, Library16);
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
if (Library) {
|
||
|
FreeLibrary (Library);
|
||
|
}
|
||
|
|
||
|
if (Library16) {
|
||
|
CloseNeFile (Library16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToIcoFileEx (
|
||
|
IN PGROWBUFFER Buffer,
|
||
|
IN HANDLE File
|
||
|
)
|
||
|
{
|
||
|
WORD w;
|
||
|
BOOL b = FALSE;
|
||
|
PICONIMAGE IconImage, IconImageEnd;
|
||
|
PICONIMAGE p;
|
||
|
INT ImageCount;
|
||
|
ICONDIRENTRY Entry;
|
||
|
PBITMAPINFOHEADER Header;
|
||
|
UINT ColorCount;
|
||
|
DWORD Offset;
|
||
|
|
||
|
if (!Buffer->End) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
SetFilePointer (File, 0, NULL, FILE_BEGIN);
|
||
|
|
||
|
//
|
||
|
// Count the images
|
||
|
//
|
||
|
|
||
|
IconImage = (PICONIMAGE) Buffer->Buf;
|
||
|
IconImageEnd = (PICONIMAGE) (Buffer->Buf + Buffer->End);
|
||
|
|
||
|
p = IconImage;
|
||
|
ImageCount = 0;
|
||
|
|
||
|
while (p < IconImageEnd) {
|
||
|
ImageCount++;
|
||
|
p = (PICONIMAGE) ((PBYTE) p + pComputeSizeOfIconImage (p));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write the icon header
|
||
|
//
|
||
|
|
||
|
w = 0; // reserved
|
||
|
if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
w = 1; // type (1 == icon)
|
||
|
if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
w = (WORD) ImageCount;
|
||
|
if (!pWriteBinaryBlock (File, &w, sizeof (WORD))) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// For each icon image, write the directory entry
|
||
|
//
|
||
|
|
||
|
p = IconImage;
|
||
|
Offset = 0;
|
||
|
|
||
|
while (p < IconImageEnd) {
|
||
|
|
||
|
ZeroMemory (&Entry, sizeof (Entry));
|
||
|
|
||
|
Header = (PBITMAPINFOHEADER) p;
|
||
|
Entry.Width = (BYTE) Header->biWidth;
|
||
|
Entry.Height = (BYTE) Header->biHeight / 2;
|
||
|
|
||
|
ColorCount = Header->biPlanes * Header->biBitCount;
|
||
|
if (ColorCount >= 8) {
|
||
|
Entry.ColorCount = 0;
|
||
|
} else {
|
||
|
Entry.ColorCount = (BYTE) Power (2, ColorCount);
|
||
|
}
|
||
|
|
||
|
Entry.Planes = Header->biPlanes;
|
||
|
Entry.BitCount = Header->biBitCount;
|
||
|
Entry.BytesInRes = pComputeSizeOfIconImage (p);
|
||
|
Entry.ImageOffset = sizeof (WORD) * 3 + sizeof (Entry) * ImageCount + Offset;
|
||
|
|
||
|
if (!pWriteBinaryBlock (File, &Entry, sizeof (Entry))) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Offset += Entry.BytesInRes;
|
||
|
|
||
|
p = (PICONIMAGE) ((PBYTE) p + Entry.BytesInRes);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write the image array
|
||
|
//
|
||
|
|
||
|
if (!pWriteBinaryBlock (File, IconImage, Buffer->End)) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
b = TRUE;
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
// empty
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToIcoFileW (
|
||
|
IN PCWSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
HANDLE File;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (!Buffer->End) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
File = CreateFileW (DestinationFile, GENERIC_WRITE, 0, NULL,
|
||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
if (File == INVALID_HANDLE_VALUE) {
|
||
|
DEBUGMSG ((DBG_WARNING, "%ls could not be created", DestinationFile));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
b = WriteIconImageArrayToIcoFileEx (Buffer, File);
|
||
|
}
|
||
|
__finally {
|
||
|
CloseHandle (File);
|
||
|
if (!b) {
|
||
|
DeleteFileW (DestinationFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToIcoFileA (
|
||
|
IN PCSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
HANDLE File;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (!Buffer->End) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
File = CreateFileA (DestinationFile, GENERIC_WRITE, 0, NULL,
|
||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
if (File == INVALID_HANDLE_VALUE) {
|
||
|
DEBUGMSG ((DBG_WARNING, "%hs could not be created", DestinationFile));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
b = WriteIconImageArrayToIcoFileEx (Buffer, File);
|
||
|
}
|
||
|
__finally {
|
||
|
CloseHandle (File);
|
||
|
if (!b) {
|
||
|
DeleteFileA (DestinationFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToPeFileExW (
|
||
|
IN PCWSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer,
|
||
|
IN PCWSTR GroupIconId,
|
||
|
IN PWORD NextIconId, OPTIONAL
|
||
|
IN HANDLE UpdateHandle
|
||
|
)
|
||
|
{
|
||
|
BOOL b = FALSE;
|
||
|
GROWBUFFER GroupIcon = GROWBUF_INIT;
|
||
|
PGRPICONDIRBASE IconDir;
|
||
|
PGRPICONDIRENTRY Entry;
|
||
|
PICONIMAGE IconImage, IconImageEnd;
|
||
|
PICONIMAGE p;
|
||
|
PBITMAPINFOHEADER Header;
|
||
|
UINT ColorCount;
|
||
|
|
||
|
if (!Buffer->End) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
//
|
||
|
// Make a group icon directory for all icon images in Buffer
|
||
|
//
|
||
|
|
||
|
IconDir = (PGRPICONDIRBASE) GrowBuffer (&GroupIcon, sizeof (GRPICONDIRBASE));
|
||
|
if (!IconDir) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
IconDir->Reserved = 0;
|
||
|
IconDir->Type = 1;
|
||
|
IconDir->Count = 0;
|
||
|
|
||
|
IconImage = (PICONIMAGE) Buffer->Buf;
|
||
|
IconImageEnd = (PICONIMAGE) (Buffer->Buf + Buffer->End);
|
||
|
|
||
|
p = IconImage;
|
||
|
while (p < IconImageEnd) {
|
||
|
|
||
|
Entry = (PGRPICONDIRENTRY) GrowBuffer (&GroupIcon, sizeof (GRPICONDIRENTRY));
|
||
|
if (!Entry) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
Header = (PBITMAPINFOHEADER) p;
|
||
|
|
||
|
Entry->Width = (BYTE) Header->biWidth;
|
||
|
Entry->Height = (BYTE) Header->biHeight / 2;
|
||
|
|
||
|
ColorCount = Header->biPlanes * Header->biBitCount;
|
||
|
if (ColorCount >= 8) {
|
||
|
Entry->ColorCount = 0;
|
||
|
} else {
|
||
|
Entry->ColorCount = (BYTE) Power (2, ColorCount);
|
||
|
}
|
||
|
|
||
|
Entry->Planes = Header->biPlanes;
|
||
|
Entry->BitCount = Header->biBitCount;
|
||
|
Entry->BytesInRes = pComputeSizeOfIconImage (p);
|
||
|
|
||
|
if (!NextIconId) {
|
||
|
Entry->ID = 1 + (WORD) ((DWORD) GroupIconId & (0xffff / MAX_RESOLUTIONS)) * MAX_RESOLUTIONS + IconDir->Count;
|
||
|
} else {
|
||
|
Entry->ID = *NextIconId;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add icon to the PE file
|
||
|
//
|
||
|
|
||
|
b = UpdateResourceA (
|
||
|
UpdateHandle,
|
||
|
RT_ICON,
|
||
|
MAKEINTRESOURCE(Entry->ID),
|
||
|
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
|
||
|
p,
|
||
|
Entry->BytesInRes
|
||
|
);
|
||
|
|
||
|
if (!b) {
|
||
|
LOGA ((LOG_ERROR, "Could not add icon to %s", DestinationFile));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
IconDir->Count += 1;
|
||
|
if (NextIconId) {
|
||
|
*NextIconId += 1;
|
||
|
}
|
||
|
|
||
|
p = (PICONIMAGE) ((PBYTE) p + Entry->BytesInRes);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add the group icon to the PE
|
||
|
//
|
||
|
|
||
|
b = UpdateResourceW (
|
||
|
UpdateHandle,
|
||
|
(PCWSTR) RT_GROUP_ICON,
|
||
|
GroupIconId,
|
||
|
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
|
||
|
GroupIcon.Buf,
|
||
|
GroupIcon.End
|
||
|
);
|
||
|
|
||
|
if (!b) {
|
||
|
LOGA ((LOG_ERROR, "Unable to add icon to %s", DestinationFile));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
b = TRUE;
|
||
|
}
|
||
|
__finally {
|
||
|
FreeGrowBuffer (&GroupIcon);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToPeFileExA (
|
||
|
IN PCSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer,
|
||
|
IN PCSTR GroupIconId,
|
||
|
IN PWORD NextIconId, OPTIONAL
|
||
|
IN HANDLE UpdateHandle
|
||
|
)
|
||
|
{
|
||
|
PCWSTR UnicodeDestinationFile;
|
||
|
PCWSTR UnicodeGroupIconId;
|
||
|
BOOL b;
|
||
|
|
||
|
if (!pGenerateUnicodeArgs (
|
||
|
DestinationFile,
|
||
|
GroupIconId,
|
||
|
&UnicodeDestinationFile,
|
||
|
&UnicodeGroupIconId
|
||
|
)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = WriteIconImageArrayToPeFileExW (
|
||
|
UnicodeDestinationFile,
|
||
|
Buffer,
|
||
|
UnicodeGroupIconId,
|
||
|
NextIconId,
|
||
|
UpdateHandle
|
||
|
);
|
||
|
|
||
|
PushError();
|
||
|
|
||
|
FreeConvertedStr (UnicodeDestinationFile);
|
||
|
DestroyUnicodeResourceId (UnicodeGroupIconId);
|
||
|
|
||
|
PopError();
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToPeFileW (
|
||
|
IN PCWSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer,
|
||
|
IN PCWSTR GroupIconId
|
||
|
)
|
||
|
{
|
||
|
HANDLE UpdateHandle = NULL;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (!Buffer->End) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
__try {
|
||
|
//
|
||
|
// Open PE file for update
|
||
|
//
|
||
|
|
||
|
UpdateHandle = BeginUpdateResourceW (DestinationFile, FALSE);
|
||
|
|
||
|
if (!UpdateHandle) {
|
||
|
LOGW ((LOG_ERROR, "Unable to begin resource update of %s", DestinationFile));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the PE file
|
||
|
//
|
||
|
|
||
|
b = WriteIconImageArrayToPeFileExW (DestinationFile, Buffer, (PCWSTR) GroupIconId, NULL, UpdateHandle);
|
||
|
}
|
||
|
__finally {
|
||
|
EndUpdateResource (UpdateHandle, !b);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WriteIconImageArrayToPeFileA (
|
||
|
IN PCSTR DestinationFile,
|
||
|
IN PGROWBUFFER Buffer,
|
||
|
IN PCSTR GroupIconId
|
||
|
)
|
||
|
{
|
||
|
PCWSTR UnicodeDestinationFile;
|
||
|
PCWSTR UnicodeGroupIconId;
|
||
|
BOOL b;
|
||
|
|
||
|
if (!pGenerateUnicodeArgs (
|
||
|
DestinationFile,
|
||
|
GroupIconId,
|
||
|
&UnicodeDestinationFile,
|
||
|
&UnicodeGroupIconId
|
||
|
)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = WriteIconImageArrayToPeFileW (
|
||
|
UnicodeDestinationFile,
|
||
|
Buffer,
|
||
|
UnicodeGroupIconId
|
||
|
);
|
||
|
|
||
|
PushError();
|
||
|
|
||
|
FreeConvertedStr (UnicodeDestinationFile);
|
||
|
DestroyUnicodeResourceId (UnicodeGroupIconId);
|
||
|
|
||
|
PopError();
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsFileAnIcoW (
|
||
|
IN PCWSTR FileInQuestion
|
||
|
)
|
||
|
{
|
||
|
PCWSTR p;
|
||
|
DWORD magic;
|
||
|
DWORD bytesRead;
|
||
|
HANDLE icoFileHandle = INVALID_HANDLE_VALUE;
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
p = wcsrchr (FileInQuestion, L'.');
|
||
|
|
||
|
if (p) {
|
||
|
if (StringIMatchW (p, L".ico")) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
icoFileHandle = CreateFileW (
|
||
|
FileInQuestion,
|
||
|
GENERIC_READ,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
if (icoFileHandle != INVALID_HANDLE_VALUE) {
|
||
|
|
||
|
if (ReadFile (icoFileHandle, (PBYTE)(&magic), sizeof (magic), &bytesRead, NULL)) {
|
||
|
if (bytesRead == sizeof (magic)) {
|
||
|
if (magic != IMAGE_DOS_SIGNATURE) {
|
||
|
result = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle (icoFileHandle);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsFileAnIcoA (
|
||
|
IN PCSTR FileInQuestion
|
||
|
)
|
||
|
{
|
||
|
PCSTR p;
|
||
|
WORD magic;
|
||
|
DWORD bytesRead;
|
||
|
HANDLE icoFileHandle = INVALID_HANDLE_VALUE;
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
p = _mbsrchr (FileInQuestion, '.');
|
||
|
|
||
|
if (p) {
|
||
|
if (StringIMatchA (p, ".ico")) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
icoFileHandle = CreateFileA (
|
||
|
FileInQuestion,
|
||
|
GENERIC_READ,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
if (icoFileHandle != INVALID_HANDLE_VALUE) {
|
||
|
|
||
|
if (ReadFile (icoFileHandle, (PBYTE)(&magic), sizeof (magic), &bytesRead, NULL)) {
|
||
|
if (bytesRead == sizeof (magic)) {
|
||
|
if (magic != IMAGE_DOS_SIGNATURE) {
|
||
|
result = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle (icoFileHandle);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ExtractIconImageFromFileExW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN PCWSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE IcoFileHandle, OPTIONAL
|
||
|
IN HANDLE PeModuleHandle, OPTIONAL
|
||
|
IN HANDLE NeModuleHandle OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
if (IsFileAnIcoW (ModuleContainingIcon)) {
|
||
|
if (IcoFileHandle) {
|
||
|
return pGetIconImageArrayFromIcoFileExW (ModuleContainingIcon, Buffer, IcoFileHandle);
|
||
|
} else {
|
||
|
return pGetIconImageArrayFromIcoFileW (ModuleContainingIcon, Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (PeModuleHandle) {
|
||
|
return pGetIconImageArrayFromBinaryExW (
|
||
|
ModuleContainingIcon,
|
||
|
GroupIconId,
|
||
|
Buffer,
|
||
|
PeModuleHandle,
|
||
|
NeModuleHandle
|
||
|
);
|
||
|
} else {
|
||
|
return pGetIconImageArrayFromBinaryW (ModuleContainingIcon, GroupIconId, Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ExtractIconImageFromFileExA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN PCSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer,
|
||
|
IN HANDLE IcoFileHandle, OPTIONAL
|
||
|
IN HANDLE PeModuleHandle, OPTIONAL
|
||
|
IN HANDLE NeModuleHandle OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
if (IsFileAnIcoA (ModuleContainingIcon)) {
|
||
|
if (IcoFileHandle) {
|
||
|
return pGetIconImageArrayFromIcoFileExA (ModuleContainingIcon, Buffer, IcoFileHandle);
|
||
|
} else {
|
||
|
return pGetIconImageArrayFromIcoFileA (ModuleContainingIcon, Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (PeModuleHandle) {
|
||
|
return pGetIconImageArrayFromBinaryExA (
|
||
|
ModuleContainingIcon,
|
||
|
GroupIconId,
|
||
|
Buffer,
|
||
|
PeModuleHandle,
|
||
|
NeModuleHandle
|
||
|
);
|
||
|
} else {
|
||
|
return pGetIconImageArrayFromBinaryA (ModuleContainingIcon, GroupIconId, Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ExtractIconImageFromFileW (
|
||
|
IN PCWSTR ModuleContainingIcon,
|
||
|
IN PCWSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
return ExtractIconImageFromFileExW (
|
||
|
ModuleContainingIcon,
|
||
|
GroupIconId,
|
||
|
Buffer,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ExtractIconImageFromFileA (
|
||
|
IN PCSTR ModuleContainingIcon,
|
||
|
IN PCSTR GroupIconId,
|
||
|
IN OUT PGROWBUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
return ExtractIconImageFromFileExA (
|
||
|
ModuleContainingIcon,
|
||
|
GroupIconId,
|
||
|
Buffer,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CALLBACK
|
||
|
pEnumIconNameProcA (
|
||
|
HANDLE Module,
|
||
|
PCSTR Type,
|
||
|
PSTR Name,
|
||
|
LONG lParam
|
||
|
)
|
||
|
{
|
||
|
PGROWBUFFER Buf;
|
||
|
PCSTR Num;
|
||
|
CHAR NumBuf[32];
|
||
|
|
||
|
Buf = (PGROWBUFFER) lParam;
|
||
|
|
||
|
if ((DWORD) Name & 0xffff0000) {
|
||
|
Num = Name;
|
||
|
} else {
|
||
|
Num = NumBuf;
|
||
|
wsprintfA (NumBuf, "#%u", Name);
|
||
|
}
|
||
|
|
||
|
MultiSzAppendA (Buf, Num);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CALLBACK
|
||
|
pEnumIconNameProcW (
|
||
|
HANDLE Module,
|
||
|
PCWSTR Type,
|
||
|
PWSTR Name,
|
||
|
LONG lParam
|
||
|
)
|
||
|
{
|
||
|
PGROWBUFFER Buf;
|
||
|
PCWSTR Num;
|
||
|
WCHAR NumBuf[32];
|
||
|
|
||
|
Buf = (PGROWBUFFER) lParam;
|
||
|
|
||
|
if ((DWORD) Name & 0xffff0000) {
|
||
|
Num = Name;
|
||
|
} else {
|
||
|
Num = NumBuf;
|
||
|
wsprintfW (NumBuf, L"#%u", Name);
|
||
|
}
|
||
|
|
||
|
MultiSzAppendW (Buf, Num);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCSTR
|
||
|
ExtractIconNamesFromFileExA (
|
||
|
IN PCSTR ModuleContainingIcons,
|
||
|
IN OUT PGROWBUFFER NameBuf,
|
||
|
IN HANDLE Module,
|
||
|
IN HANDLE Module16
|
||
|
)
|
||
|
{
|
||
|
PCSTR ReturnBuf;
|
||
|
|
||
|
NameBuf->End = 0;
|
||
|
|
||
|
if (Module) {
|
||
|
if (!EnumResourceNamesA (Module, RT_GROUP_ICON, pEnumIconNameProcA, (LONG) NameBuf)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
} else if (Module16) {
|
||
|
if (!EnumNeResourceNamesA (Module16, RT_GROUP_ICON, pEnumIconNameProcA, (LONG) NameBuf)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
} else {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
MultiSzAppendA (NameBuf, "");
|
||
|
ReturnBuf = (PCSTR) NameBuf->Buf;
|
||
|
|
||
|
return ReturnBuf;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCWSTR
|
||
|
ExtractIconNamesFromFileExW (
|
||
|
IN PCWSTR ModuleContainingIcons,
|
||
|
IN OUT PGROWBUFFER NameBuf,
|
||
|
IN HANDLE Module,
|
||
|
IN HANDLE Module16
|
||
|
)
|
||
|
{
|
||
|
PCWSTR ReturnBuf;
|
||
|
|
||
|
NameBuf->End = 0;
|
||
|
|
||
|
if (Module) {
|
||
|
if (!EnumResourceNamesW (Module, (PCWSTR) RT_GROUP_ICON, pEnumIconNameProcW, (LONG) NameBuf)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
} else if (Module16) {
|
||
|
if (!EnumNeResourceNamesW (Module16, (PWSTR) RT_GROUP_ICON, pEnumIconNameProcW, (LONG) NameBuf)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
} else {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
MultiSzAppendW (NameBuf, L"");
|
||
|
ReturnBuf = (PCWSTR) NameBuf->Buf;
|
||
|
|
||
|
return ReturnBuf;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCSTR
|
||
|
ExtractIconNamesFromFileA (
|
||
|
IN PCSTR ModuleContainingIcons,
|
||
|
IN OUT PGROWBUFFER NameBuf
|
||
|
)
|
||
|
{
|
||
|
HANDLE Module = NULL;
|
||
|
HANDLE Module16 = NULL;
|
||
|
PCSTR ReturnBuf = NULL;
|
||
|
|
||
|
__try {
|
||
|
Module = LoadLibraryExA (ModuleContainingIcons, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
|
||
|
if (!Module) {
|
||
|
|
||
|
Module16 = OpenNeFileA (ModuleContainingIcons);
|
||
|
if (!Module16) {
|
||
|
DEBUGMSGA ((DBG_WARNING, "Can't load %s, error %u", ModuleContainingIcons, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnBuf = ExtractIconNamesFromFileExA (ModuleContainingIcons, NameBuf, Module, Module16);
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
if (Module) {
|
||
|
FreeLibrary (Module);
|
||
|
}
|
||
|
|
||
|
if (Module16) {
|
||
|
CloseNeFile (Module16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ReturnBuf;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCWSTR
|
||
|
ExtractIconNamesFromFileW (
|
||
|
IN PCWSTR ModuleContainingIcons,
|
||
|
IN OUT PGROWBUFFER NameBuf
|
||
|
)
|
||
|
{
|
||
|
HANDLE Module = NULL;
|
||
|
HANDLE Module16 = NULL;
|
||
|
PCWSTR ReturnBuf = NULL;
|
||
|
|
||
|
__try {
|
||
|
Module = LoadLibraryExW (ModuleContainingIcons, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
|
||
|
if (!Module) {
|
||
|
|
||
|
Module16 = OpenNeFileW (ModuleContainingIcons);
|
||
|
if (!Module16) {
|
||
|
DEBUGMSGW ((DBG_WARNING, "Can't load %s, error %u", ModuleContainingIcons, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnBuf = ExtractIconNamesFromFileExW (ModuleContainingIcons, NameBuf, Module, Module16);
|
||
|
|
||
|
}
|
||
|
__finally {
|
||
|
if (Module) {
|
||
|
FreeLibrary (Module);
|
||
|
}
|
||
|
|
||
|
if (Module16) {
|
||
|
CloseNeFile (Module16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ReturnBuf;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pInitContextA (
|
||
|
PICON_EXTRACT_CONTEXTA Context
|
||
|
)
|
||
|
{
|
||
|
ZeroMemory (Context, sizeof (ICON_EXTRACT_CONTEXTA));
|
||
|
Context->GroupId = 1;
|
||
|
Context->IconId = 1;
|
||
|
Context->IconImageFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pInitContextW (
|
||
|
PICON_EXTRACT_CONTEXTW Context
|
||
|
)
|
||
|
{
|
||
|
ZeroMemory (Context, sizeof (ICON_EXTRACT_CONTEXTW));
|
||
|
Context->GroupId = 1;
|
||
|
Context->IconId = 1;
|
||
|
Context->IconImageFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
BeginIconExtractionA (
|
||
|
OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR DestFile OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
pInitContextA (Context);
|
||
|
|
||
|
if (DestFile) {
|
||
|
Context->Update = BeginUpdateResourceA (DestFile, FALSE);
|
||
|
|
||
|
if (!Context->Update) {
|
||
|
LOGA ((LOG_ERROR, "Unable to begin resource update of %s", DestFile));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
StringCopyA (Context->DestFile, DestFile);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
BeginIconExtractionW (
|
||
|
OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR DestFile OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
pInitContextW (Context);
|
||
|
|
||
|
if (DestFile) {
|
||
|
Context->Update = BeginUpdateResourceW (DestFile, FALSE);
|
||
|
|
||
|
if (!Context->Update) {
|
||
|
LOGW ((LOG_ERROR, "Unable to begin resource update of %s", DestFile));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
StringCopyW (Context->DestFile, DestFile);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pLoadBinaryImageA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR IconFile
|
||
|
)
|
||
|
{
|
||
|
if (Context->Module || Context->Module16) {
|
||
|
if (StringIMatchA (Context->ModuleName, IconFile)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->Module) {
|
||
|
FreeLibrary (Context->Module);
|
||
|
Context->Module = NULL;
|
||
|
}
|
||
|
|
||
|
if (Context->Module16) {
|
||
|
CloseNeFile (Context->Module16);
|
||
|
Context->Module16 = NULL;
|
||
|
}
|
||
|
|
||
|
Context->Module = LoadLibraryExA (IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
if (Context->Module) {
|
||
|
StringCopyA (Context->ModuleName, IconFile);
|
||
|
} else {
|
||
|
Context->Module16 = OpenNeFileA (IconFile);
|
||
|
if (Context->Module16) {
|
||
|
StringCopyA (Context->ModuleName, IconFile);
|
||
|
} else {
|
||
|
Context->ModuleName[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Context->Module != NULL || Context->Module16 != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pLoadBinaryImageW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR IconFile
|
||
|
)
|
||
|
{
|
||
|
if (Context->Module || Context->Module16) {
|
||
|
if (StringIMatchW (Context->ModuleName, IconFile)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->Module) {
|
||
|
FreeLibrary (Context->Module);
|
||
|
}
|
||
|
|
||
|
if (Context->Module16) {
|
||
|
CloseNeFile (Context->Module16);
|
||
|
Context->Module16 = NULL;
|
||
|
}
|
||
|
|
||
|
Context->Module = LoadLibraryExW (IconFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||
|
if (Context->Module) {
|
||
|
StringCopyW (Context->ModuleName, IconFile);
|
||
|
} else {
|
||
|
Context->Module16 = OpenNeFileW (IconFile);
|
||
|
if (Context->Module16) {
|
||
|
StringCopyW (Context->ModuleName, IconFile);
|
||
|
} else {
|
||
|
Context->ModuleName[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Context->Module != NULL || Context->Module16 != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pOpenIcoFileA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR IconFile
|
||
|
)
|
||
|
{
|
||
|
if (Context->IcoFile) {
|
||
|
if (StringIMatchA (Context->IcoFileName, IconFile)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->IcoFile) {
|
||
|
CloseHandle (Context->IcoFile);
|
||
|
}
|
||
|
|
||
|
Context->IcoFile = CreateFileA (IconFile, GENERIC_READ, 0, NULL,
|
||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
if (Context->IcoFile == INVALID_HANDLE_VALUE) {
|
||
|
Context->IcoFile = NULL;
|
||
|
Context->IcoFileName[0] = 0;
|
||
|
} else {
|
||
|
StringCopyA (Context->IcoFileName, IconFile);
|
||
|
}
|
||
|
|
||
|
return Context->IcoFile != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pOpenIcoFileW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR IconFile
|
||
|
)
|
||
|
{
|
||
|
if (Context->IcoFile) {
|
||
|
if (StringIMatchW (Context->IcoFileName, IconFile)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->IcoFile) {
|
||
|
CloseHandle (Context->IcoFile);
|
||
|
}
|
||
|
|
||
|
Context->IcoFile = CreateFileW (IconFile, GENERIC_READ, 0, NULL,
|
||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
if (Context->IcoFile == INVALID_HANDLE_VALUE) {
|
||
|
Context->IcoFile = NULL;
|
||
|
Context->IcoFileName[0] = 0;
|
||
|
} else {
|
||
|
StringCopyW (Context->IcoFileName, IconFile);
|
||
|
}
|
||
|
|
||
|
return Context->IcoFile != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pOpenIconImageA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR FileToOpen,
|
||
|
OUT PBOOL IsIco, OPTIONAL
|
||
|
OUT PBOOL Is16Bit OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
if (Is16Bit) {
|
||
|
*Is16Bit = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsFileAnIcoA (FileToOpen)) {
|
||
|
if (IsIco) {
|
||
|
*IsIco = TRUE;
|
||
|
}
|
||
|
|
||
|
return pOpenIcoFileA (Context, FileToOpen);
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
*IsIco = FALSE;
|
||
|
}
|
||
|
|
||
|
if (pLoadBinaryImageA (Context, FileToOpen)) {
|
||
|
if (Context->Module16 && Is16Bit) {
|
||
|
*Is16Bit = TRUE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pOpenIconImageW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR FileToOpen,
|
||
|
OUT PBOOL IsIco, OPTIONAL
|
||
|
OUT PBOOL Is16Bit OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
if (Is16Bit) {
|
||
|
*Is16Bit = FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsFileAnIcoW (FileToOpen)) {
|
||
|
if (IsIco) {
|
||
|
*IsIco = TRUE;
|
||
|
}
|
||
|
|
||
|
return pOpenIcoFileW (Context, FileToOpen);
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
*IsIco = FALSE;
|
||
|
}
|
||
|
|
||
|
if (pLoadBinaryImageW (Context, FileToOpen)) {
|
||
|
if (Context->Module16 && Is16Bit) {
|
||
|
*Is16Bit = TRUE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
OpenIconImageFileA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR FileName,
|
||
|
IN BOOL SaveMode
|
||
|
)
|
||
|
{
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle (Context->IconImageFile);
|
||
|
Context->IconImageFileName[0] = 0;
|
||
|
}
|
||
|
|
||
|
if (SaveMode) {
|
||
|
Context->IconImageFile = CreateFileA (
|
||
|
FileName,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
} else {
|
||
|
Context->IconImageFile = CreateFileA (
|
||
|
FileName,
|
||
|
GENERIC_READ,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
StringCopyA (Context->IconImageFileName, FileName);
|
||
|
Context->SaveMode = SaveMode;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
OpenIconImageFileW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR FileName,
|
||
|
IN BOOL SaveMode
|
||
|
)
|
||
|
{
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle (Context->IconImageFile);
|
||
|
Context->IconImageFileName[0] = 0;
|
||
|
}
|
||
|
|
||
|
if (SaveMode) {
|
||
|
Context->IconImageFile = CreateFileW (
|
||
|
FileName,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
} else {
|
||
|
Context->IconImageFile = CreateFileW (
|
||
|
FileName,
|
||
|
GENERIC_READ,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
StringCopyW (Context->IconImageFileName, FileName);
|
||
|
Context->SaveMode = SaveMode;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromFileA (
|
||
|
IN PICON_EXTRACT_CONTEXTA Context
|
||
|
)
|
||
|
{
|
||
|
DWORD Size;
|
||
|
PBYTE Dest;
|
||
|
HANDLE File;
|
||
|
|
||
|
File = Context->IconImageFile;
|
||
|
|
||
|
if (!ReadBinaryBlock (File, &Size, sizeof (DWORD))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Context->IconImages.End = 0;
|
||
|
|
||
|
Dest = GrowBuffer (&Context->IconImages, Size);
|
||
|
if (!Dest) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return ReadBinaryBlock (File, Dest, Size);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIconImageArrayFromFileW (
|
||
|
IN PICON_EXTRACT_CONTEXTW Context
|
||
|
)
|
||
|
{
|
||
|
DWORD Size;
|
||
|
PBYTE Dest;
|
||
|
HANDLE File;
|
||
|
|
||
|
File = Context->IconImageFile;
|
||
|
|
||
|
if (!ReadBinaryBlock (File, &Size, sizeof (DWORD))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Context->IconImages.End = 0;
|
||
|
|
||
|
Dest = GrowBuffer (&Context->IconImages, Size);
|
||
|
if (!Dest) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return ReadBinaryBlock (File, Dest, Size);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pPutIconImageArrayInFileA (
|
||
|
IN PICON_EXTRACT_CONTEXTA Context
|
||
|
)
|
||
|
{
|
||
|
HANDLE File;
|
||
|
|
||
|
File = Context->IconImageFile;
|
||
|
|
||
|
if (!Context->IconImages.End) {
|
||
|
|
||
|
DEBUGMSGA_IF ((
|
||
|
Context->ModuleName[0],
|
||
|
DBG_WARNING,
|
||
|
"Ignoring empty icon in %s",
|
||
|
Context->ModuleName
|
||
|
));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (!pWriteBinaryBlock (File, &Context->IconImages.End, sizeof (DWORD))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return pWriteBinaryBlock (File, Context->IconImages.Buf, Context->IconImages.End);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pPutIconImageArrayInFileW (
|
||
|
IN PICON_EXTRACT_CONTEXTW Context
|
||
|
)
|
||
|
{
|
||
|
HANDLE File;
|
||
|
|
||
|
File = Context->IconImageFile;
|
||
|
|
||
|
if (!Context->IconImages.End) {
|
||
|
|
||
|
DEBUGMSGW_IF ((
|
||
|
Context->ModuleName[0],
|
||
|
DBG_WARNING,
|
||
|
"Ignoring empty icon in %s",
|
||
|
Context->ModuleName
|
||
|
));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!pWriteBinaryBlock (File, &Context->IconImages.End, sizeof (DWORD))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return pWriteBinaryBlock (File, Context->IconImages.Buf, Context->IconImages.End);
|
||
|
}
|
||
|
|
||
|
|
||
|
PCSTR
|
||
|
pFindResourceIdFromIndexA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR FileContainingIcon,
|
||
|
IN INT ResourceIndex,
|
||
|
OUT PSTR Buffer
|
||
|
)
|
||
|
{
|
||
|
PCSTR ImageList;
|
||
|
|
||
|
if (!pLoadBinaryImageA (Context, FileContainingIcon)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (ResourceIndex < 0) {
|
||
|
wsprintfA (Buffer, "#%i", -ResourceIndex);
|
||
|
return Buffer;
|
||
|
} else {
|
||
|
*Buffer = 0;
|
||
|
}
|
||
|
|
||
|
ImageList = ExtractIconNamesFromFileExA (
|
||
|
FileContainingIcon,
|
||
|
&Context->IconList,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
|
||
|
while (ImageList) {
|
||
|
if (!ResourceIndex) {
|
||
|
StringCopyA (Buffer, ImageList);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ResourceIndex--;
|
||
|
}
|
||
|
|
||
|
return *Buffer ? Buffer : NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCWSTR
|
||
|
pFindResourceIdFromIndexW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR FileContainingIcon,
|
||
|
IN INT ResourceIndex,
|
||
|
OUT PWSTR Buffer
|
||
|
)
|
||
|
{
|
||
|
PCWSTR ImageList;
|
||
|
|
||
|
if (!pLoadBinaryImageW (Context, FileContainingIcon)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (ResourceIndex < 0) {
|
||
|
wsprintfW (Buffer, L"#%i", -ResourceIndex);
|
||
|
return Buffer;
|
||
|
} else {
|
||
|
*Buffer = 0;
|
||
|
}
|
||
|
|
||
|
ImageList = ExtractIconNamesFromFileExW (
|
||
|
FileContainingIcon,
|
||
|
&Context->IconList,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
|
||
|
while (ImageList) {
|
||
|
if (!ResourceIndex) {
|
||
|
StringCopyW (Buffer, ImageList);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ResourceIndex--;
|
||
|
}
|
||
|
|
||
|
return *Buffer ? Buffer : NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CopyIconA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR FileContainingIcon, OPTIONAL
|
||
|
IN PCSTR ResourceId, OPTIONAL
|
||
|
IN INT ResourceIndex OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
BOOL IsIco;
|
||
|
BOOL b;
|
||
|
CHAR Buffer[256];
|
||
|
|
||
|
if (Context->Error) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!ResourceId && FileContainingIcon) {
|
||
|
if (!IsFileAnIco (FileContainingIcon)) {
|
||
|
ResourceId = pFindResourceIdFromIndexA (
|
||
|
Context,
|
||
|
FileContainingIcon,
|
||
|
ResourceIndex,
|
||
|
Buffer
|
||
|
);
|
||
|
|
||
|
if (!ResourceId) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
|
||
|
!Context->SaveMode
|
||
|
) {
|
||
|
//
|
||
|
// Get icon image from the icon image array file
|
||
|
//
|
||
|
|
||
|
b = pGetIconImageArrayFromFileA (Context);
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// Get icon image from source file
|
||
|
//
|
||
|
|
||
|
if (!pOpenIconImageA (Context, FileContainingIcon, &IsIco, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
b = pGetIconImageArrayFromIcoFileExA (
|
||
|
Context->IcoFileName,
|
||
|
&Context->IconImages,
|
||
|
Context->IcoFile
|
||
|
);
|
||
|
} else {
|
||
|
|
||
|
b = pGetIconImageArrayFromBinaryExA (
|
||
|
Context->ModuleName,
|
||
|
ResourceId,
|
||
|
&Context->IconImages,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (b) {
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
|
||
|
Context->SaveMode
|
||
|
) {
|
||
|
|
||
|
//
|
||
|
// Save icon to icon image array file
|
||
|
//
|
||
|
|
||
|
b = pPutIconImageArrayInFileA (Context);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Save icon to PE file
|
||
|
//
|
||
|
|
||
|
b = WriteIconImageArrayToPeFileExA (
|
||
|
Context->DestFile,
|
||
|
&Context->IconImages,
|
||
|
(PCSTR) Context->GroupId,
|
||
|
&Context->IconId,
|
||
|
Context->Update
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!b) {
|
||
|
Context->Error = TRUE;
|
||
|
} else {
|
||
|
Context->GroupId++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CopyIconW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR FileContainingIcon, // OPTIONAL if using an icon image file
|
||
|
IN PCWSTR ResourceId, // OPTIONAL if FileContainingIcon is an ico
|
||
|
IN INT ResourceIndex OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
BOOL IsIco;
|
||
|
BOOL b;
|
||
|
WCHAR Buffer[256];
|
||
|
|
||
|
if (Context->Error) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!ResourceId && FileContainingIcon) {
|
||
|
if (!IsFileAnIcoW (FileContainingIcon)) {
|
||
|
|
||
|
ResourceId = pFindResourceIdFromIndexW (
|
||
|
Context,
|
||
|
FileContainingIcon,
|
||
|
ResourceIndex,
|
||
|
Buffer
|
||
|
);
|
||
|
|
||
|
if (!ResourceId) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
|
||
|
!Context->SaveMode
|
||
|
) {
|
||
|
//
|
||
|
// Get icon image from the icon image array file
|
||
|
//
|
||
|
|
||
|
b = pGetIconImageArrayFromFileW (Context);
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// Get icon image from source file
|
||
|
//
|
||
|
|
||
|
if (!pOpenIconImageW (Context, FileContainingIcon, &IsIco, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
b = pGetIconImageArrayFromIcoFileExW (
|
||
|
Context->IcoFileName,
|
||
|
&Context->IconImages,
|
||
|
Context->IcoFile
|
||
|
);
|
||
|
} else {
|
||
|
|
||
|
b = pGetIconImageArrayFromBinaryExW (
|
||
|
Context->ModuleName,
|
||
|
ResourceId,
|
||
|
&Context->IconImages,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (b) {
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE &&
|
||
|
Context->SaveMode
|
||
|
) {
|
||
|
|
||
|
//
|
||
|
// Save icon to icon image array file
|
||
|
//
|
||
|
|
||
|
b = pPutIconImageArrayInFileW (Context);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Save icon to PE file
|
||
|
//
|
||
|
|
||
|
b = WriteIconImageArrayToPeFileExW (
|
||
|
Context->DestFile,
|
||
|
&Context->IconImages,
|
||
|
(PCWSTR) Context->GroupId,
|
||
|
&Context->IconId,
|
||
|
Context->Update
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!b) {
|
||
|
Context->Error = TRUE;
|
||
|
} else {
|
||
|
Context->GroupId++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CopyAllIconsA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context,
|
||
|
IN PCSTR FileContainingIcons
|
||
|
)
|
||
|
{
|
||
|
MULTISZ_ENUMA e;
|
||
|
BOOL IsIco;
|
||
|
PCSTR IconList;
|
||
|
BOOL b = TRUE;
|
||
|
|
||
|
if (Context->Error) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pOpenIconImageA (Context, FileContainingIcons, &IsIco, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
return CopyIconA (Context, FileContainingIcons, NULL, 0);
|
||
|
}
|
||
|
|
||
|
IconList = ExtractIconNamesFromFileExA (
|
||
|
FileContainingIcons,
|
||
|
&Context->IconList,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
|
||
|
if (!IconList) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (EnumFirstMultiSzA (&e, IconList)) {
|
||
|
do {
|
||
|
b = CopyIconA (Context, FileContainingIcons, e.CurrentString, 0);
|
||
|
if (!b) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (EnumNextMultiSzA (&e));
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CopyAllIconsW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context,
|
||
|
IN PCWSTR FileContainingIcons
|
||
|
)
|
||
|
{
|
||
|
MULTISZ_ENUMW e;
|
||
|
BOOL IsIco;
|
||
|
PCWSTR IconList;
|
||
|
BOOL b = TRUE;
|
||
|
|
||
|
if (Context->Error) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pOpenIconImageW (Context, FileContainingIcons, &IsIco, NULL)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IsIco) {
|
||
|
return CopyIconW (Context, FileContainingIcons, NULL, 0);
|
||
|
}
|
||
|
|
||
|
IconList = ExtractIconNamesFromFileExW (
|
||
|
FileContainingIcons,
|
||
|
&Context->IconList,
|
||
|
Context->Module,
|
||
|
Context->Module16
|
||
|
);
|
||
|
|
||
|
if (!IconList) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (EnumFirstMultiSzW (&e, IconList)) {
|
||
|
do {
|
||
|
b = CopyIconW (Context, FileContainingIcons, e.CurrentString, 0);
|
||
|
if (!b) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (EnumNextMultiSzW (&e));
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
EndIconExtractionA (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTA Context
|
||
|
)
|
||
|
{
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (Context->Update) {
|
||
|
b = EndUpdateResource (Context->Update, Context->Error);
|
||
|
}
|
||
|
|
||
|
if (Context->Module) {
|
||
|
FreeLibrary (Context->Module);
|
||
|
}
|
||
|
|
||
|
if (Context->Module16) {
|
||
|
CloseNeFile (Context->Module16);
|
||
|
}
|
||
|
|
||
|
if (Context->IcoFile) {
|
||
|
FreeLibrary (Context->IcoFile);
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle (Context->IconImageFile);
|
||
|
}
|
||
|
|
||
|
FreeGrowBuffer (&Context->IconImages);
|
||
|
FreeGrowBuffer (&Context->IconList);
|
||
|
|
||
|
pInitContextA (Context);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
EndIconExtractionW (
|
||
|
IN OUT PICON_EXTRACT_CONTEXTW Context
|
||
|
)
|
||
|
{
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (Context->Update) {
|
||
|
b = EndUpdateResource (Context->Update, Context->Error);
|
||
|
}
|
||
|
|
||
|
if (Context->Module) {
|
||
|
FreeLibrary (Context->Module);
|
||
|
}
|
||
|
|
||
|
if (Context->Module16) {
|
||
|
CloseNeFile (Context->Module16);
|
||
|
}
|
||
|
|
||
|
if (Context->IcoFile) {
|
||
|
FreeLibrary (Context->IcoFile);
|
||
|
}
|
||
|
|
||
|
if (Context->IconImageFile != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle (Context->IconImageFile);
|
||
|
}
|
||
|
|
||
|
FreeGrowBuffer (&Context->IconImages);
|
||
|
FreeGrowBuffer (&Context->IconList);
|
||
|
|
||
|
pInitContextW (Context);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|