Added WindowsRegistry.
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/*
|
||||
@@ -475,4 +476,81 @@ JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions_restoreStandardHandles(JNIEnv *env, jclass target, jobject result) {
|
||||
}
|
||||
|
||||
HKEY get_key_from_ordinal(jint keyNum) {
|
||||
return keyNum == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions_getStringValue(JNIEnv *env, jclass target, jint keyNum, jstring subkey, jstring valueName, jobject result) {
|
||||
HKEY key = get_key_from_ordinal(keyNum);
|
||||
wchar_t* subkeyStr = java_to_wchar(env, subkey, result);
|
||||
wchar_t* valueNameStr = java_to_wchar(env, valueName, result);
|
||||
DWORD size = 0;
|
||||
|
||||
LONG retval = SHRegGetValueW(key, subkeyStr, valueNameStr, SRRF_RT_REG_SZ, NULL, NULL, &size);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(subkeyStr);
|
||||
free(valueNameStr);
|
||||
if (retval != ERROR_FILE_NOT_FOUND) {
|
||||
mark_failed_with_code(env, "could not determine size of registry value", retval, NULL, result);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t* value = (wchar_t*)malloc(sizeof(wchar_t) * (size+1));
|
||||
retval = SHRegGetValueW(key, subkeyStr, valueNameStr, SRRF_RT_REG_SZ, NULL, value, &size);
|
||||
free(subkeyStr);
|
||||
free(valueNameStr);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(value);
|
||||
mark_failed_with_code(env, "could not get registry value", retval, NULL, result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jstring jvalue = wchar_to_java(env, value, wcslen(value), result);
|
||||
free(value);
|
||||
|
||||
return jvalue;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions_getSubkeys(JNIEnv *env, jclass target, jint keyNum, jstring subkey, jobject subkeys, jobject result) {
|
||||
wchar_t* subkeyStr = java_to_wchar(env, subkey, result);
|
||||
jclass subkeys_class = env->GetObjectClass(subkeys);
|
||||
jmethodID method = env->GetMethodID(subkeys_class, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
HKEY key;
|
||||
LONG retval = RegOpenKeyExW(get_key_from_ordinal(keyNum), subkeyStr, 0, KEY_READ, &key);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
free(subkeyStr);
|
||||
if (retval != ERROR_FILE_NOT_FOUND) {
|
||||
mark_failed_with_code(env, "could open registry key", retval, NULL, result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD subkeyCount;
|
||||
DWORD maxSubkeyLen;
|
||||
retval = RegQueryInfoKeyW(key, NULL, NULL, NULL, &subkeyCount, &maxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could query registry key", retval, NULL, result);
|
||||
} else {
|
||||
wchar_t* keyNameStr = (wchar_t*)malloc(sizeof(wchar_t) * (maxSubkeyLen+1));
|
||||
for (int i = 0; i < subkeyCount; i++) {
|
||||
DWORD keyNameLen = maxSubkeyLen + 1;
|
||||
retval = RegEnumKeyExW(key, i, keyNameStr, &keyNameLen, NULL, NULL, NULL, NULL);
|
||||
if (retval != ERROR_SUCCESS) {
|
||||
mark_failed_with_code(env, "could enumerate registry subkey", retval, NULL, result);
|
||||
break;
|
||||
}
|
||||
env->CallVoidMethod(subkeys, method, wchar_to_java(env, keyNameStr, wcslen(keyNameStr), result));
|
||||
}
|
||||
free(keyNameStr);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
free(subkeyStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NATIVE_VERSION 15
|
||||
#define NATIVE_VERSION 16
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the given error message
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.rubygrapefruit.platform;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to query an unknown registry key or value.
|
||||
*/
|
||||
public class MissingRegistryEntryException extends NativeException {
|
||||
public MissingRegistryEntryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.rubygrapefruit.platform;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ThreadSafe
|
||||
public interface WindowsRegistry extends NativeIntegration {
|
||||
public enum Key {
|
||||
HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registry key value as a String.
|
||||
*
|
||||
* @throws NativeException On failure.
|
||||
* @throws MissingRegistryEntryException When the requested key or value does not exist.
|
||||
*/
|
||||
String getStringValue(Key key, String subkey, String value) throws NativeException;
|
||||
|
||||
/**
|
||||
* Lists the subkeys of a registry key.
|
||||
*
|
||||
* @throws NativeException On failure.
|
||||
* @throws MissingRegistryEntryException When the requested key does not exist.
|
||||
*/
|
||||
List<String> getSubkeys(Key key, String subkey) throws NativeException;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.rubygrapefruit.platform.internal;
|
||||
|
||||
import net.rubygrapefruit.platform.MissingRegistryEntryException;
|
||||
import net.rubygrapefruit.platform.NativeException;
|
||||
import net.rubygrapefruit.platform.WindowsRegistry;
|
||||
import net.rubygrapefruit.platform.internal.jni.WindowsRegistryFunctions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultWindowsRegistry implements WindowsRegistry {
|
||||
public String getStringValue(Key key, String subkey, String valueName) throws NativeException {
|
||||
FunctionResult result = new FunctionResult();
|
||||
String value = WindowsRegistryFunctions.getStringValue(key.ordinal(), subkey, valueName, result);
|
||||
if (result.isFailed()) {
|
||||
throw new NativeException(String.format("Could not get value '%s' of registry key '%s\\%s': %s", valueName,
|
||||
key,
|
||||
subkey, result.getMessage()));
|
||||
}
|
||||
if (value == null) {
|
||||
throw new MissingRegistryEntryException(String.format(
|
||||
"Could not get value '%s' of registry key '%s\\%s' as it does not exist.", valueName, key, subkey));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public List<String> getSubkeys(Key key, String subkey) throws NativeException {
|
||||
FunctionResult result = new FunctionResult();
|
||||
ArrayList<String> subkeys = new ArrayList<String>();
|
||||
boolean found = WindowsRegistryFunctions.getSubkeys(key.ordinal(), subkey, subkeys, result);
|
||||
if (result.isFailed()) {
|
||||
throw new NativeException(String.format("Could not get subkeys of registry key '%s\\%s': %s", key,
|
||||
subkey, result.getMessage()));
|
||||
}
|
||||
if (!found) {
|
||||
throw new MissingRegistryEntryException(String.format(
|
||||
"Could not list the subkeys of registry key '%s\\%s' as it does not exist.", key, subkey));
|
||||
}
|
||||
return subkeys;
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,9 @@ public abstract class Platform {
|
||||
if (type.equals(FileSystems.class)) {
|
||||
return type.cast(new PosixFileSystems());
|
||||
}
|
||||
if (type.equals(WindowsRegistry.class)) {
|
||||
return type.cast(new DefaultWindowsRegistry());
|
||||
}
|
||||
return super.get(type, nativeLibraryLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.rubygrapefruit.platform.internal.FunctionResult;
|
||||
import net.rubygrapefruit.platform.internal.MutableSystemInfo;
|
||||
|
||||
public class NativeLibraryFunctions {
|
||||
public static final int VERSION = 15;
|
||||
public static final int VERSION = 16;
|
||||
|
||||
public static native int getVersion();
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.rubygrapefruit.platform.internal.jni;
|
||||
|
||||
import net.rubygrapefruit.platform.internal.FunctionResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WindowsRegistryFunctions {
|
||||
// Returns null for unknown key or value
|
||||
public static native String getStringValue(int key, String subkey, String value, FunctionResult result);
|
||||
|
||||
// Returns false for unknown key
|
||||
public static native boolean getSubkeys(int key, String subkey, List<String> subkeys, FunctionResult result);
|
||||
}
|
||||
Reference in New Issue
Block a user