1 /*
   2  * Copyright (c) 2018, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.IOException;
  25 import java.nio.file.Path;
  26 import java.io.InputStream;
  27 import java.io.FileInputStream;
  28 
  29 /*
  30  * @test
  31  * @summary jpackage create image win console test
  32  * @library ../helpers
  33  * @library ../share
  34  * @build JPackageHelper
  35  * @build JPackagePath
  36  * @build Base
  37  * @requires (os.family == "windows")
  38  * @modules jdk.jpackage
  39  * @run main/othervm -Xmx512m WinConsoleTest
  40  */
  41 
  42 public class WinConsoleTest {
  43     private static final String NAME = "test";
  44     private static final String OUTPUT = "output";
  45     private static final String OUTPUT_WIN_CONSOLE = "outputWinConsole";
  46     private static final int BUFFER_SIZE = 512;
  47     private static final int GUI_SUBSYSTEM = 2;
  48     private static final int CONSOLE_SUBSYSTEM = 3;
  49 
  50     private static final String [] CMD = {
  51         "--input", "input",
  52         "--output", OUTPUT,
  53         "--name", NAME,
  54         "--main-jar", "hello.jar",
  55         "--main-class", "Hello",
  56     };
  57 
  58     private static final String [] CMD_WIN_CONSOLE = {
  59         "--input", "input",
  60         "--output", OUTPUT_WIN_CONSOLE,
  61         "--name", NAME,
  62         "--main-jar", "hello.jar",
  63         "--main-class", "Hello",
  64         "--win-console"
  65     };
  66 
  67     private static void checkSubsystem(boolean console) throws Exception {
  68         Path path = Path.of(console ? OUTPUT_WIN_CONSOLE : OUTPUT,
  69                 NAME, NAME + ".exe");
  70 
  71         System.out.println("validate path: " + path.toString());
  72         Base.validate(path.toString());
  73 
  74         try (InputStream inputStream = new FileInputStream(path.toString())) {
  75             byte [] bytes = new byte[BUFFER_SIZE];
  76             if (inputStream.read(bytes) != BUFFER_SIZE) {
  77                 throw new AssertionError("Wrong number of bytes read");
  78             }
  79 
  80             // Check PE header for console or Win GUI app.
  81             // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_image_nt_headers
  82             for (int i = 0;  i < (bytes.length - 4); i++) {
  83                 if (bytes[i] == 0x50 && bytes[i + 1] == 0x45 &&
  84                         bytes[i + 2] == 0x0 && bytes[i + 3] == 0x0) {
  85 
  86                     // Signature, File Header and subsystem offset.
  87                     i = i + 4 + 20 + 68;
  88                     byte subsystem = bytes[i];
  89                     if (console) {
  90                         if (subsystem != CONSOLE_SUBSYSTEM) {
  91                             throw new AssertionError("Unexpected subsystem: "
  92                                     + subsystem);
  93                         } else {
  94                             return;
  95                         }
  96                     } else {
  97                         if (subsystem != GUI_SUBSYSTEM) {
  98                             throw new AssertionError("Unexpected subsystem: "
  99                                     + subsystem);
 100                         } else {
 101                             return;
 102                         }
 103                     }
 104                 }
 105             }
 106         }
 107 
 108         throw new AssertionError("Unable to verify PE header");
 109     }
 110 
 111     private static void validate() throws Exception {
 112         checkSubsystem(false);
 113         checkSubsystem(true);
 114     }
 115 
 116     private static void testCreateAppImage(String [] cmd) throws Exception {
 117         JPackageHelper.executeCLI(true, cmd);
 118     }
 119 
 120     private static void testCreateAppImageToolProvider(String [] cmd)
 121                 throws Exception {
 122         JPackageHelper.executeToolProvider(true, cmd);
 123     }
 124 
 125     public static void main(String[] args) throws Exception {
 126         JPackageHelper.createHelloImageJar();
 127         testCreateAppImage(CMD);
 128         testCreateAppImage(CMD_WIN_CONSOLE);
 129         validate();
 130         JPackageHelper.deleteOutputFolder(OUTPUT);
 131         JPackageHelper.deleteOutputFolder(OUTPUT_WIN_CONSOLE);
 132         testCreateAppImageToolProvider(CMD);
 133         testCreateAppImageToolProvider(CMD_WIN_CONSOLE);
 134         validate();
 135     }
 136 }