blob: 99a0e108e739d434ba3dd1456d037af3e236afb4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <windows.h>
#include "vmi.h"
#include "java_util_prefs_RegistryPreferencesImpl.h"
// max buffer size in bytes
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 255
#define MAX_VALUE_DATA 16383
//map windows error code to customized error code
int
checkErrorCode (DWORD err)
{
switch (err)
{
case ERROR_ACCESS_DENIED:
return java_util_prefs_RegistryPreferencesImpl_RETURN_ACCESS_DENIED;
case ERROR_SUCCESS:
return java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS;
case ERROR_FILE_NOT_FOUND:
return java_util_prefs_RegistryPreferencesImpl_RETURN_FILE_NOT_FOUND;
default:
return java_util_prefs_RegistryPreferencesImpl_RETURN_UNKNOWN_ERROR;
}
}
// convert java byte array to c string
jbyte *
byte2str (JNIEnv * env, const jbyteArray jkey)
{
PORT_ACCESS_FROM_ENV (env);
jboolean isCopy = JNI_TRUE;
jbyte *keyByte = (*env)->GetPrimitiveArrayCritical (env, jkey, &isCopy);
const jsize keyLen = (*env)->GetArrayLength (env, jkey);
jbyte *keyStr = hymem_allocate_memory ((keyLen + 1) * sizeof (jbyte));
jsize i = 0;
if (keyByte == NULL)
{
return NULL;
}
while (i < keyLen)
keyStr[i] = keyByte[i++];
keyStr[i] = '\0';
(*env)->ReleasePrimitiveArrayCritical (env, jkey, keyByte, JNI_ABORT);
return keyStr;
}
DWORD
openRegKey (JNIEnv * env, jbyteArray jpath, jboolean jUserNode, PHKEY phKey,
REGSAM samDesired)
{
PORT_ACCESS_FROM_ENV (env);
jbyte *path = byte2str (env, jpath);
const HKEY root = jUserNode ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
DWORD err;
err = RegOpenKeyEx (root, path, 0, samDesired, phKey);
if (err == ERROR_FILE_NOT_FOUND)
{
err =
RegCreateKeyEx (root, path, 0, NULL, REG_OPTION_NON_VOLATILE,
samDesired, NULL, phKey, NULL);
}
hymem_free_memory (path);
return err;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: getValue
* Signature: ([B[BZ[I)[B
*/
JNIEXPORT jbyteArray JNICALL
Java_java_util_prefs_RegistryPreferencesImpl_getValue
(JNIEnv * env, jobject obj, jbyteArray jpath, jbyteArray jkey,
jboolean jUserNode, jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
HKEY hKey;
DWORD type = REG_SZ, errorCode;
jbyteArray result;
jboolean isCopy = JNI_TRUE;
jint *err = NULL;
jbyte *keyStr = NULL;
TCHAR *value;
DWORD dwBufLen = MAX_VALUE_DATA + 1;
int localErrorCode = 0;
err = (*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
keyStr = byte2str (env, jkey);
errorCode = openRegKey (env, jpath, jUserNode, &hKey, KEY_QUERY_VALUE);
localErrorCode = checkErrorCode (errorCode);
err[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] = localErrorCode;
if (localErrorCode !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, err, 0);
RegCloseKey (hKey);
hymem_free_memory (keyStr);
return NULL;
}
value = hymem_allocate_memory ((MAX_VALUE_DATA + 1) * sizeof (TCHAR));
errorCode = RegQueryValueEx (hKey, keyStr, 0, &type, value, &dwBufLen);
localErrorCode = checkErrorCode (errorCode);
RegCloseKey (hKey);
hymem_free_memory (keyStr);
err[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] = localErrorCode;
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, err, 0);
if (localErrorCode !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
hymem_free_memory (value);
return NULL;
}
if(dwBufLen > 0)
{
result = (*env)->NewByteArray (env, dwBufLen-1);
(*env)->SetByteArrayRegion (env, result, 0, dwBufLen-1, value);
}
else
{
result = (*env)->NewByteArray (env, 0);
}
hymem_free_memory (value);
return result;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: putValue
* Signature: ([B[B[BZ[I)V
*/
JNIEXPORT void JNICALL Java_java_util_prefs_RegistryPreferencesImpl_putValue
(JNIEnv * env, jobject obj, jbyteArray jpath, jbyteArray jkey,
jbyteArray jvalue, jboolean jUserNode, jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
DWORD err;
HKEY hKey;
jbyte *keyStr;
jbyte *valueByte;
int localErrorCode = 0;
const jint valueLen = (*env)->GetArrayLength (env, jvalue);
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_SET_VALUE);
localErrorCode = checkErrorCode (err);
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
localErrorCode;
if (localErrorCode !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return;
}
keyStr = byte2str (env, jkey);
valueByte = byte2str (env, jvalue);
err = RegSetValueEx (hKey, keyStr, 0, REG_SZ, valueByte, valueLen);
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (keyStr);
hymem_free_memory (valueByte);
RegCloseKey (hKey);
return;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: removeKey
* Signature: ([B[BZ[I)V
*/
JNIEXPORT void JNICALL Java_java_util_prefs_RegistryPreferencesImpl_removeKey
(JNIEnv * env, jobject obj, jbyteArray jpath, jbyteArray jkey,
jboolean jUserNode, jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
DWORD err;
HKEY hKey;
jbyte *keyStr;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_SET_VALUE);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return;
}
keyStr = byte2str (env, jkey);
err = RegDeleteValue (hKey, keyStr);
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (keyStr);
RegCloseKey (hKey);
return;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: keys
* Signature: ([BZ[I)[[B
*/
JNIEXPORT jobjectArray JNICALL
Java_java_util_prefs_RegistryPreferencesImpl_keys
(JNIEnv * env, jobject obj, jbyteArray jpath, jboolean jUserNode,
jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
DWORD number, size;
jclass objectClazz;
jobjectArray result;
TCHAR *value;
DWORD i = 0, j, err;
HKEY hKey;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_QUERY_VALUE);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return NULL;
}
err =
RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &number, NULL,
NULL, NULL, NULL);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
RegCloseKey (hKey);
return NULL;
}
objectClazz = (*env)->FindClass (env, "java/lang/Object");
result = (*env)->NewObjectArray (env, number, objectClazz, NULL);
value = hymem_allocate_memory ((MAX_VALUE_NAME + 1) * sizeof (TCHAR));
for (j = 0; j < number; j++)
{
value[0] = '\0';
size = MAX_VALUE_NAME + 1;
err = RegEnumValue (hKey, j, value, &size, NULL, NULL, NULL, NULL);
if (err == ERROR_SUCCESS)
{
jbyteArray key = (*env)->NewByteArray (env, strlen (value));
(*env)->SetByteArrayRegion (env, key, 0, strlen (value), value);
(*env)->SetObjectArrayElement (env, result, i++, key);
}
else
{
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
}
}
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (value);
RegCloseKey (hKey);
return result;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: removeNode
* Signature: ([B[BZ[I)V
*/
JNIEXPORT void JNICALL Java_java_util_prefs_RegistryPreferencesImpl_removeNode
(JNIEnv * env, jobject obj, jbyteArray jpath, jbyteArray jname,
jboolean jUserNode, jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
jbyte *nameStr;
HKEY hKey;
DWORD err;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_SET_VALUE);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return;
}
nameStr = byte2str (env, jname);
err = RegDeleteKey (hKey, nameStr);
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (nameStr);
RegCloseKey (hKey);
return;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: getNode
* Signature: ([B[BZ[I)Z
*/
JNIEXPORT jboolean JNICALL
Java_java_util_prefs_RegistryPreferencesImpl_getNode
(JNIEnv * env, jobject obj, jbyteArray jpath, jbyteArray jname,
jboolean jUserNode, jintArray jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
jbyte *name;
HKEY hKey, childKey;
DWORD dwDisposition, err;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_QUERY_VALUE);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return JNI_FALSE;
}
name = byte2str (env, jname);
err =
RegCreateKeyEx (hKey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &childKey, &dwDisposition);
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (name);
RegCloseKey (hKey);
RegCloseKey (childKey);
return dwDisposition == REG_CREATED_NEW_KEY;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: getChildNames
* Signature: ([BZ[I)[[B
*/
JNIEXPORT jobjectArray JNICALL
Java_java_util_prefs_RegistryPreferencesImpl_getChildNames (JNIEnv * env,
jobject obj,
jbyteArray jpath,
jboolean
jUserNode,
jintArray
jErrorCode)
{
PORT_ACCESS_FROM_ENV (env);
DWORD number, size;
jclass objectClazz = NULL;
jobjectArray result = NULL;
TCHAR *value;
DWORD i = 0, j;
HKEY hKey;
DWORD err;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_READ);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return NULL;
}
err =
RegQueryInfoKey (hKey, NULL, NULL, NULL, &number, NULL, NULL, NULL, NULL,
NULL, NULL, NULL);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
RegCloseKey (hKey);
return NULL;
}
objectClazz = (*env)->FindClass (env, "java/lang/Object");
result = (*env)->NewObjectArray (env, number, objectClazz, NULL);
value = hymem_allocate_memory ((MAX_VALUE_DATA + 1) * sizeof (TCHAR));
for (j = 0; j < number; j++)
{
value[0] = '\0';
size = MAX_VALUE_DATA + 1;
err = RegEnumKeyEx (hKey, j, value, &size, NULL, NULL, NULL, NULL);
if (err == ERROR_SUCCESS)
{
jbyteArray name = (*env)->NewByteArray (env, strlen (value));
(*env)->SetByteArrayRegion (env, name, 0, strlen (value), value);
(*env)->SetObjectArrayElement (env, result, i++, name);
}
else
{
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err);
}
}
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
hymem_free_memory (value);
RegCloseKey (hKey);
return result;
}
/*
* Class: java_util_prefs_RegistryPreferencesImpl
* Method: flushPrefs
* Signature: ([BZ[I)V
*/
JNIEXPORT void JNICALL Java_java_util_prefs_RegistryPreferencesImpl_flushPrefs
(JNIEnv * env, jobject obj, jbyteArray jpath, jboolean jUserNode,
jintArray jErrorCode)
{
HKEY hKey;
DWORD err;
jboolean isCopy = JNI_TRUE;
jint *errArray =
(*env)->GetPrimitiveArrayCritical (env, jErrorCode, &isCopy);
err = openRegKey (env, jpath, jUserNode, &hKey, KEY_ALL_ACCESS);
if ((errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (err)) !=
java_util_prefs_RegistryPreferencesImpl_RETURN_SUCCESS)
{
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray,
0);
return;
}
errArray[java_util_prefs_RegistryPreferencesImpl_ERROR_CODE] =
checkErrorCode (RegFlushKey (hKey));
(*env)->ReleasePrimitiveArrayCritical (env, jErrorCode, errArray, 0);
RegCloseKey (hKey);
return;
}