src/jdk.jpackage/windows/native/jpackage/IconSwap.cpp
branchJDK-8200758-branch
changeset 57151 38d0b67617e3
parent 57150 fa68c2ab636d
child 57152 225a4ac5bd57
equal deleted inserted replaced
57150:fa68c2ab636d 57151:38d0b67617e3
     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 // iconswap.cpp : Defines the entry point for the console application.
       
    27 //
       
    28 
       
    29 //Define Windows compatibility requirements
       
    30 //XP or later
       
    31 #define WINVER 0x0501
       
    32 #define _WIN32_WINNT 0x0501
       
    33 
       
    34 #include <tchar.h>
       
    35 #include <stdio.h>
       
    36 #include <windows.h>
       
    37 #include <stdlib.h>
       
    38 #include <iostream>
       
    39 #include <malloc.h>
       
    40 #include <sys/types.h>
       
    41 #include <sys/stat.h>
       
    42 #include <io.h>
       
    43 #include <strsafe.h>
       
    44 #include <Shellapi.h>
       
    45 
       
    46 
       
    47 // http://msdn.microsoft.com/en-us/library/ms997538.aspx
       
    48 
       
    49 typedef struct _ICONDIRENTRY {
       
    50     BYTE bWidth;
       
    51     BYTE bHeight;
       
    52     BYTE bColorCount;
       
    53     BYTE bReserved;
       
    54     WORD wPlanes;
       
    55     WORD wBitCount;
       
    56     DWORD dwBytesInRes;
       
    57     DWORD dwImageOffset;
       
    58 } ICONDIRENTRY, * LPICONDIRENTRY;
       
    59 
       
    60 typedef struct _ICONDIR {
       
    61     WORD idReserved;
       
    62     WORD idType;
       
    63     WORD idCount;
       
    64     ICONDIRENTRY idEntries[1];
       
    65 } ICONDIR, * LPICONDIR;
       
    66 
       
    67 // #pragmas are used here to insure that the structure's
       
    68 // packing in memory matches the packing of the EXE or DLL.
       
    69 #pragma pack(push)
       
    70 #pragma pack(2)
       
    71 typedef struct _GRPICONDIRENTRY {
       
    72     BYTE bWidth;
       
    73     BYTE bHeight;
       
    74     BYTE bColorCount;
       
    75     BYTE bReserved;
       
    76     WORD wPlanes;
       
    77     WORD wBitCount;
       
    78     DWORD dwBytesInRes;
       
    79     WORD nID;
       
    80 } GRPICONDIRENTRY, * LPGRPICONDIRENTRY;
       
    81 #pragma pack(pop)
       
    82 
       
    83 #pragma pack(push)
       
    84 #pragma pack(2)
       
    85 typedef struct _GRPICONDIR {
       
    86     WORD idReserved;
       
    87     WORD idType;
       
    88     WORD idCount;
       
    89     GRPICONDIRENTRY idEntries[1];
       
    90 } GRPICONDIR, * LPGRPICONDIR;
       
    91 #pragma pack(pop)
       
    92 
       
    93 void PrintError()
       
    94 {
       
    95     LPVOID message;
       
    96     DWORD error = GetLastError();
       
    97 
       
    98     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
       
    99         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
       
   100         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       
   101         (LPTSTR) &message, 0, NULL);
       
   102 
       
   103     wprintf(L"%s\n", (__wchar_t *) message); // VS2017 - FIXME
       
   104     LocalFree(message);
       
   105 }
       
   106 
       
   107 bool ChangeIcon(_TCHAR* iconFileName, _TCHAR* executableFileName)
       
   108 {
       
   109     bool result = false;
       
   110 
       
   111     DWORD dwData = 1;
       
   112     WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
       
   113 
       
   114     _TCHAR* iconExtension = wcsrchr(iconFileName, '.');
       
   115     if (iconExtension == NULL || wcscmp(iconExtension, L".ico") != 0) {
       
   116         wprintf(L"Unknown icon format - please provide .ICO file.\n");
       
   117         return result;
       
   118     }
       
   119 
       
   120     HANDLE icon = CreateFile(iconFileName, GENERIC_READ, 0, NULL,
       
   121             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       
   122     if (icon == INVALID_HANDLE_VALUE) {
       
   123         PrintError();
       
   124         return result;
       
   125     }
       
   126 
       
   127     // Reading .ICO file
       
   128     WORD idReserved, idType, idCount;
       
   129 
       
   130     DWORD dwBytesRead;
       
   131     ReadFile(icon, &idReserved, sizeof(WORD), &dwBytesRead, NULL);
       
   132     ReadFile(icon, &idType, sizeof(WORD), &dwBytesRead, NULL);
       
   133     ReadFile(icon, &idCount, sizeof(WORD), &dwBytesRead, NULL);
       
   134 
       
   135     LPICONDIR lpid = (LPICONDIR)malloc(
       
   136             sizeof(ICONDIR) + (sizeof(ICONDIRENTRY) * (idCount - 1)));
       
   137 
       
   138     if (lpid == NULL) {
       
   139         CloseHandle(icon);
       
   140         wprintf(L"Unknown error.\n");
       
   141     }
       
   142 
       
   143     lpid->idReserved = idReserved;
       
   144     lpid->idType = idType;
       
   145     lpid->idCount = idCount;
       
   146 
       
   147     ReadFile(icon, &lpid->idEntries[0], sizeof(ICONDIRENTRY) * lpid->idCount,
       
   148             &dwBytesRead, NULL);
       
   149 
       
   150 
       
   151     LPGRPICONDIR lpgid = (LPGRPICONDIR)malloc(
       
   152             sizeof(GRPICONDIR) + (sizeof(GRPICONDIRENTRY) * (idCount - 1)));
       
   153 
       
   154     if (lpid == NULL) {
       
   155         CloseHandle(icon);
       
   156         free(lpid);
       
   157         wprintf(L"Unknown error.\n");
       
   158     }
       
   159 
       
   160     lpgid->idReserved = idReserved;
       
   161     lpgid->idType = idType;
       
   162     lpgid->idCount = idCount;
       
   163 
       
   164     for(int i = 0; i < lpgid->idCount; i++)
       
   165     {
       
   166         lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth;
       
   167         lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight;
       
   168         lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount;
       
   169         lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved;
       
   170         lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes;
       
   171         lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount;
       
   172         lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes;
       
   173         lpgid->idEntries[i].nID = i + 1;
       
   174     }
       
   175 
       
   176     // Store images in .EXE
       
   177     HANDLE update = BeginUpdateResource( executableFileName, FALSE );
       
   178 
       
   179     if (update == NULL) {
       
   180         free(lpid);
       
   181         free(lpgid);
       
   182         CloseHandle(icon);
       
   183         PrintError();
       
   184         return result;
       
   185     }
       
   186 
       
   187     for(int i = 0; i < lpid->idCount; i++)
       
   188     {
       
   189         LPBYTE lpBuffer = (LPBYTE)malloc(lpid->idEntries[i].dwBytesInRes);
       
   190         SetFilePointer(icon, lpid->idEntries[i].dwImageOffset,
       
   191                 NULL, FILE_BEGIN);
       
   192         ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes,
       
   193                 &dwBytesRead, NULL);
       
   194         if (!UpdateResource(update, RT_ICON,
       
   195                 MAKEINTRESOURCE(lpgid->idEntries[i].nID),
       
   196                 language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes))
       
   197         {
       
   198             free(lpBuffer);
       
   199             free(lpid);
       
   200             free(lpgid);
       
   201             CloseHandle(icon);
       
   202             PrintError();
       
   203             return result;
       
   204         }
       
   205         free(lpBuffer);
       
   206     }
       
   207 
       
   208     free(lpid);
       
   209     CloseHandle(icon);
       
   210 
       
   211     if (!UpdateResource(update, RT_GROUP_ICON,
       
   212             MAKEINTRESOURCE(1), language, &lpgid[0],
       
   213             (sizeof(WORD) * 3) + (sizeof(GRPICONDIRENTRY) * lpgid->idCount)))
       
   214     {
       
   215         free(lpgid);
       
   216         PrintError();
       
   217         return result;
       
   218     }
       
   219 
       
   220     free(lpgid);
       
   221 
       
   222     if (EndUpdateResource(update, FALSE) == FALSE) {
       
   223         PrintError();
       
   224         return result;
       
   225     }
       
   226 
       
   227     result = true;
       
   228     return result;
       
   229 }