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 | FORMAT_MESSAGE_FROM_SYSTEM | 87 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 88 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 89 (LPTSTR) & message, 0, NULL) != 0) { 90 printf("%S", (LPTSTR) message); 91 LocalFree(message); 92 } 93 } 94 95 // Note: We do not check here that iconTarget is valid icon. 96 // Java code will already do this for us. 97 98 bool ChangeIcon(wstring iconTarget, wstring launcher) { 99 WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); 100 101 HANDLE icon = CreateFile(iconTarget.c_str(), GENERIC_READ, 0, NULL, 102 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 103 if (icon == INVALID_HANDLE_VALUE) { 104 PrintError(); 105 return false; 106 } 107 108 // Reading .ICO file 109 WORD idReserved, idType, idCount; 110 111 DWORD dwBytesRead; 112 ReadFile(icon, &idReserved, sizeof (WORD), &dwBytesRead, NULL); 113 ReadFile(icon, &idType, sizeof (WORD), &dwBytesRead, NULL); 114 ReadFile(icon, &idCount, sizeof (WORD), &dwBytesRead, NULL); 115 116 LPICONDIR lpid = (LPICONDIR) malloc( 117 sizeof (ICONDIR) + (sizeof (ICONDIRENTRY) * (idCount - 1))); 118 if (lpid == NULL) { 119 CloseHandle(icon); 120 printf("Error: Failed to allocate memory\n"); 121 return false; 122 } 123 124 lpid->idReserved = idReserved; 125 lpid->idType = idType; 126 lpid->idCount = idCount; 127 128 ReadFile(icon, &lpid->idEntries[0], sizeof (ICONDIRENTRY) * lpid->idCount, 129 &dwBytesRead, NULL); 130 131 LPGRPICONDIR lpgid = (LPGRPICONDIR) malloc( 132 sizeof (GRPICONDIR) + (sizeof (GRPICONDIRENTRY) * (idCount - 1))); 133 if (lpid == NULL) { 134 CloseHandle(icon); 135 free(lpid); 136 printf("Error: Failed to allocate memory\n"); 137 return false; 138 } 139 140 lpgid->idReserved = idReserved; 141 lpgid->idType = idType; 142 lpgid->idCount = idCount; 143 144 for (int i = 0; i < lpgid->idCount; i++) { 145 lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth; 146 lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight; 147 lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount; 148 lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved; 149 lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes; 150 lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount; 151 lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes; 152 lpgid->idEntries[i].nID = i + 1; 153 } 154 155 // Store images in .EXE 156 HANDLE update = BeginUpdateResource(launcher.c_str(), FALSE); 157 if (update == NULL) { 158 free(lpid); 159 free(lpgid); 160 CloseHandle(icon); 161 PrintError(); 162 return false; 163 } 164 165 for (int i = 0; i < lpid->idCount; i++) { 166 LPBYTE lpBuffer = (LPBYTE) malloc(lpid->idEntries[i].dwBytesInRes); 167 SetFilePointer(icon, lpid->idEntries[i].dwImageOffset, 168 NULL, FILE_BEGIN); 169 ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes, 170 &dwBytesRead, NULL); 171 if (!UpdateResource(update, RT_ICON, 172 MAKEINTRESOURCE(lpgid->idEntries[i].nID), 173 language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) { 174 free(lpBuffer); 175 free(lpid); 176 free(lpgid); 177 CloseHandle(icon); 178 PrintError(); 179 return false; 180 } 181 free(lpBuffer); 182 } 183 184 free(lpid); 185 CloseHandle(icon); 186 187 if (!UpdateResource(update, RT_GROUP_ICON, 188 MAKEINTRESOURCE(1), language, &lpgid[0], 189 (sizeof (WORD) * 3) + (sizeof (GRPICONDIRENTRY) * lpgid->idCount))) { 190 free(lpgid); 191 PrintError(); 192 return false; 193 } 194 195 free(lpgid); 196 197 if (EndUpdateResource(update, FALSE) == FALSE) { 198 PrintError(); 199 return false; 200 } 201 202 return true; 203 }