mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-08 11:25:46 -04:00
使用 JNA 查询注册表 (#3913)
This commit is contained in:
parent
76ed9353bd
commit
6e05b5ee58
@ -31,18 +31,17 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.util.CacheRepository;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.platform.Architecture;
|
||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||
import org.jackhuang.hmcl.util.platform.Platform;
|
||||
import org.jackhuang.hmcl.util.platform.UnsupportedPlatformException;
|
||||
import org.jackhuang.hmcl.util.platform.windows.WinReg;
|
||||
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -357,10 +356,10 @@ public final class JavaManager {
|
||||
|
||||
switch (OperatingSystem.CURRENT_OS) {
|
||||
case WINDOWS:
|
||||
queryJavaInRegistryKey(javaRuntimes, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\");
|
||||
queryJavaInRegistryKey(javaRuntimes, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\");
|
||||
queryJavaInRegistryKey(javaRuntimes, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JRE\\");
|
||||
queryJavaInRegistryKey(javaRuntimes, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK\\");
|
||||
queryJavaInRegistryKey(javaRuntimes, WinReg.HKEY.HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
|
||||
queryJavaInRegistryKey(javaRuntimes, WinReg.HKEY.HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Development Kit");
|
||||
queryJavaInRegistryKey(javaRuntimes, WinReg.HKEY.HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\JRE");
|
||||
queryJavaInRegistryKey(javaRuntimes, WinReg.HKEY.HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\JDK");
|
||||
|
||||
searchJavaInProgramFiles(javaRuntimes, "ProgramFiles", "C:\\Program Files");
|
||||
searchJavaInProgramFiles(javaRuntimes, "ProgramFiles(x86)", "C:\\Program Files (x86)");
|
||||
@ -646,67 +645,22 @@ public final class JavaManager {
|
||||
}
|
||||
|
||||
// ==== Windows Registry Support ====
|
||||
private static void queryJavaInRegistryKey(Map<Path, JavaRuntime> javaRuntimes, String location) {
|
||||
for (String java : querySubFolders(location)) {
|
||||
if (!querySubFolders(java).contains(java + "\\MSI"))
|
||||
private static void queryJavaInRegistryKey(Map<Path, JavaRuntime> javaRuntimes, WinReg.HKEY hkey, String location) {
|
||||
WinReg reg = WinReg.INSTANCE;
|
||||
if (reg == null)
|
||||
return;
|
||||
|
||||
for (String java : reg.queryKeys(hkey, location)) {
|
||||
if (!reg.queryKeys(hkey, java).contains(java + "\\MSI"))
|
||||
continue;
|
||||
String home = queryRegisterValue(java, "JavaHome");
|
||||
if (home != null) {
|
||||
Object home = reg.queryValue(hkey, java, "JavaHome");
|
||||
if (home instanceof String) {
|
||||
try {
|
||||
tryAddJavaHome(javaRuntimes, Paths.get(home));
|
||||
tryAddJavaHome(javaRuntimes, Paths.get((String) home));
|
||||
} catch (InvalidPathException e) {
|
||||
LOG.warning("Invalid Java path in system registry: " + home);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> querySubFolders(String location) {
|
||||
List<String> res = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", "reg", "query", location});
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), OperatingSystem.NATIVE_CHARSET))) {
|
||||
for (String line; (line = reader.readLine()) != null; ) {
|
||||
if (line.startsWith(location) && !line.equals(location)) {
|
||||
res.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Failed to query sub folders of " + location, e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static String queryRegisterValue(String location, String name) {
|
||||
boolean last = false;
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", "reg", "query", location, "/v", name});
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), OperatingSystem.NATIVE_CHARSET))) {
|
||||
for (String line; (line = reader.readLine()) != null; ) {
|
||||
if (StringUtils.isNotBlank(line)) {
|
||||
if (last && line.trim().startsWith(name)) {
|
||||
int begins = line.indexOf(name);
|
||||
if (begins > 0) {
|
||||
String s2 = line.substring(begins + name.length());
|
||||
begins = s2.indexOf("REG_SZ");
|
||||
if (begins > 0) {
|
||||
return s2.substring(begins + "REG_SZ".length()).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (location.equals(line.trim())) {
|
||||
last = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Failed to query register value of " + location, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,6 @@ dependencies {
|
||||
api(libs.pci.ids)
|
||||
|
||||
compileOnlyApi(libs.jetbrains.annotations)
|
||||
|
||||
testImplementation(libs.jna.platform)
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.platform.windows;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import com.sun.jna.win32.StdCallLibrary;
|
||||
import org.jackhuang.hmcl.util.platform.NativeUtils;
|
||||
|
||||
/**
|
||||
* @author Glavo
|
||||
*/
|
||||
public interface Advapi32 extends StdCallLibrary {
|
||||
|
||||
Advapi32 INSTANCE = NativeUtils.USE_JNA && com.sun.jna.Platform.isWindows()
|
||||
? NativeUtils.load("advapi32", Advapi32.class)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regopenkeyexw">RegOpenKeyExW function</a>
|
||||
*/
|
||||
int RegOpenKeyExW(Pointer hKey, WString lpSubKey, int ulOptions, int samDesired, PointerByReference phkResult);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regclosekey">RegCloseKey function</a>
|
||||
*/
|
||||
int RegCloseKey(Pointer hKey);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regqueryvalueexw">RegQueryValueExW function</a>
|
||||
*/
|
||||
int RegQueryValueExW(Pointer hKey, WString lpValueName, Pointer lpReserved, IntByReference lpType, Pointer lpData, IntByReference lpcbData);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regenumkeyexw">RegEnumKeyExW function</a>
|
||||
*/
|
||||
int RegEnumKeyExW(Pointer hKey, int dwIndex,
|
||||
Pointer lpName, IntByReference lpcchName,
|
||||
IntByReference lpReserved,
|
||||
Pointer lpClass, IntByReference lpcchClass,
|
||||
Pointer lpftLastWriteTime);
|
||||
}
|
@ -22,9 +22,53 @@ package org.jackhuang.hmcl.util.platform.windows;
|
||||
*/
|
||||
public interface WinConstants {
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/debug/system-error-codes--0-499-
|
||||
int ERROR_SUCCESS = 0;
|
||||
int ERROR_FILE_NOT_FOUND = 2;
|
||||
int ERROR_PATH_NOT_FOUND = 3;
|
||||
int ERROR_ACCESS_DENIED = 5;
|
||||
int ERROR_INVALID_HANDLE = 6;
|
||||
int ERROR_INVALID_DATA = 13;
|
||||
int ERROR_NOT_SAME_DEVICE = 17;
|
||||
int ERROR_NOT_READY = 21;
|
||||
int ERROR_SHARING_VIOLATION = 32;
|
||||
int ERROR_FILE_EXISTS = 80;
|
||||
int ERROR_INVALID_PARAMETER = 87;
|
||||
int ERROR_DISK_FULL = 112;
|
||||
int ERROR_INSUFFICIENT_BUFFER = 122;
|
||||
int ERROR_INVALID_LEVEL = 124;
|
||||
int ERROR_DIR_NOT_ROOT = 144;
|
||||
int ERROR_DIR_NOT_EMPTY = 145;
|
||||
int ERROR_ALREADY_EXISTS = 183;
|
||||
int ERROR_MORE_DATA = 234;
|
||||
int ERROR_NO_MORE_ITEMS = 259;
|
||||
int ERROR_DIRECTORY = 267;
|
||||
int ERROR_NOTIFY_ENUM_DIR = 1022;
|
||||
int ERROR_PRIVILEGE_NOT_HELD = 1314;
|
||||
int ERROR_NONE_MAPPED = 1332;
|
||||
int ERROR_CANT_ACCESS_FILE = 1920;
|
||||
int ERROR_NOT_A_REPARSE_POINT = 4390;
|
||||
int ERROR_INVALID_REPARSE_DATA = 4392;
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/sysinfo/registry-key-security-and-access-rights
|
||||
int KEY_QUERY_VALUE = 0x0001;
|
||||
int KEY_ENUMERATE_SUB_KEYS = 0x0008;
|
||||
int KEY_READ = 0x20019;
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/sysinfo/registry-value-types
|
||||
int REG_NONE = 0;
|
||||
int REG_SZ = 1;
|
||||
int REG_EXPAND_SZ = 2;
|
||||
int REG_BINARY = 3;
|
||||
int REG_DWORD_LITTLE_ENDIAN = 4;
|
||||
int REG_DWORD_BIG_ENDIAN = 5;
|
||||
int REG_LINK = 6;
|
||||
int REG_MULTI_SZ = 7;
|
||||
int REG_RESOURCE_LIST = 8;
|
||||
int REG_FULL_RESOURCE_DESCRIPTOR = 9;
|
||||
int REG_RESOURCE_REQUIREMENTS_LIST = 10;
|
||||
int REG_QWORD_LITTLE_ENDIAN = 11;
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/sysinfo/predefined-keys
|
||||
long HKEY_CLASSES_ROOT = 0x80000000L;
|
||||
long HKEY_CURRENT_USER = 0x80000001L;
|
||||
|
@ -17,11 +17,28 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.platform.windows;
|
||||
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import org.jackhuang.hmcl.util.platform.NativeUtils;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
|
||||
/**
|
||||
* @author Glavo
|
||||
*/
|
||||
public abstract class WinReg {
|
||||
|
||||
public static final WinReg INSTANCE = NativeUtils.USE_JNA && Advapi32.INSTANCE != null
|
||||
? new JNAWinReg(Advapi32.INSTANCE) : null;
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/sysinfo/predefined-keys">Predefined Keys</a>
|
||||
*/
|
||||
@ -36,7 +53,6 @@ public abstract class WinReg {
|
||||
HKEY_CURRENT_CONFIG(0x80000005),
|
||||
HKEY_DYN_DATA(0x80000006),
|
||||
HKEY_CURRENT_USER_LOCAL_SETTINGS(0x80000007);
|
||||
|
||||
private final int value;
|
||||
|
||||
HKEY(int value) {
|
||||
@ -46,5 +62,156 @@ public abstract class WinReg {
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Pointer toPointer() {
|
||||
return Pointer.createConstant((long) value);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean exists(HKEY root, String key);
|
||||
|
||||
public abstract Object queryValue(HKEY root, String key, String valueName);
|
||||
|
||||
public abstract List<String> queryKeys(HKEY root, String key);
|
||||
|
||||
private static final class JNAWinReg extends WinReg {
|
||||
|
||||
private final Advapi32 advapi32;
|
||||
|
||||
JNAWinReg(Advapi32 advapi32) {
|
||||
this.advapi32 = advapi32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(HKEY root, String key) {
|
||||
PointerByReference phkKey = new PointerByReference();
|
||||
int status = advapi32.RegOpenKeyExW(root.toPointer(), new WString(key), 0, WinConstants.KEY_READ, phkKey);
|
||||
|
||||
if (status == WinConstants.ERROR_SUCCESS) {
|
||||
advapi32.RegCloseKey(phkKey.getValue());
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void checkLength(int expected, int actual) {
|
||||
if (expected != actual) {
|
||||
throw new IllegalStateException("Expected " + expected + " bytes, but got " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object queryValue(HKEY root, String key, String valueName) {
|
||||
PointerByReference phkKey = new PointerByReference();
|
||||
if (advapi32.RegOpenKeyExW(root.toPointer(), new WString(key), 0, WinConstants.KEY_READ, phkKey) != WinConstants.ERROR_SUCCESS)
|
||||
return null;
|
||||
|
||||
Pointer hkey = phkKey.getValue();
|
||||
try {
|
||||
IntByReference lpType = new IntByReference();
|
||||
IntByReference lpcbData = new IntByReference();
|
||||
int status = advapi32.RegQueryValueExW(hkey, new WString(valueName), null, lpType, null, lpcbData);
|
||||
if (status != WinConstants.ERROR_SUCCESS) {
|
||||
if (status == WinConstants.ERROR_FILE_NOT_FOUND)
|
||||
return null;
|
||||
else
|
||||
throw new RuntimeException("Failed to query value: " + status);
|
||||
}
|
||||
|
||||
int type = lpType.getValue();
|
||||
int cbData = lpcbData.getValue();
|
||||
|
||||
try (Memory lpData = new Memory(cbData)) {
|
||||
status = advapi32.RegQueryValueExW(hkey, new WString(valueName), null, null, lpData, lpcbData);
|
||||
if (status != WinConstants.ERROR_SUCCESS) {
|
||||
if (status == WinConstants.ERROR_FILE_NOT_FOUND)
|
||||
return null;
|
||||
else
|
||||
throw new RuntimeException("Failed to query value: " + status);
|
||||
}
|
||||
|
||||
checkLength(cbData, lpcbData.getValue());
|
||||
|
||||
switch (type) {
|
||||
case WinConstants.REG_NONE:
|
||||
case WinConstants.REG_BINARY:
|
||||
return lpData.getByteArray(0L, cbData);
|
||||
case WinConstants.REG_DWORD_LITTLE_ENDIAN:
|
||||
case WinConstants.REG_DWORD_BIG_ENDIAN: {
|
||||
checkLength(4, cbData);
|
||||
int value = lpData.getInt(0L);
|
||||
ByteOrder expectedOrder = type == WinConstants.REG_DWORD_LITTLE_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
|
||||
if (expectedOrder != ByteOrder.nativeOrder())
|
||||
value = Integer.reverseBytes(value);
|
||||
return value;
|
||||
}
|
||||
case WinConstants.REG_QWORD_LITTLE_ENDIAN: {
|
||||
checkLength(8, cbData);
|
||||
long value = lpData.getLong(0L);
|
||||
if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN)
|
||||
value = Long.reverseBytes(value);
|
||||
return value;
|
||||
}
|
||||
case WinConstants.REG_SZ:
|
||||
case WinConstants.REG_EXPAND_SZ:
|
||||
case WinConstants.REG_LINK: {
|
||||
if (cbData < 2)
|
||||
throw new RuntimeException("Illegal length: " + cbData);
|
||||
if (lpData.getChar(cbData - 2) != '\0')
|
||||
throw new RuntimeException("The string does not end with \\0");
|
||||
|
||||
return lpData.getWideString(0L);
|
||||
}
|
||||
default:
|
||||
throw new RuntimeException("Unknown reg type: " + type);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOG.warning("Failed to query value", e);
|
||||
} finally {
|
||||
advapi32.RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> queryKeys(HKEY root, String key) {
|
||||
PointerByReference phkKey = new PointerByReference();
|
||||
if (advapi32.RegOpenKeyExW(root.toPointer(), new WString(key), 0, WinConstants.KEY_READ, phkKey) != WinConstants.ERROR_SUCCESS)
|
||||
return Collections.emptyList();
|
||||
|
||||
Pointer hkey = phkKey.getValue();
|
||||
try {
|
||||
String prefix = key.endsWith("\\") ? key : key + "\\";
|
||||
ArrayList<String> res = new ArrayList<>();
|
||||
int maxKeyLength = 256;
|
||||
try (Memory lpName = new Memory(maxKeyLength * 2)) {
|
||||
IntByReference lpcchName = new IntByReference();
|
||||
int i = 0;
|
||||
|
||||
while (true) {
|
||||
lpcchName.setValue(maxKeyLength);
|
||||
int status = advapi32.RegEnumKeyExW(hkey, i, lpName, lpcchName, null, null, null, null);
|
||||
if (status == WinConstants.ERROR_SUCCESS) {
|
||||
res.add(prefix + lpName.getWideString(0L));
|
||||
i++;
|
||||
} else {
|
||||
if (status != WinConstants.ERROR_NO_MORE_ITEMS)
|
||||
LOG.warning("Failed to enum key: " + status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} catch (Throwable e) {
|
||||
LOG.warning("Failed to query keys", e);
|
||||
} finally {
|
||||
advapi32.RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -87,6 +87,4 @@ public interface WinTypes {
|
||||
"ullTotalVirtual", "ullAvailVirtual", "ullAvailExtendedVirtual");
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.platform.windows;
|
||||
|
||||
import com.sun.jna.platform.win32.Advapi32Util;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* @author Glavo
|
||||
*/
|
||||
@EnabledIf("isEnabled")
|
||||
public final class WinRegTest {
|
||||
public static boolean isEnabled() {
|
||||
return WinReg.INSTANCE != null;
|
||||
}
|
||||
|
||||
private static final com.sun.jna.platform.win32.WinReg.HKEY ROOT_KEY = com.sun.jna.platform.win32.WinReg.HKEY_CURRENT_USER;
|
||||
private static final String KEY_BASE = "Software\\JavaSoft\\Prefs\\hmcl\\test";
|
||||
private static String key;
|
||||
|
||||
private static final String[] SUBKEYS = {
|
||||
"Sub0", "Sub1", "Sub2", "Sub3"
|
||||
};
|
||||
|
||||
private static final byte[] TEST_DATA = new byte[128];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < TEST_DATA.length; i++) {
|
||||
TEST_DATA[i] = (byte) i;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
key = KEY_BASE + "\\" + UUID.randomUUID();
|
||||
if (!Advapi32Util.registryCreateKey(ROOT_KEY, key))
|
||||
throw new AssertionError("Failed to create key");
|
||||
|
||||
Advapi32Util.registrySetBinaryValue(ROOT_KEY, key, "BINARY", TEST_DATA);
|
||||
Advapi32Util.registrySetStringValue(ROOT_KEY, key, "SZ", "Hello World!");
|
||||
Advapi32Util.registrySetIntValue(ROOT_KEY, key, "DWORD", 0xCAFEBABE);
|
||||
Advapi32Util.registrySetLongValue(ROOT_KEY, key, "QWORD", 0xCAFEBABEL);
|
||||
|
||||
for (String subkey : SUBKEYS) {
|
||||
if (!Advapi32Util.registryCreateKey(ROOT_KEY, key, subkey))
|
||||
throw new AssertionError("Failed to create key");
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void cleanUp() {
|
||||
if (key != null) {
|
||||
if (!Advapi32Util.registryKeyExists(ROOT_KEY, key))
|
||||
return;
|
||||
|
||||
for (String subKey : Advapi32Util.registryGetKeys(ROOT_KEY, key))
|
||||
Advapi32Util.registryDeleteKey(ROOT_KEY, key, subKey);
|
||||
|
||||
Advapi32Util.registryDeleteKey(ROOT_KEY, key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryValue() {
|
||||
WinReg.HKEY hkey = WinReg.HKEY.HKEY_CURRENT_USER;
|
||||
WinReg reg = WinReg.INSTANCE;
|
||||
|
||||
assertArrayEquals(TEST_DATA, (byte[]) reg.queryValue(hkey, key, "BINARY"));
|
||||
assertEquals("Hello World!", reg.queryValue(hkey, key, "SZ"));
|
||||
assertEquals(0xCAFEBABE, reg.queryValue(hkey, key, "DWORD"));
|
||||
assertEquals(0xCAFEBABEL, reg.queryValue(hkey, key, "QWORD"));
|
||||
assertNull(reg.queryValue(hkey, key, "UNKNOWN"));
|
||||
assertNull(reg.queryValue(hkey, KEY_BASE + "\\" + "NOT_EXIST", "UNKNOWN"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryKeys() {
|
||||
WinReg.HKEY hkey = WinReg.HKEY.HKEY_CURRENT_USER;
|
||||
WinReg reg = WinReg.INSTANCE;
|
||||
|
||||
assertEquals(Arrays.asList(SUBKEYS).stream().map(it -> key + "\\" + it).collect(Collectors.toList()),
|
||||
reg.queryKeys(hkey, key).stream().sorted().collect(Collectors.toList()));
|
||||
for (String subkey : SUBKEYS) {
|
||||
assertEquals(Collections.emptyList(), reg.queryKeys(hkey, key + "\\" + subkey));
|
||||
}
|
||||
assertEquals(Collections.emptyList(), reg.queryKeys(hkey, key + "\\NOT_EXIST"));
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
||||
chardet = { module = "org.glavo:chardet", version.ref = "chardet" }
|
||||
twelvemonkeys-imageio-webp = { module = "com.twelvemonkeys.imageio:imageio-webp", version.ref = "twelvemonkeys" }
|
||||
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
|
||||
jna-platform = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" }
|
||||
pci-ids = { module = "org.glavo:pci-ids", version.ref = "pci-ids" }
|
||||
|
||||
[plugins]
|
||||
|
Loading…
x
Reference in New Issue
Block a user