1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdio.h> 27 #include <windows.h> 28 #include <stdlib.h> 29 #include <string> 30 #include <malloc.h> 31 32 using namespace std; 33 34 // http://msdn.microsoft.com/en-us/library/ms997538.aspx 35 36 typedef struct _ICONDIRENTRY { 37 BYTE bWidth; 38 BYTE bHeight; 39 BYTE bColorCount; 40 BYTE bReserved; 41 WORD wPlanes; 42 WORD wBitCount; 43 DWORD dwBytesInRes; 44 DWORD dwImageOffset; 45 } ICONDIRENTRY, * LPICONDIRENTRY; 46 47 typedef struct _ICONDIR { 48 WORD idReserved; 49 WORD idType; 50 WORD idCount; 51 ICONDIRENTRY idEntries[1]; 52 } ICONDIR, * LPICONDIR; 53 54 // #pragmas are used here to insure that the structure's 55 // packing in memory matches the packing of the EXE or DLL. 56 #pragma pack(push) 57 #pragma pack(2) 58 59 typedef struct _GRPICONDIRENTRY { 60 BYTE bWidth; 61 BYTE bHeight; 62 BYTE bColorCount; 63 BYTE bReserved; 64 WORD wPlanes; 65 WORD wBitCount; 66 DWORD dwBytesInRes; 67 WORD nID; 68 } GRPICONDIRENTRY, * LPGRPICONDIRENTRY; 69 #pragma pack(pop) 70 71 #pragma pack(push) 72 #pragma pack(2) 73 74 typedef struct _GRPICONDIR { 75 WORD idReserved; 76 WORD idType; 77 WORD idCount; 78 GRPICONDIRENTRY idEntries[1]; 79 } GRPICONDIR, * LPGRPICONDIR; 80 #pragma pack(pop) 81 82 void PrintError() { 83 LPVOID message = NULL; 84 DWORD error = GetLastError(); 85 86 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 87 | FORMAT_MESSAGE_FROM_SYSTEM 88 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 89 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 90 (LPTSTR) & message, 0, NULL) != 0) { 91 printf("%S", (LPTSTR) message); 92 LocalFree(message); 93 } 94 } 95 96 // Note: We do not check here that iconTarget is valid icon. 97 // Java code will already do this for us. 98 99 bool ChangeIcon(wstring iconTarget, wstring launcher) { 100 WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); 101 102 HANDLE icon = CreateFile(iconTarget.c_str(), GENERIC_READ, 0, NULL, 103 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 104 if (icon == INVALID_HANDLE_VALUE) { 105 PrintError(); 106 return false; 107 } 108 109 // Reading .ICO file 110 WORD idReserved, idType, idCount; 111 112 DWORD dwBytesRead; 113 ReadFile(icon, &idReserved, sizeof (WORD), &dwBytesRead, NULL); 114 ReadFile(icon, &idType, sizeof (WORD), &dwBytesRead, NULL); 115 ReadFile(icon, &idCount, sizeof (WORD), &dwBytesRead, NULL); 116 117 LPICONDIR lpid = (LPICONDIR) malloc( 118 sizeof (ICONDIR) + (sizeof (ICONDIRENTRY) * (idCount - 1))); 119 if (lpid == NULL) { 120 CloseHandle(icon); 121 printf("Error: Failed to allocate memory\n"); 122 return false; 123 } 124 125 lpid->idReserved = idReserved; 126 lpid->idType = idType; 127 lpid->idCount = idCount; 128 129 ReadFile(icon, &lpid->idEntries[0], sizeof (ICONDIRENTRY) * lpid->idCount, 130 &dwBytesRead, NULL); 131 132 LPGRPICONDIR lpgid = (LPGRPICONDIR) malloc( 133 sizeof (GRPICONDIR) + (sizeof (GRPICONDIRENTRY) * (idCount - 1))); 134 if (lpid == NULL) { 135 CloseHandle(icon); 136 free(lpid); 137 printf("Error: Failed to allocate memory\n"); 138 return false; 139 } 140 141 lpgid->idReserved = idReserved; 142 lpgid->idType = idType; 143 lpgid->idCount = idCount; 144 145 for (int i = 0; i < lpgid->idCount; i++) { 146 lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth; 147 lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight; 148 lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount; 149 lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved; 150 lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes; 151 lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount; 152 lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes; 153 lpgid->idEntries[i].nID = i + 1; 154 } 155 156 // Store images in .EXE 157 HANDLE update = BeginUpdateResource(launcher.c_str(), FALSE); 158 if (update == NULL) { 159 free(lpid); 160 free(lpgid); 161 CloseHandle(icon); 162 PrintError(); 163 return false; 164 } 165 166 for (int i = 0; i < lpid->idCount; i++) { 167 LPBYTE lpBuffer = (LPBYTE) malloc(lpid->idEntries[i].dwBytesInRes); 168 SetFilePointer(icon, lpid->idEntries[i].dwImageOffset, 169 NULL, FILE_BEGIN); 170 ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes, 171 &dwBytesRead, NULL); 172 if (!UpdateResource(update, RT_ICON, 173 MAKEINTRESOURCE(lpgid->idEntries[i].nID), 174 language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) { 175 free(lpBuffer); 176 free(lpid); 177 free(lpgid); 178 CloseHandle(icon); 179 PrintError(); 180 return false; 181 } 182 free(lpBuffer); 183 } 184 185 free(lpid); 186 CloseHandle(icon); 187 188 if (!UpdateResource(update, RT_GROUP_ICON, MAKEINTRESOURCE(1), 189 language, &lpgid[0], (sizeof (WORD) * 3) 190 + (sizeof (GRPICONDIRENTRY) * lpgid->idCount))) { 191 free(lpgid); 192 PrintError(); 193 return false; 194 } 195 196 free(lpgid); 197 198 if (EndUpdateResource(update, FALSE) == FALSE) { 199 PrintError(); 200 return false; 201 } 202 203 return true; 204 }