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