/*++ Copyright (c) 1998 Microsoft Corporation Module Name: icontool.c Abstract: Tool to extract icons from ICO, PE and NE files and to write them to an ICO or PE file Author: Calin Negreanu (calinn) 16 June 2000 Revision History: () --*/ #include "pch.h" HANDLE g_hHeap; HINSTANCE g_hInst; BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID); BOOL pCallEntryPoints ( DWORD Reason ) { switch (Reason) { case DLL_PROCESS_ATTACH: UtInitialize (NULL); FileEnumInitialize (); LogReInit (NULL, NULL, NULL, NULL); break; case DLL_PROCESS_DETACH: FileEnumTerminate (); UtTerminate (); break; } return TRUE; } BOOL Init ( VOID ) { g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL); return pCallEntryPoints (DLL_PROCESS_ATTACH); } VOID Terminate ( VOID ) { pCallEntryPoints (DLL_PROCESS_DETACH); } VOID pHelpAndExit ( VOID ) { // // This routine is called whenever command line args are wrong // fprintf ( stderr, "Command Line Syntax:\n\n" // // Describe command line syntax(es), indent 2 spaces // " icontool [/D:] \n" "\nDescription:\n\n" // // Describe tool, indent 2 spaces // " Extracts icon groups from ICO, PE and NE files specified and\n" " . Optionally writes the extracted icons to either a PE file or\n" " a sequence of ICO files.\n" "\nArguments:\n\n" // // Describe args, indent 2 spaces, say optional if necessary // " /D: - Specifies the destination file where all extracted icons\n" " are going to be written. It's either a PE file specification\n" " or a sequence of ICO files with %%d in name (like icon%%04d.ico)\n" " Specifies the directory pattern (like c:\\foo*\\bar?\\*)\n" " Specifies the file pattern (like abc*.exe)\n" ); exit (1); } BOOL pGetFilePath ( IN PCSTR UserSpecifiedFile, OUT PTSTR Buffer, IN UINT BufferTchars ) { PSTR tempBuffer = NULL; CHAR modulePath[MAX_MBCHAR_PATH]; CHAR currentDir[MAX_MBCHAR_PATH]; PSTR p; PCSTR userFile = NULL; PSTR dontCare; __try { // // Locate the file using the full path specified by the user, or // if only a file spec was given, use the following priorities: // // 1. Current directory // 2. Directory where the tool is // // In all cases, return the full path to the file. // tempBuffer = AllocTextA (BufferTchars); *tempBuffer = 0; if (!_mbsrchr (UserSpecifiedFile, '\\')) { if (!GetModuleFileNameA (NULL, modulePath, ARRAYSIZE(modulePath))) { MYASSERT (FALSE); return FALSE; } p = _mbsrchr (modulePath, '\\'); if (p) { *p = 0; } else { MYASSERT (FALSE); return FALSE; } if (!GetCurrentDirectoryA (ARRAYSIZE(currentDir), currentDir)) { MYASSERT (FALSE); return FALSE; } // // Let's see if it's in the current dir // userFile = JoinPathsA (currentDir, UserSpecifiedFile); if (DoesFileExistA (userFile)) { GetFullPathNameA ( userFile, BufferTchars, tempBuffer, &dontCare ); } else { // // Let's try the module dir // FreePathStringA (userFile); userFile = JoinPathsA (modulePath, UserSpecifiedFile); if (DoesFileExistA (userFile)) { GetFullPathNameA ( userFile, BufferTchars, tempBuffer, &dontCare ); } } } else { // // Use the full path that the user specified // GetFullPathNameA ( UserSpecifiedFile, BufferTchars, tempBuffer, &dontCare ); } // // Transfer output into caller's buffer. Note the TCHAR conversion. // #ifdef UNICODE KnownSizeAtoW (Buffer, tempBuffer); #else StringCopy (Buffer, tempBuffer); #endif } __finally { if (userFile) { FreePathStringA (userFile); } FreeTextA (tempBuffer); } return *Buffer != 0; } PCTSTR pGetIconFileType ( IN DWORD FileType ) { switch (FileType) { case ICON_ICOFILE: return TEXT("ICO File"); case ICON_PEFILE: return TEXT("PE File"); case ICON_NEFILE: return TEXT("NE File"); } return TEXT("UNKNOWN "); } INT __cdecl _tmain ( INT Argc, PCTSTR Argv[] ) { INT i; PCTSTR nodePattern = NULL; PCTSTR leafPattern = NULL; PTSTR encodedPattern = NULL; PCSTR destFile = NULL; PSTR p; TCHAR destPath[MAX_PATH_PLUS_NUL]; TCHAR destIcoPath[MAX_PATH_PLUS_NUL]; FILETREE_ENUM e; ICON_ENUM iconEnum; PCSTR resourceId; DWORD totalIcons = 0; DWORD fileIcons = 0; DWORD fileType = 0; if (!Init()) { return 0; } for (i = 1 ; i < Argc ; i++) { if (Argv[i][0] == TEXT('/') || Argv[i][0] == TEXT('-')) { switch (_totlower (_tcsnextc (&Argv[i][1]))) { case TEXT('d'): if (Argv[i][2] == TEXT(':')) { destFile = &Argv[i][3]; } else if (i + 1 < Argc) { i++; destFile = Argv[i]; } else { pHelpAndExit(); } if (!pGetFilePath (destFile, destPath, ARRAYSIZE(destPath))) { destPath [0] = 0; break; } break; default: pHelpAndExit(); } } else { // // Parse other args that don't require / or - // if (nodePattern || leafPattern) { pHelpAndExit(); } nodePattern = Argv[i]; if (*nodePattern == TEXT('\"')) { nodePattern++; p = _tcsdec2 (nodePattern, GetEndOfString (nodePattern)); if (p && *p == TEXT('\"')) { *p = 0; } } leafPattern = Argv[i+1]; i++; } } if (!nodePattern) { pHelpAndExit (); } if (!leafPattern) { pHelpAndExit (); } // // Begin processing // encodedPattern = ObsBuildEncodedObjectStringEx (nodePattern, leafPattern, FALSE); if (EnumFirstFileInTree (&e, encodedPattern)) { // at this point, if we don't have a valid updateHandle and moduleHandle // we will assume that the destination specification is a sequence of ICO files. do { fileIcons = 0; if (IcoEnumFirstIconGroupInFile (e.NativeFullName, &iconEnum)) { fileType = iconEnum.FileType; do { if (destPath [0]) { if (fileIcons == 0x0b) { } else { if (!IcoWriteIconGroupToPeFile (destPath, iconEnum.IconGroup, &resourceId, NULL)) { wsprintf (destIcoPath, destPath, totalIcons); if (!IcoWriteIconGroupToIcoFile (destIcoPath, iconEnum.IconGroup, TRUE)) { printf ("Error writing icon group to destination file %s\n", destPath); } } } } totalIcons ++; fileIcons ++; } while (IcoEnumNextIconGroupInFile (&iconEnum)); IcoAbortEnumIconGroup (&iconEnum); } if (fileIcons) { printf ("[%6u],[%6u] [%8s] %s\n", totalIcons, fileIcons, pGetIconFileType (fileType), e.NativeFullName); } } while (EnumNextFileInTree (&e)); } // // End of processing // Terminate(); return 0; }