--- /dev/null 2019-01-11 12:15:53.000000000 -0500 +++ new/src/jdk.jpackage/windows/native/jpackage/IconSwap.cpp 2019-01-11 12:15:52.442384800 -0500 @@ -0,0 +1,229 @@ +/* + * 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; +}