|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
icontool.c
Abstract:
Extracts icons in a variety of ways to test the icon extraction code.
Author:
Jim Schmidt (jimschm) 22-Apr-1998
Revision History:
<alias> <date> <comments>
--*/
#include "pch.h"
INT g_ErrorLevel;
VOID pLaunchCompareDlg ( IN PCTSTR FileName1, IN PCTSTR FileName2 );
UINT pRemoveIcons ( IN PICON_EXTRACT_CONTEXT Context, IN UINT Start, IN UINT End );
UINT pCopyIconRange ( IN PICON_EXTRACT_CONTEXT Context, IN PCTSTR IconFile, IN UINT Start, IN UINT End );
//
// This routine is in migutil\icons.c
//
BOOL pOpenIconImageA ( IN OUT PICON_EXTRACT_CONTEXTA Context, IN PCSTR FileToOpen, OUT PBOOL IsIco, OPTIONAL OUT PBOOL Is16Bit OPTIONAL );
BOOL pOpenIconImageW ( IN OUT PICON_EXTRACT_CONTEXTW Context, IN PCWSTR FileToOpen, OUT PBOOL IsIco, OPTIONAL OUT PBOOL Is16Bit OPTIONAL );
#ifdef UNICODE
#define pOpenIconImage pOpenIconImageW
#else
#define pOpenIconImage pOpenIconImageA
#endif
typedef enum { NONE, CREATE_ICO, EXTRACT, EXTRACT_ALL, IMPLANT, EXTRACT_ONE, LIST, COMPARE, MAKE_UNIQUE, KILL } MODE;
VOID HelpAndExit ( VOID ) { printf ("Command line syntax:\n\n" "icontool -a [-r] <pe-file>\n" "icontool -c <pe-file-1> <pe-file-2>\n" "icontool -d [i:<index>] <in-file> <migicons.dat>\n" "icontool -e[:range] <in-file> <migicons.dat>\n" "icontool [-i:<index>] <in-file> <ico-file>\n" "icontool -k <pe-file> <index range>\n" "icontool -l[i] [-q] [-n] [-p:<path>] <in-file> [<in-file>] [...]\n" "icontool -u <pe-file>\n" "icontool -x <migicons.dat> <pe-file>\n" "\n" "<in-file> Specifies the file to extract an icon from (.ICO, NE or PE)\n" "<ico-file> Specifies the file to save the icon to (.ICO only)\n" "<pe-file> Specifies the file to save the icon(s) to (PE only)\n" "<migicons.dat> Specifies the path to migicons.dat (note: same as what\n" " is generated by WINNT32)\n" "-a Scans all files for icons\n" "-c Compare pe-file-1 to pe-file-2 visually\n" "-d Extracts icon from a file into dat file\n" "-e Extracts all icons from <in-file>, or a range of icons. The\n" " range must be simple (as in these three examples: 152 or 1-4\n" " or 10-)\n" "-i Specifies the index or string ID of the icon to extract, default\n" " is 0\n" "-k Kill icon where <index range> is in the form of 1,4-5,10\n" "-l Lists icon resource names\n" "-li Produces output for [Compatible Icon Indexes]\n" "-n No header (used with -li only)\n" "-p Specifies a path to compare the same-named <in-file>, used to\n" " produce [Compatible Icon Index] that have binaries with icons\n" " in common.\n" "-q Quiet (no error output)\n" "-r Enables recursion\n" "-u Makes all icons unique, removes duplicates\n" "-x Extracts icons from a dat file into a pe file\n" );
exit(0); }
BOOL pRemoveDuplicateIcons ( IN PCTSTR SourcePeFile, IN PCTSTR DestPeFile );
BOOL pGetMinAndMax ( IN PICON_EXTRACT_CONTEXT Context, OUT PUINT Min, OUT PUINT Max );
HANDLE g_hHeap; HINSTANCE g_hInst;
BOOL pIsErrorOk ( DWORD Error ) { if (Error != ERROR_SUCCESS && Error != ERROR_FILE_INVALID && Error != ERROR_ACCESS_DENIED && Error != ERROR_BAD_FORMAT && Error != ERROR_RESOURCE_TYPE_NOT_FOUND && Error != ERROR_SHARING_VIOLATION && Error != ERROR_NO_MORE_FILES && Error != ERROR_RESOURCE_DATA_NOT_FOUND && Error != ERROR_NOACCESS && Error != ERROR_INVALID_EXE_SIGNATURE && Error != ERROR_CANT_ACCESS_FILE ) { return TRUE; }
return FALSE; }
BOOL WINAPI MigUtil_Entry ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
VOID Init ( VOID ) { MigUtil_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL); }
VOID Terminate ( VOID ) { MigUtil_Entry (g_hInst, DLL_PROCESS_DETACH, NULL); }
INT __cdecl _tmain ( INT argc, TCHAR *argv[] ) { PCTSTR IconFile = NULL; PCTSTR DestFile = NULL; PCTSTR IconId = NULL; INT IconIndex = 0; INT i; GROWBUFFER Buf = GROWBUF_INIT; GROWBUFFER Buf2 = GROWBUF_INIT; MODE Mode = NONE; BOOL RecurseMode = FALSE; INT Id = 1; ICON_EXTRACT_CONTEXT Context; WORD Icon; DWORD Error; UINT Count; BOOL UseIconIndex = TRUE; TCHAR IconIndexStr[128]; MULTISZ_ENUM MultiSz; PCTSTR IconList; PCTSTR IconList2; BOOL InfOutput = FALSE; INT ResourceId; UINT Column; UINT Indent; TCHAR Buffer[2048]; MULTISZ_ENUM LookAhead; INT Range; PCTSTR LastValidString; BOOL NeedsHeader = TRUE; GROWBUFFER FileList = GROWBUF_INIT; MULTISZ_ENUM FileListEnum; FILE_ENUM FileEnum; UINT Files = 0; TCHAR RootPath[MAX_TCHAR_PATH]; PCTSTR comparePath = NULL; PCTSTR FileName; PCTSTR RootPathPtr; BOOL Quiet = FALSE; PCTSTR NextNum; UINT Start = 0; UINT End = 0xFFFF; UINT Min; UINT Max; TCHAR workPath[MAX_TCHAR_PATH]; PCTSTR fileSpec; MULTISZ_ENUM compareEnum; BOOL match; BOOL noHeader = FALSE;
g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL);
Init();
for (i = 1 ; i < argc ; i++) {
if (argv[i][0] == TEXT('-') || argv[i][0] == TEXT('/')) { switch (_totlower (argv[i][1])) {
case TEXT('x'): if (Mode != NONE) { HelpAndExit(); }
Mode = IMPLANT; break;
case TEXT('d'): if (Mode != NONE) { HelpAndExit(); }
Mode = EXTRACT_ONE; break;
case TEXT('l'): if (Mode != NONE) { HelpAndExit(); }
if (_totlower (argv[i][2]) == TEXT('i')) { InfOutput = TRUE; } else if (argv[i][2]) { HelpAndExit(); }
Mode = LIST; break;
case TEXT('n'): if (noHeader) { HelpAndExit(); }
noHeader = TRUE; break;
case TEXT('c'): if (Mode != NONE) { HelpAndExit(); }
Mode = COMPARE; break;
case TEXT('u'): if (Mode != NONE) { HelpAndExit(); }
Mode = MAKE_UNIQUE; break;
case TEXT('p'): if (comparePath) { HelpAndExit(); }
if (argv[i][2] == ':') { comparePath = &argv[i][3]; } else if (i + 1 < argc) { i++; comparePath = argv[i]; } else { HelpAndExit(); } break;
case TEXT('i'): if (argv[i][2] == ':') { IconId = &argv[i][3]; } else if (i + 1 < argc) { i++; IconId= argv[i]; } else { HelpAndExit(); }
IconIndex = _ttoi (IconId); while (_istspace ((TCHAR)_tcsnextc (IconId))) { IconId = _tcsinc (IconId); }
if (*IconId) { if (!IconIndex && iscsymf(_tcsnextc (IconId))) { UseIconIndex = FALSE; } }
break;
case TEXT('k'): if (Mode != NONE) { HelpAndExit(); }
Mode = KILL; break;
case TEXT('a'): if (Mode != NONE) { HelpAndExit(); }
Mode = EXTRACT_ALL; break;
case TEXT('q'): if (Quiet) { HelpAndExit(); }
Quiet = TRUE; break;
case TEXT('e'): if (Mode != NONE) { HelpAndExit(); }
if (argv[i][2] == ':') { NextNum = &argv[i][3];
if (_tcsnextc (NextNum) != TEXT('-')) { Start = _tcstoul (NextNum, (PTSTR *) (&NextNum), 10); }
if (_tcsnextc (NextNum) == TEXT('-')) { NextNum = _tcsinc (NextNum);
if (*NextNum) { End = _tcstoul (NextNum, (PTSTR *) (&NextNum), 10); } } else { End = Start; }
if (*NextNum) { HelpAndExit(); } }
Mode = EXTRACT; break;
case TEXT('r'): if (RecurseMode) { HelpAndExit(); }
RecurseMode = TRUE; break;
default: HelpAndExit(); } }
else {
Files++; MultiSzAppend (&FileList, argv[i]);
if (IconFile) { DestFile = argv[i]; }
else { IconFile = argv[i]; }
} }
MultiSzAppend (&FileList, S_EMPTY);
//
// Enforce syntax
//
if (Quiet && Mode != LIST) { HelpAndExit(); }
if (Mode == EXTRACT_ALL && DestFile) { HelpAndExit(); }
if (Mode == EXTRACT_ALL || Mode == LIST) { DestFile = IconFile; }
if (Mode == MAKE_UNIQUE) { if (!DestFile) { DestFile = IconFile; } }
if (!DestFile) { HelpAndExit(); }
if (RecurseMode && Mode != EXTRACT_ALL) { HelpAndExit(); }
if (Files > 2 && Mode != LIST) { HelpAndExit(); }
if ((comparePath || noHeader) && Mode != LIST) { HelpAndExit(); }
if (UseIconIndex) { IconId = (PCTSTR) (WORD) IconIndex; wsprintf (IconIndexStr, TEXT("%i"), IconIndex); } else { StringCopy (IconIndexStr, IconId); }
if (Mode == KILL) {
fprintf (stderr, "Beginning icon processing\n");
if (!BeginIconExtraction (&Context, IconFile)) { fprintf (stderr, "Can't begin icon extraction\n"); return 0; }
//
// Get the min and max IDs
//
if (!pGetMinAndMax (&Context, &Min, &Max)) { fprintf (stderr, "Can't kill icons without min/max info\n"); return 0; }
//
// Evaluate the range and remove the icons
//
NextNum = DestFile; Count = 0;
fprintf (stderr, "Removing icons\n");
for (;;) { NextNum = SkipSpace (NextNum);
if (!(*NextNum)) { break; }
if (_tcsnextc (NextNum) == TEXT('-')) { Start = Min; } else { Start = _tcstoul (NextNum, (PTSTR *) (&NextNum), 10); NextNum = SkipSpace (NextNum); }
if (_tcsnextc (NextNum) == TEXT('-')) { NextNum = SkipSpace (_tcsinc (NextNum));
if (_tcsnextc (NextNum) == TEXT(',') || !(*NextNum)) { End = Max; } else { End = _tcstoul (NextNum, (PTSTR *) (&NextNum), 10); NextNum = SkipSpace (NextNum); } } else { End = Start; }
Count += pRemoveIcons (&Context, Start, End);
if (_tcsnextc (NextNum) == TEXT(',')) { NextNum = _tcsinc (NextNum); } else { break; } }
fprintf (stderr, "Saving\n");
if (EndIconExtraction (&Context)) { printf ("Icons removed: %u\n", Count); }
return 0; }
else if (Mode == IMPLANT) { //
// Use IconFile as a source to generate a PE file of icons
//
if (!BeginIconExtraction (&Context, DestFile)) { fprintf (stderr, "Can't begin icon extraction\n"); return 0; }
if (!OpenIconImageFile (&Context, IconFile, FALSE)) { _ftprintf (stderr, TEXT("Can't open %s\n"), IconFile); EndIconExtraction (&Context); return 0; }
Count = 0; while (CopyIcon (&Context, NULL, NULL, 0)) { Count++; }
if (EndIconExtraction (&Context)) { printf ("Icons extracted: %u\n", Count); } }
else if (Mode == EXTRACT || Mode == EXTRACT_ONE) { //
// Use IconFile as a source to generate a PE file of icons
//
if (!BeginIconExtraction (&Context, NULL)) { fprintf (stderr, "Can't begin icon extraction\n"); return 0; }
if (!OpenIconImageFile (&Context, DestFile, TRUE)) { _ftprintf (stderr, TEXT("Can't create %s\n"), DestFile); EndIconExtraction (&Context); return 0; }
if (Mode == EXTRACT) {
//
// If no range is specified, use the CopyAllIcons api
//
if (Start == 0 && End == 0xFFFF) { if (!CopyAllIcons (&Context, IconFile)) { _ftprintf (stderr, TEXT("Can't copy all icons from %s, error %u\n"), IconFile, GetLastError()); } else { _tprintf (TEXT("Extracted all icons from %s\n"), IconFile); } }
//
// If a range is specified, get the names and copy them
// if they are in the range.
//
else { Count = pCopyIconRange (&Context, IconFile, Start, End); _tprintf (TEXT("Icons extracted: %u\n"), Count); }
} else { if (!CopyIcon (&Context, IconFile, NULL, IconIndex)) { _ftprintf (stderr, TEXT("Can't copy %s [%i], error %u\n"), IconFile, IconIndex, GetLastError()); } else { _tprintf (TEXT("Extracted %s [%i]\n"), IconFile, IconIndex); } }
EndIconExtraction (&Context); }
else if (Mode == MAKE_UNIQUE) {
pRemoveDuplicateIcons (IconFile, DestFile);
}
else if (Mode == LIST) {
EnumFirstMultiSz (&FileListEnum, (PCTSTR) FileList.Buf);
do { //
// Separate the path and file pattern
//
FileName = GetFileNameFromPath (FileListEnum.CurrentString);
if (FileName == FileListEnum.CurrentString) { RootPathPtr = TEXT("."); } else { _tcssafecpyab ( RootPath, FileListEnum.CurrentString, FileName, sizeof (RootPath) / sizeof (RootPath[0]) ); RootPathPtr = RootPath;
if (CharCount (RootPath) > 3) { RemoveWackAtEnd (RootPath); } }
//
// Process all files specified
//
if (EnumFirstFile (&FileEnum, RootPathPtr, FileName)) { do {
if (FileEnum.Directory) { continue; }
//
// Process IconFile
//
IconFile = FileEnum.FullPath; IconList = ExtractIconNamesFromFile (IconFile, &Buf);
Count = 0;
if (comparePath) { //
// Prepare a list of resources in a binary located
// in an alternate path
//
fileSpec = GetFileNameFromPath (IconFile); StringCopy (workPath, comparePath); StringCopy (AppendWack (workPath), fileSpec);
IconList2 = ExtractIconNamesFromFile (workPath, &Buf2); } else { IconList2 = IconList; }
if (IconList && IconList2) {
if (!InfOutput) {
//
// Simple output
//
if (EnumFirstMultiSz (&MultiSz, IconList)) {
do { if (IconList != IconList2) { match = FALSE; if (EnumFirstMultiSz (&compareEnum, IconList2)) { do {
if (StringMatch (MultiSz.CurrentString, compareEnum.CurrentString)) { match = TRUE; break; }
} while (EnumNextMultiSz (&compareEnum)); }
if (!match) { continue; } }
if (!Count) { if (IconList != IconList2) { _tprintf (TEXT("Icon resources in both %s and %s:\n\n"), IconFile, workPath); } else { _tprintf (TEXT("Icon resources in %s:\n\n"), IconFile); } }
_tprintf (TEXT(" %s\n"), MultiSz.CurrentString); Count++; } while (EnumNextMultiSz (&MultiSz));
if (Count) { _tprintf (TEXT("\n")); } }
if (IconList != IconList2) { if (EnumFirstMultiSz (&MultiSz, IconList)) {
Count = 0;
do { match = FALSE; if (EnumFirstMultiSz (&compareEnum, IconList2)) { do {
if (StringMatch (MultiSz.CurrentString, compareEnum.CurrentString)) { match = TRUE; break; }
} while (EnumNextMultiSz (&compareEnum)); }
if (match) { continue; }
if (!Count) { _tprintf (TEXT("Icon resources in only in %s:\n\n"), IconFile); }
_tprintf (TEXT(" %s\n"), MultiSz.CurrentString); Count++; } while (EnumNextMultiSz (&MultiSz));
if (Count) { _tprintf (TEXT("\n")); } }
if (EnumFirstMultiSz (&MultiSz, IconList2)) {
Count = 0;
do { match = FALSE; if (EnumFirstMultiSz (&compareEnum, IconList)) { do {
if (StringMatch (MultiSz.CurrentString, compareEnum.CurrentString)) { match = TRUE; break; }
} while (EnumNextMultiSz (&compareEnum)); }
if (match) { continue; }
if (!Count) { _tprintf (TEXT("Icon resources in only in %s:\n\n"), workPath); }
_tprintf (TEXT(" %s\n"), MultiSz.CurrentString); Count++; } while (EnumNextMultiSz (&MultiSz));
if (Count) { _tprintf (TEXT("\n")); } }
Count = 1; }
} else {
//
// INF output
//
//
// Count the numeric resources
//
if (EnumFirstMultiSz (&MultiSz, IconList)) { do { if (IconList != IconList2) { match = FALSE; if (EnumFirstMultiSz (&compareEnum, IconList2)) { do {
if (StringMatch (MultiSz.CurrentString, compareEnum.CurrentString)) { match = TRUE; break; }
} while (EnumNextMultiSz (&compareEnum)); }
if (!match) { continue; } }
if (_tcsnextc (MultiSz.CurrentString) == TEXT('#')) { Count++; } } while (EnumNextMultiSz (&MultiSz)); }
//
// If at least one numeric resource, print it
//
if (Count) {
if (NeedsHeader) { if (!noHeader) { _tprintf (TEXT("[%s]\n"), S_KNOWN_GOOD_ICON_MODULES); }
NeedsHeader = FALSE; }
wsprintf (Buffer, TEXT("%s="), GetFileNameFromPath (IconFile)); Indent = TcharCount (Buffer);
wsprintf (GetEndOfString (Buffer), TEXT("%u"), Count); Column = TcharCount (Buffer);
_tprintf (TEXT("%s"), Buffer);
if (EnumFirstMultiSz (&MultiSz, IconList)) { do { if (IconList != IconList2) { match = FALSE; if (EnumFirstMultiSz (&compareEnum, IconList2)) { do {
if (StringMatch (MultiSz.CurrentString, compareEnum.CurrentString)) { match = TRUE; break; }
} while (EnumNextMultiSz (&compareEnum)); }
if (!match) { continue; } }
if (_tcsnextc (MultiSz.CurrentString) == TEXT('#')) {
ResourceId = _ttoi (_tcsinc (MultiSz.CurrentString));
//
// Determine if this is a range
//
Range = ResourceId;
EnumFirstMultiSz (&LookAhead, MultiSz.CurrentString); LastValidString = MultiSz.CurrentString;
while (EnumNextMultiSz (&LookAhead)) {
if (_tcsnextc (LookAhead.CurrentString) != TEXT('#')) { continue; }
i = _ttoi (_tcsinc (LookAhead.CurrentString)); if (Range + 1 == i) { Range = i; LastValidString = LookAhead.CurrentString; } else { break; } }
//
// Add separator
//
_tprintf (TEXT(",")); Column++;
if (Range > ResourceId + 1) { wsprintf (Buffer, TEXT("%u-%u"), ResourceId, Range); MultiSz.CurrentString = LastValidString; } else { wsprintf (Buffer, TEXT("%u"), ResourceId); }
if (TcharCount (Buffer) + Column > 78) { _tprintf (TEXT("\\\n"));
for (Column = 0 ; Column < Indent ; Column++) { _tprintf (TEXT(" ")); } }
Column += TcharCount (Buffer); _tprintf (TEXT("%s"), Buffer); }
} while (EnumNextMultiSz (&MultiSz)); }
_tprintf (TEXT("\n")); } } }
if (!Count && !Quiet) { _ftprintf (stderr, TEXT("No icons in %s\n"), IconFile); }
if (Count) { g_ErrorLevel = 1; }
} while (EnumNextFile (&FileEnum)); }
} while (EnumNextMultiSz (&FileListEnum)); }
else if (Mode == EXTRACT_ONE) { //
// Extract one icon
//
if (ExtractIconImageFromFile (IconFile, IconId, &Buf)) { if (WriteIconImageArrayToIcoFile (DestFile, &Buf)) { _ftprintf (stderr, TEXT("Icon %s from %s written successfully to %s.\n"), IconIndexStr, IconFile, DestFile); } else { _ftprintf (stderr, TEXT("Can't write icon to %s (error %u)\n"), DestFile, GetLastError()); } } else { _ftprintf (stderr, TEXT("Can't extract icon %s from %s (error %u)\n"), IconIndexStr, IconFile, GetLastError()); } }
else if (Mode == EXTRACT_ALL) { //
// Extract default icon of every file
//
if (!BeginIconExtraction (&Context, DestFile)) { fprintf (stderr, "Can't begin icon extraction\n"); return 0; }
if (RecurseMode) { TREE_ENUM e;
if (EnumFirstFileInTree (&e, TEXT("."), NULL, FALSE)) { do { if (StringIMatch (e.FullPath, DestFile)) { continue; }
Icon = Context.IconId;
if (!CopyAllIcons (&Context, e.FullPath)) { Error = GetLastError();
if (pIsErrorOk (Error)) { _ftprintf (stderr, TEXT("Can't copy icons from %s, error %u\n"), e.FullPath, Error); break; } } else { _tprintf (TEXT("%u: %s\n"), Icon, e.FullPath); } } while (EnumNextFileInTree (&e)); }
} else { WIN32_FIND_DATA fd; HANDLE FindHandle; TCHAR FullPath[MAX_TCHAR_PATH]; PTSTR p;
GetCurrentDirectory (MAX_TCHAR_PATH, FullPath); p = AppendWack (FullPath); StringCopy (p, TEXT("*.*"));
FindHandle = FindFirstFile (FullPath, &fd); if (FindHandle != INVALID_HANDLE_VALUE) { do { if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; }
StringCopy (p, fd.cFileName); if (StringIMatch (FullPath, DestFile)) { continue; }
Icon = Context.IconId;
if (!CopyAllIcons (&Context, fd.cFileName)) { Error = GetLastError();
if (pIsErrorOk (Error)) { _ftprintf (stderr, TEXT("Can't copy icons from %s, error %u\n"), fd.cFileName, Error); break; } } else { _tprintf (TEXT("%u: %s\n"), Icon, fd.cFileName); }
} while (FindNextFile (FindHandle, &fd));
FindClose (FindHandle); } }
if (EndIconExtraction (&Context)) { printf ("Icons extracted.\n"); } }
else if (Mode == COMPARE) { pLaunchCompareDlg (IconFile, DestFile); }
FreeGrowBuffer (&Buf); FreeGrowBuffer (&Buf2); FreeGrowBuffer (&FileList);
Terminate();
return g_ErrorLevel; }
BOOL pSetIconInWindow ( IN HWND IconWnd1, IN HWND IconWnd2, IN PCTSTR FileName1, IN PCTSTR FileName2, IN INT ResourceId ) { HANDLE Instance1; HANDLE Instance2; BOOL b = FALSE; HICON Icon1 = NULL; HICON Icon2 = NULL;
Instance1 = LoadLibraryEx (FileName1, NULL, LOAD_LIBRARY_AS_DATAFILE); if (Instance1) { //
// Get the icon
//
Icon1 = LoadIcon (Instance1, MAKEINTRESOURCE (ResourceId)); }
Instance2 = LoadLibraryEx (FileName2, NULL, LOAD_LIBRARY_AS_DATAFILE); if (Instance2) { //
// Get the icon
//
Icon2 = LoadIcon (Instance2, MAKEINTRESOURCE (ResourceId)); }
if (Icon1 && Icon2) { SendMessage (IconWnd1, STM_SETICON, (WPARAM) Icon1, 0); SendMessage (IconWnd2, STM_SETICON, (WPARAM) Icon2, 0);
b = TRUE; }
if (Instance1) { FreeLibrary (Instance1); }
if (Instance2) { FreeLibrary (Instance2); }
return b; }
typedef struct { GROWBUFFER IdArray; UINT CurrentId; UINT IdCount; PCTSTR FileName1; PCTSTR FileName2; } DLGARGS, *PDLGARGS;
#define WMX_UPDATE_ICONS (WM_APP+1)
BOOL CALLBACK IconCompareDlgProc ( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static PDLGARGS Args; TCHAR Number[32]; INT ResourceId;
switch (uMsg) {
case WM_INITDIALOG: Args = (PDLGARGS) lParam;
SetDlgItemText (hdlg, IDC_FILE_NAME1, Args->FileName1); SetDlgItemText (hdlg, IDC_FILE_NAME2, Args->FileName2); SendMessage (hdlg, WMX_UPDATE_ICONS, 0, 0);
switch (g_ErrorLevel) {
case 0: ResourceId = IDC_NO_MATCH; break;
case 1: ResourceId = IDC_PARTIAL; break;
case 2: ResourceId = IDC_MATCH; break; }
CheckDlgButton (hdlg, ResourceId, BST_CHECKED);
break;
case WMX_UPDATE_ICONS:
ResourceId = (INT) (*((PDWORD) Args->IdArray.Buf + Args->CurrentId));
pSetIconInWindow ( GetDlgItem (hdlg, IDC_ICON1), GetDlgItem (hdlg, IDC_ICON2), Args->FileName1, Args->FileName2, ResourceId );
wsprintf (Number, TEXT("%i"), ResourceId); SetDlgItemText (hdlg, IDC_RESOURCE_ID, Number);
break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: if (IsDlgButtonChecked (hdlg, IDC_NO_MATCH) == BST_CHECKED) { g_ErrorLevel = 0; } else if (IsDlgButtonChecked (hdlg, IDC_PARTIAL) == BST_CHECKED) { g_ErrorLevel = 1; } else if (IsDlgButtonChecked (hdlg, IDC_MATCH) == BST_CHECKED) { g_ErrorLevel = 2; }
EndDialog (hdlg, 0); break;
case IDC_NEXT: if (Args->CurrentId < (Args->IdCount - 1)) { Args->CurrentId++; SendMessage (hdlg, WMX_UPDATE_ICONS, 0, 0); } break;
case IDC_PREV: if (Args->CurrentId > 0) { Args->CurrentId--; SendMessage (hdlg, WMX_UPDATE_ICONS, 0, 0); } break; } break; }
return FALSE; }
VOID pLaunchCompareDlg ( IN PCTSTR FileName1, IN PCTSTR FileName2 ) { DLGARGS Args; PCTSTR IconList1; PCTSTR IconList2; GROWBUFFER Buf1 = GROWBUF_INIT; GROWBUFFER Buf2 = GROWBUF_INIT; MULTISZ_ENUM Enum1, Enum2; BOOL Match;
//
// Obtain the resource ID list from both FileName1 and FileName2.
// Put the union in a grow buffer.
//
ZeroMemory (&Args, sizeof (Args)); Args.FileName1 = FileName1; Args.FileName2 = FileName2;
IconList1 = ExtractIconNamesFromFile (FileName1, &Buf1); IconList2 = ExtractIconNamesFromFile (FileName2, &Buf2);
if (IconList1 && IconList2) { //
// Enumerate list one, then scan list two for a match
//
if (EnumFirstMultiSz (&Enum1, IconList1)) { do { if (_tcsnextc (Enum1.CurrentString) != TEXT('#')) { continue; }
Match = FALSE;
if (EnumFirstMultiSz (&Enum2, IconList2)) { do {
if (StringMatch (Enum1.CurrentString, Enum2.CurrentString)) { Match = TRUE; break; }
} while (EnumNextMultiSz (&Enum2)); }
if (Match) { GrowBufAppendDword ( &Args.IdArray, (DWORD) _ttoi (_tcsinc (Enum1.CurrentString)) );
Args.IdCount++; } else { _ftprintf ( stderr, TEXT("Resource ID %s is not in %s\n"), Enum1.CurrentString, FileName2 ); }
} while (EnumNextMultiSz (&Enum1)); }
//
// Enumerate list two, then scan list one for a match
//
if (EnumFirstMultiSz (&Enum2, IconList2)) { do { if (_tcsnextc (Enum2.CurrentString) != TEXT('#')) { continue; }
Match = FALSE;
if (EnumFirstMultiSz (&Enum1, IconList1)) { do {
if (StringMatch (Enum1.CurrentString, Enum2.CurrentString)) { Match = TRUE; break; }
} while (EnumNextMultiSz (&Enum1)); }
if (!Match) { _ftprintf ( stderr, TEXT("Resource ID %s is not in %s\n"), Enum2.CurrentString, FileName1 ); } } while (EnumNextMultiSz (&Enum2)); }
//
// Now present the dialog
//
if (Args.IdCount) {
DialogBoxParam ( g_hInst, MAKEINTRESOURCE(IDD_COMPARE), NULL, IconCompareDlgProc, (LPARAM) &Args );
} else { _ftprintf (stderr, TEXT("No common icon resources found.\n")); }
} else { if (!IconList1) { _ftprintf (stderr, TEXT("Can't get icon list from %s\n"), FileName1); }
if (!IconList2) { _ftprintf (stderr, TEXT("Can't get icon list from %s\n"), FileName2); } }
FreeGrowBuffer (&Buf1); FreeGrowBuffer (&Buf2);
}
BOOL pCompareIconImages ( IN PCTSTR SourceFile, IN PCTSTR Name1, IN PCTSTR Name2 ) { GROWBUFFER SrcBuf = GROWBUF_INIT; GROWBUFFER DestBuf = GROWBUF_INIT; BOOL b;
b = ExtractIconImageFromFile (SourceFile, Name1, &SrcBuf);
if (b) { b = ExtractIconImageFromFile (SourceFile, Name2, &DestBuf); }
if (b) { if (SrcBuf.End != DestBuf.End) { b = FALSE; } else { b = (memcmp (SrcBuf.Buf, DestBuf.Buf, SrcBuf.End) == 0); } }
FreeGrowBuffer (&SrcBuf); FreeGrowBuffer (&DestBuf);
return b; }
BOOL pMakeNameIndex ( IN PCTSTR SourceFile, OUT PGROWBUFFER IndexBuf, OUT PGROWBUFFER IndexArray ) { PCTSTR IconList; MULTISZ_ENUM e;
IndexBuf->End = 0; IndexArray->End = 0;
IconList = ExtractIconNamesFromFile (SourceFile, IndexBuf);
if (IconList) { //
// Build an index array
//
if (EnumFirstMultiSz (&e, IconList)) { do { if (_tcsnextc (e.CurrentString) != TEXT('#')) { //
// This is a named string
//
GrowBufAppendDword (IndexArray, (DWORD) e.CurrentString);
} else {
//
// This is a 16-bit ID
//
GrowBufAppendDword (IndexArray, (DWORD) _ttoi (_tcsinc (e.CurrentString))); } } while (EnumNextMultiSz (&e)); }
} else { _ftprintf (stderr, TEXT("No icons found in %s\n"), SourceFile); }
return IndexArray->End != 0; }
#define BLANK_ID 0xFFFFFFFF
BOOL pFindUniqueIcons ( IN PCTSTR SourceFile, OUT PGROWBUFFER WorkBuffer, OUT PGROWBUFFER UniqueIndexArray, OUT PUINT OriginalMax ) { GROWBUFFER IndexArray = GROWBUF_INIT; BOOL b; UINT i, j; UINT Count; PDWORD IdPtr;
UniqueIndexArray->End = 0;
b = pMakeNameIndex (SourceFile, WorkBuffer, &IndexArray);
if (b) {
*OriginalMax = 0;
Count = IndexArray.End / sizeof (DWORD); IdPtr = (PDWORD) IndexArray.Buf;
for (i = 0 ; i < Count ; i++) {
if (IdPtr[i] == BLANK_ID) { continue; }
if (IdPtr[i] < 0x10000) { _ftprintf (stderr, TEXT("Processing ID %u\n"), IdPtr[i]);
if (IdPtr[i] > *OriginalMax) { *OriginalMax = IdPtr[i]; } } else { _ftprintf (stderr, TEXT("Processing ID %s\n"), IdPtr[i]); }
for (j = i + 1 ; j < Count ; j++) {
if (IdPtr[j] == BLANK_ID) { continue; }
if (pCompareIconImages (SourceFile, (PCTSTR) (IdPtr[i]), (PCTSTR) (IdPtr[j]))) { IdPtr[j] = BLANK_ID; } } }
for (i = 0 ; i < Count ; i++) { if (IdPtr[i] != BLANK_ID) { GrowBufAppendDword (UniqueIndexArray, IdPtr[i]); } } }
FreeGrowBuffer (&IndexArray); return b; }
UINT pRemoveIcons ( IN PICON_EXTRACT_CONTEXT Context, IN UINT Start, IN UINT End ) { UINT Count = 0; GROWBUFFER Names = GROWBUF_INIT; PCTSTR IconList; MULTISZ_ENUM e; UINT id;
if (Start > End) { return 0; }
if (Start == End) { _ftprintf (stderr, TEXT("Removing icon %u\n"), Start); } else { _ftprintf (stderr, TEXT("Removing icon range %u through %u\n"), Start, End); }
pOpenIconImage (Context, Context->DestFile, NULL, NULL);
IconList = ExtractIconNamesFromFileEx ( Context->ModuleName, &Names, Context->Module, Context->Module16 );
if (IconList) { if (EnumFirstMultiSz (&e, IconList)) { do { if (_tcsnextc (e.CurrentString) == TEXT('#')) {
id = (DWORD) _ttoi (_tcsinc (e.CurrentString));
if (id >= Start && id <= End) { if (UpdateResource ( Context->Update, RT_ICON, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), NULL, 0 )) { Count++; } else { _ftprintf (stderr, TEXT("Can't remove icon ID %u; rc=%u\n"), id, GetLastError()); } } } } while (EnumNextMultiSz (&e)); } } else { _ftprintf (stderr, TEXT("Can't get icon names; rc=%u\n"), GetLastError()); }
FreeGrowBuffer (&Names);
return Count; }
BOOL pRemoveDuplicateIcons ( IN PCTSTR SourcePeFile, IN PCTSTR DestPeFile ) { GROWBUFFER WorkBuffer = GROWBUF_INIT; GROWBUFFER UniqueIndexArray = GROWBUF_INIT; ICON_EXTRACT_CONTEXT Context; UINT Count = 0; UINT u; PDWORD IconId; BOOL b; UINT OriginalMax;
_ftprintf (stderr, TEXT("Finding unique icons\n")); b = pFindUniqueIcons (SourcePeFile, &WorkBuffer, &UniqueIndexArray, &OriginalMax);
if (b) { b = BeginIconExtraction (&Context, DestPeFile);
if (!b) { _ftprintf (stderr, TEXT("Can't save icons to %s\n"), DestPeFile); } }
if (b) {
_ftprintf (stderr, TEXT("Updating icon resources\n"));
Count = UniqueIndexArray.End / sizeof (DWORD); IconId = (PDWORD) UniqueIndexArray.Buf;
for (u = 0 ; u < Count ; u++) { b = CopyIcon (&Context, SourcePeFile, (PCTSTR) (IconId[u]), 0); if (!b) { if (IconId[u] < 0x10000) { _ftprintf (stderr, TEXT("Can't copy icon %u\n"), IconId[u]); } else { _ftprintf (stderr, TEXT("Can't copy icon %s\n"), IconId[u]); }
break; } } }
if (b) {
pRemoveIcons (&Context, Count + 1, OriginalMax);
b = EndIconExtraction (&Context);
if (!b) { _ftprintf (stderr, TEXT("Can't safe icons\n")); } }
if (b) { _ftprintf (stderr, TEXT("Final icon count: %u\n"), Count); }
FreeGrowBuffer (&WorkBuffer); FreeGrowBuffer (&UniqueIndexArray);
return b; }
BOOL pGetMinAndMax ( IN PICON_EXTRACT_CONTEXT Context, OUT PUINT Min, OUT PUINT Max ) { BOOL b = FALSE; GROWBUFFER Names = GROWBUF_INIT; PCTSTR IconList; UINT id; MULTISZ_ENUM e;
*Min = (UINT) -1; *Max = 0;
pOpenIconImage (Context, Context->DestFile, NULL, NULL);
_ftprintf (stderr, TEXT("Getting min/max icon indexes from %s\n"), Context->ModuleName);
IconList = ExtractIconNamesFromFileEx ( Context->ModuleName, &Names, Context->Module, Context->Module16 );
if (IconList) { if (EnumFirstMultiSz (&e, IconList)) { do { if (_tcsnextc (e.CurrentString) == TEXT('#')) {
id = (DWORD) _ttoi (_tcsinc (e.CurrentString));
if (id < *Min) { *Min = id; }
if (id > *Max) { *Max = id; } } } while (EnumNextMultiSz (&e)); }
b = TRUE; }
FreeGrowBuffer (&Names);
if (b) { _ftprintf (stderr, TEXT("Min: %u Max: %u\n"), *Min, *Max); } else { _ftprintf (stderr, TEXT("Can't get min/max info, rc=%u\n"), GetLastError()); }
return b; }
UINT pCopyIconRange ( IN PICON_EXTRACT_CONTEXT Context, IN PCTSTR IconFile, IN UINT Start, IN UINT End ) { UINT Count = 0; GROWBUFFER Names = GROWBUF_INIT; PCTSTR IconList; UINT id; MULTISZ_ENUM e;
pOpenIconImage (Context, IconFile, NULL, NULL);
if (Start == End) { _ftprintf ( stderr, TEXT("Copying icon %u from %s to %s\n"), Start, Context->ModuleName, Context->IconImageFileName ); } else { _ftprintf ( stderr, TEXT("Copying icon range %u to %u from %s to %s\n"), Start, End, Context->ModuleName, Context->IconImageFileName ); }
IconList = ExtractIconNamesFromFileEx ( Context->ModuleName, &Names, Context->Module, Context->Module16 );
if (IconList) { if (EnumFirstMultiSz (&e, IconList)) { do { if (_tcsnextc (e.CurrentString) == TEXT('#')) {
id = (DWORD) _ttoi (_tcsinc (e.CurrentString));
if (id >= Start && id <= End) { if (!CopyIcon (Context, IconFile, e.CurrentString, 0)) { _ftprintf (stderr, TEXT("Can't copy %s [%i], error %u\n"), IconFile, id, GetLastError()); } else { Count++; } } } } while (EnumNextMultiSz (&e)); } } else { _ftprintf (stderr, TEXT("Can't get icon names from %s\n"), Context->ModuleName); }
FreeGrowBuffer (&Names);
return Count; }
|