1 /*
2 * Copyright (c) 2012, 2020, 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
PrintError()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
ChangeIcon(HANDLE update,const wstring & iconTarget)99 bool ChangeIcon(HANDLE update, const wstring& iconTarget) {
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 for (int i = 0; i < lpid->idCount; i++) {
158 LPBYTE lpBuffer = (LPBYTE) malloc(lpid->idEntries[i].dwBytesInRes);
159 SetFilePointer(icon, lpid->idEntries[i].dwImageOffset,
160 NULL, FILE_BEGIN);
161 ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes,
162 &dwBytesRead, NULL);
163 if (!UpdateResource(update, RT_ICON,
164 MAKEINTRESOURCE(lpgid->idEntries[i].nID),
165 language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) {
166 free(lpBuffer);
167 free(lpid);
168 free(lpgid);
169 CloseHandle(icon);
170 PrintError();
171 return false;
172 }
173 free(lpBuffer);
174 }
175
176 free(lpid);
177 CloseHandle(icon);
178
179 if (!UpdateResource(update, RT_GROUP_ICON, MAKEINTRESOURCE(1),
180 language, &lpgid[0], (sizeof (WORD) * 3)
181 + (sizeof (GRPICONDIRENTRY) * lpgid->idCount))) {
182 free(lpgid);
183 PrintError();
184 return false;
185 }
186
187 free(lpgid);
188
189 return true;
190 }
191