/* * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ // iconswap.cpp : Defines the entry point for the console application. // //Define Windows compatibility requirements //XP or later #define WINVER 0x0501 #define _WIN32_WINNT 0x0501 #include #include #include #include #include #include #include #include #include #include #include // http://msdn.microsoft.com/en-us/library/ms997538.aspx typedef struct _ICONDIRENTRY { BYTE bWidth; BYTE bHeight; BYTE bColorCount; BYTE bReserved; WORD wPlanes; WORD wBitCount; DWORD dwBytesInRes; DWORD dwImageOffset; } ICONDIRENTRY, * LPICONDIRENTRY; typedef struct _ICONDIR { WORD idReserved; WORD idType; WORD idCount; ICONDIRENTRY idEntries[1]; } ICONDIR, * LPICONDIR; // #pragmas are used here to insure that the structure's // packing in memory matches the packing of the EXE or DLL. #pragma pack(push) #pragma pack(2) typedef struct _GRPICONDIRENTRY { BYTE bWidth; BYTE bHeight; BYTE bColorCount; BYTE bReserved; WORD wPlanes; WORD wBitCount; DWORD dwBytesInRes; WORD nID; } GRPICONDIRENTRY, * LPGRPICONDIRENTRY; #pragma pack(pop) #pragma pack(push) #pragma pack(2) typedef struct _GRPICONDIR { WORD idReserved; WORD idType; WORD idCount; GRPICONDIRENTRY idEntries[1]; } GRPICONDIR, * LPGRPICONDIR; #pragma pack(pop) void PrintError() { LPVOID message; DWORD error = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &message, 0, NULL); wprintf(L"%s\n", (__wchar_t *) message); // VS2017 - FIXME LocalFree(message); } bool ChangeIcon(_TCHAR* iconFileName, _TCHAR* executableFileName) { bool result = false; DWORD dwData = 1; WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); _TCHAR* iconExtension = wcsrchr(iconFileName, '.'); if (iconExtension == NULL || wcscmp(iconExtension, L".ico") != 0) { wprintf(L"Unknown icon format - please provide .ICO file.\n"); return result; } HANDLE icon = CreateFile(iconFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (icon == INVALID_HANDLE_VALUE) { PrintError(); return result; } // Reading .ICO file WORD idReserved, idType, idCount; DWORD dwBytesRead; ReadFile(icon, &idReserved, sizeof(WORD), &dwBytesRead, NULL); ReadFile(icon, &idType, sizeof(WORD), &dwBytesRead, NULL); ReadFile(icon, &idCount, sizeof(WORD), &dwBytesRead, NULL); LPICONDIR lpid = (LPICONDIR)malloc( sizeof(ICONDIR) + (sizeof(ICONDIRENTRY) * (idCount - 1))); if (lpid == NULL) { CloseHandle(icon); wprintf(L"Unknown error.\n"); } lpid->idReserved = idReserved; lpid->idType = idType; lpid->idCount = idCount; ReadFile(icon, &lpid->idEntries[0], sizeof(ICONDIRENTRY) * lpid->idCount, &dwBytesRead, NULL); LPGRPICONDIR lpgid = (LPGRPICONDIR)malloc( sizeof(GRPICONDIR) + (sizeof(GRPICONDIRENTRY) * (idCount - 1))); if (lpid == NULL) { CloseHandle(icon); free(lpid); wprintf(L"Unknown error.\n"); } lpgid->idReserved = idReserved; lpgid->idType = idType; lpgid->idCount = idCount; for(int i = 0; i < lpgid->idCount; i++) { lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth; lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight; lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount; lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved; lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes; lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount; lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes; lpgid->idEntries[i].nID = i + 1; } // Store images in .EXE HANDLE update = BeginUpdateResource( executableFileName, FALSE ); if (update == NULL) { free(lpid); free(lpgid); CloseHandle(icon); PrintError(); return result; } for(int i = 0; i < lpid->idCount; i++) { LPBYTE lpBuffer = (LPBYTE)malloc(lpid->idEntries[i].dwBytesInRes); SetFilePointer(icon, lpid->idEntries[i].dwImageOffset, NULL, FILE_BEGIN); ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes, &dwBytesRead, NULL); if (!UpdateResource(update, RT_ICON, MAKEINTRESOURCE(lpgid->idEntries[i].nID), language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) { free(lpBuffer); free(lpid); free(lpgid); CloseHandle(icon); PrintError(); return result; } free(lpBuffer); } free(lpid); CloseHandle(icon); if (!UpdateResource(update, RT_GROUP_ICON, MAKEINTRESOURCE(1), language, &lpgid[0], (sizeof(WORD) * 3) + (sizeof(GRPICONDIRENTRY) * lpgid->idCount))) { free(lpgid); PrintError(); return result; } free(lpgid); if (EndUpdateResource(update, FALSE) == FALSE) { PrintError(); return result; } result = true; return result; }