1 /*
   2  * Copyright (c) 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 <Windows.h>
  27 #include <strsafe.h>
  28 #include <tchar.h>
  29 #include <jni.h>
  30 
  31 #include "Utils.h"
  32 
  33 // Max value name size per MSDN plus NULL
  34 #define VALUE_NAME_SIZE 16384
  35 
  36 #ifdef __cplusplus
  37 extern "C" {
  38 #endif
  39 #undef jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE
  40 #define jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE 1L
  41 
  42     /*
  43      * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
  44      * Method:    readDwordValue
  45      * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
  46      */
  47     JNIEXPORT jint JNICALL
  48             Java_jdk_incubator_jpackage_internal_WindowsRegistry_readDwordValue(
  49             JNIEnv *pEnv, jclass c, jint key, jstring jSubKey,
  50             jstring jValue, jint defaultValue) {
  51         jint jResult = defaultValue;
  52 
  53         if (key != jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
  54             return jResult;
  55         }
  56 
  57         wstring subKey = GetStringFromJString(pEnv, jSubKey);
  58         wstring value = GetStringFromJString(pEnv, jValue);
  59 
  60         HKEY hSubKey = NULL;
  61         LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
  62                 KEY_QUERY_VALUE, &hSubKey);
  63         if (status == ERROR_SUCCESS) {
  64             DWORD dwValue = 0;
  65             DWORD cbData = sizeof (DWORD);
  66             status = RegQueryValueEx(hSubKey, value.c_str(), NULL, NULL,
  67                     (LPBYTE) & dwValue, &cbData);
  68             if (status == ERROR_SUCCESS) {
  69                 jResult = (jint) dwValue;
  70             }
  71 
  72             RegCloseKey(hSubKey);
  73         }
  74 
  75         return jResult;
  76     }
  77 
  78     /*
  79      * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
  80      * Method:    openRegistryKey
  81      * Signature: (ILjava/lang/String;)J
  82      */
  83     JNIEXPORT jlong JNICALL
  84             Java_jdk_incubator_jpackage_internal_WindowsRegistry_openRegistryKey(
  85             JNIEnv *pEnv, jclass c, jint key, jstring jSubKey) {
  86         if (key != jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
  87             return 0;
  88         }
  89 
  90         wstring subKey = GetStringFromJString(pEnv, jSubKey);
  91         HKEY hSubKey = NULL;
  92         LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
  93                 KEY_QUERY_VALUE, &hSubKey);
  94         if (status == ERROR_SUCCESS) {
  95             return (jlong)hSubKey;
  96         }
  97 
  98         return 0;
  99     }
 100 
 101     /*
 102      * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
 103      * Method:    enumRegistryValue
 104      * Signature: (JI)Ljava/lang/String;
 105      */
 106     JNIEXPORT jstring JNICALL
 107             Java_jdk_incubator_jpackage_internal_WindowsRegistry_enumRegistryValue(
 108             JNIEnv *pEnv, jclass c, jlong lKey, jint jIndex) {
 109         HKEY hKey = (HKEY)lKey;
 110         TCHAR valueName[VALUE_NAME_SIZE] = {0}; // Max size per MSDN plus NULL
 111         DWORD cchValueName = VALUE_NAME_SIZE;
 112         LSTATUS status = RegEnumValue(hKey, (DWORD)jIndex, valueName,
 113                 &cchValueName, NULL, NULL, NULL, NULL);
 114         if (status == ERROR_SUCCESS) {
 115             size_t chLength = 0;
 116             if (StringCchLength(valueName, VALUE_NAME_SIZE, &chLength)
 117                     == S_OK) {
 118                 return GetJStringFromString(pEnv, valueName, (jsize)chLength);
 119             }
 120         }
 121 
 122         return NULL;
 123     }
 124 
 125     /*
 126      * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
 127      * Method:    closeRegistryKey
 128      * Signature: (J)V
 129      */
 130     JNIEXPORT void JNICALL
 131             Java_jdk_incubator_jpackage_internal_WindowsRegistry_closeRegistryKey(
 132             JNIEnv *pEnc, jclass c, jlong lKey) {
 133         HKEY hKey = (HKEY)lKey;
 134         RegCloseKey(hKey);
 135     }
 136 
 137     /*
 138      * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
 139      * Method:    comparePaths
 140      * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
 141      */
 142      JNIEXPORT jboolean JNICALL
 143             Java_jdk_incubator_jpackage_internal_WindowsRegistry_comparePaths(
 144             JNIEnv *pEnv, jclass c, jstring jPath1, jstring jPath2) {
 145          wstring path1 = GetStringFromJString(pEnv, jPath1);
 146          wstring path2 = GetStringFromJString(pEnv, jPath2);
 147 
 148          path1 = GetLongPath(path1);
 149          path2 = GetLongPath(path2);
 150 
 151          if (path1.length() == 0 || path2.length() == 0) {
 152              return JNI_FALSE;
 153          }
 154 
 155          if (path1.length() != path2.length()) {
 156              return JNI_FALSE;
 157          }
 158 
 159          if (_tcsnicmp(path1.c_str(), path2.c_str(), path1.length()) == 0) {
 160              return JNI_TRUE;
 161          }
 162 
 163          return JNI_FALSE;
 164      }
 165 
 166 #ifdef __cplusplus
 167 }
 168 #endif