| /* 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. |
| */ |
| |
| /* |
| * |
| * @author Mladen Turk |
| * @version $Revision$, $Date$ |
| */ |
| |
| #ifndef _WIN32_WINNT |
| #define _WIN32_WINNT 0x0500 |
| #endif |
| #include <winsock2.h> |
| #include <mswsock.h> |
| #include <ws2tcpip.h> |
| #include <shlwapi.h> |
| |
| #include "apr.h" |
| #include "apr_pools.h" |
| #include "apr_arch_misc.h" /* for apr_os_level */ |
| #include "apr_arch_atime.h" /* for FileTimeToAprTime */ |
| |
| #include "tcn.h" |
| |
| #define SAFE_CLOSE_KEY(k) \ |
| if ((k) != NULL && (k) != INVALID_HANDLE_VALUE) { \ |
| RegCloseKey((k)); \ |
| (k) = NULL; \ |
| } |
| |
| typedef struct { |
| apr_pool_t *pool; |
| HKEY root; |
| HKEY key; |
| } tcn_nt_registry_t; |
| |
| |
| #define TCN_HKEY_CLASSES_ROOT 1 |
| #define TCN_HKEY_CURRENT_CONFIG 2 |
| #define TCN_HKEY_CURRENT_USER 3 |
| #define TCN_HKEY_LOCAL_MACHINE 4 |
| #define TCN_HKEY_USERS 5 |
| |
| static const struct { |
| HKEY k; |
| } TCN_KEYS[] = { |
| INVALID_HANDLE_VALUE, |
| HKEY_CLASSES_ROOT, |
| HKEY_CURRENT_CONFIG, |
| HKEY_CURRENT_USER, |
| HKEY_LOCAL_MACHINE, |
| HKEY_USERS, |
| INVALID_HANDLE_VALUE |
| }; |
| |
| #define TCN_KEY_ALL_ACCESS 0x0001 |
| #define TCN_KEY_CREATE_LINK 0x0002 |
| #define TCN_KEY_CREATE_SUB_KEY 0x0004 |
| #define TCN_KEY_ENUMERATE_SUB_KEYS 0x0008 |
| #define TCN_KEY_EXECUTE 0x0010 |
| #define TCN_KEY_NOTIFY 0x0020 |
| #define TCN_KEY_QUERY_VALUE 0x0040 |
| #define TCN_KEY_READ 0x0080 |
| #define TCN_KEY_SET_VALUE 0x0100 |
| #define TCN_KEY_WOW64_64KEY 0x0200 |
| #define TCN_KEY_WOW64_32KEY 0x0400 |
| #define TCN_KEY_WRITE 0x0800 |
| |
| #define TCN_REGSAM(s, x) \ |
| s = 0; \ |
| if (x & TCN_KEY_ALL_ACCESS) \ |
| s |= KEY_ALL_ACCESS; \ |
| if (x & TCN_KEY_CREATE_LINK) \ |
| s |= KEY_CREATE_LINK; \ |
| if (x & TCN_KEY_CREATE_SUB_KEY) \ |
| s |= KEY_CREATE_SUB_KEY; \ |
| if (x & TCN_KEY_ENUMERATE_SUB_KEYS) \ |
| s |= KEY_ENUMERATE_SUB_KEYS; \ |
| if (x & TCN_KEY_EXECUTE) \ |
| s |= KEY_EXECUTE; \ |
| if (x & TCN_KEY_NOTIFY) \ |
| s |= KEY_NOTIFY; \ |
| if (x & TCN_KEY_READ) \ |
| s |= KEY_READ; \ |
| if (x & TCN_KEY_SET_VALUE) \ |
| s |= KEY_SET_VALUE; \ |
| if (x & TCN_KEY_WOW64_64KEY) \ |
| s |= KEY_WOW64_64KEY; \ |
| if (x & TCN_KEY_WOW64_32KEY) \ |
| s |= KEY_WOW64_32KEY; \ |
| if (x & TCN_KEY_WRITE) \ |
| s |= KEY_WRITE |
| |
| #define TCN_REG_BINARY 1 |
| #define TCN_REG_DWORD 2 |
| #define TCN_REG_EXPAND_SZ 3 |
| #define TCN_REG_MULTI_SZ 4 |
| #define TCN_REG_QWORD 5 |
| #define TCN_REG_SZ 6 |
| |
| static const struct { |
| DWORD t; |
| } TCN_REGTYPES[] = { |
| REG_NONE, |
| REG_BINARY, |
| REG_DWORD, |
| REG_EXPAND_SZ, |
| REG_MULTI_SZ, |
| REG_QWORD, |
| REG_SZ, |
| REG_NONE |
| }; |
| |
| static apr_status_t registry_cleanup(void *data) |
| { |
| tcn_nt_registry_t *reg = (tcn_nt_registry_t *)data; |
| |
| if (reg) { |
| SAFE_CLOSE_KEY(reg->key); |
| } |
| return APR_SUCCESS; |
| } |
| |
| TCN_IMPLEMENT_CALL(jlong, Registry, create)(TCN_STDARGS, jint root, jstring name, |
| jint sam, jlong pool) |
| { |
| apr_pool_t *p = J2P(pool, apr_pool_t *); |
| tcn_nt_registry_t *reg = NULL; |
| TCN_ALLOC_WSTRING(name); |
| HKEY key; |
| LONG rc; |
| REGSAM s; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(pool != 0); |
| |
| if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { |
| tcn_ThrowException(e, "Invalid Registry Root Key"); |
| goto cleanup; |
| } |
| if (sam < TCN_KEY_ALL_ACCESS || root > TCN_KEY_WRITE) { |
| tcn_ThrowException(e, "Invalid Registry Key Security"); |
| goto cleanup; |
| } |
| reg = (tcn_nt_registry_t *)apr_palloc(p, sizeof(tcn_nt_registry_t)); |
| reg->pool = p; |
| reg->root = TCN_KEYS[root].k; |
| reg->key = NULL; |
| TCN_INIT_WSTRING(name); |
| TCN_REGSAM(s, sam); |
| rc = RegCreateKeyExW(reg->root, J2W(name), 0, NULL, REG_OPTION_NON_VOLATILE, |
| s, NULL, &key, NULL); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| reg->key = key; |
| apr_pool_cleanup_register(p, (const void *)reg, |
| registry_cleanup, |
| apr_pool_cleanup_null); |
| |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return P2J(reg); |
| } |
| |
| TCN_IMPLEMENT_CALL(jlong, Registry, open)(TCN_STDARGS, jint root, jstring name, |
| jint sam, jlong pool) |
| { |
| apr_pool_t *p = J2P(pool, apr_pool_t *); |
| tcn_nt_registry_t *reg = NULL; |
| TCN_ALLOC_WSTRING(name); |
| HKEY key; |
| LONG rc; |
| REGSAM s; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(pool != 0); |
| |
| if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { |
| tcn_ThrowException(e, "Invalid Registry Root Key"); |
| goto cleanup; |
| } |
| if (sam < TCN_KEY_ALL_ACCESS || root > TCN_KEY_WRITE) { |
| tcn_ThrowException(e, "Invalid Registry Key Security"); |
| goto cleanup; |
| } |
| reg = (tcn_nt_registry_t *)apr_palloc(p, sizeof(tcn_nt_registry_t)); |
| reg->pool = p; |
| reg->root = TCN_KEYS[root].k; |
| reg->key = NULL; |
| TCN_INIT_WSTRING(name); |
| TCN_REGSAM(s, sam); |
| rc = RegOpenKeyExW(reg->root, J2W(name), 0, s, &key); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| reg->key = key; |
| apr_pool_cleanup_register(p, (const void *)reg, |
| registry_cleanup, |
| apr_pool_cleanup_null); |
| |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return P2J(reg); |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, close)(TCN_STDARGS, jlong reg) |
| { |
| tcn_nt_registry_t *r = J2P(reg, tcn_nt_registry_t *); |
| UNREFERENCED_STDARGS; |
| |
| TCN_ASSERT(reg != 0); |
| |
| registry_cleanup(r); |
| apr_pool_cleanup_kill(r->pool, r, registry_cleanup); |
| return APR_SUCCESS; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, getType)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD v; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &v, NULL, NULL); |
| if (rc != ERROR_SUCCESS) |
| v = -rc; |
| TCN_FREE_WSTRING(name); |
| switch (v) { |
| case REG_BINARY: |
| v = TCN_REG_BINARY; |
| break; |
| case REG_DWORD: |
| v = TCN_REG_DWORD; |
| break; |
| case REG_EXPAND_SZ: |
| v = TCN_REG_EXPAND_SZ; |
| break; |
| case REG_MULTI_SZ: |
| v = TCN_REG_MULTI_SZ; |
| break; |
| case REG_QWORD: |
| v = TCN_REG_QWORD; |
| break; |
| case REG_SZ: |
| v = TCN_REG_SZ; |
| break; |
| case REG_DWORD_BIG_ENDIAN: |
| v = 0; |
| break; |
| } |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, getSize)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD v; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, NULL, &v); |
| if (rc != ERROR_SUCCESS) |
| v = -rc; |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, getValueI)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD t, l; |
| DWORD v = 0; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| if (t == REG_DWORD) { |
| l = sizeof(DWORD); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&v, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| } |
| else if (t == REG_SZ || t == REG_BINARY || |
| t == REG_MULTI_SZ || t == REG_EXPAND_SZ) |
| v = l; |
| else { |
| v = 0; |
| tcn_ThrowException(e, "Unable to convert the value to integer"); |
| } |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jlong, Registry, getValueJ)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD t, l; |
| UINT64 v = 0; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| if (t == REG_DWORD) { |
| DWORD tv; |
| l = sizeof(DWORD); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&tv, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| v = tv; |
| } |
| else if (t == REG_QWORD) { |
| l = sizeof(UINT64); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&v, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| } |
| else if (t == REG_SZ || t == REG_BINARY || |
| t == REG_MULTI_SZ || t == REG_EXPAND_SZ) |
| v = l; |
| else { |
| v = 0; |
| tcn_ThrowException(e, "Unable to convert the value to long"); |
| } |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jstring, Registry, getValueS)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD t, l; |
| jstring v = NULL; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| if (t == REG_SZ || t == REG_EXPAND_SZ) { |
| jchar *vw = (jchar *)malloc(l); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)vw, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| free(vw); |
| goto cleanup; |
| } |
| v = (*e)->NewString((e), vw, wcslen(vw)); |
| free(vw); |
| } |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jbyteArray, Registry, getValueB)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD t, l; |
| jbyteArray v = NULL; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| if (t == REG_BINARY) { |
| BYTE *b = (BYTE *)malloc(l); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, b, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| free(b); |
| goto cleanup; |
| } |
| v = tcn_new_arrayb(e, b, l); |
| free(b); |
| } |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| static jsize get_multi_sz_count(LPCWSTR str) |
| { |
| LPCWSTR p = str; |
| jsize cnt = 0; |
| for ( ; p && *p; p++) { |
| cnt++; |
| while (*p) |
| p++; |
| } |
| return cnt; |
| } |
| |
| TCN_IMPLEMENT_CALL(jobjectArray, Registry, getValueA)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD t, l; |
| jobjectArray v = NULL; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| if (t == REG_MULTI_SZ) { |
| jsize cnt = 0; |
| jchar *p; |
| jchar *vw = (jchar *)malloc(l); |
| rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)vw, &l); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| free(vw); |
| goto cleanup; |
| } |
| cnt = get_multi_sz_count(vw); |
| if (cnt) { |
| jsize idx = 0; |
| v = tcn_new_arrays(e, cnt); |
| for (p = vw ; p && *p; p++) { |
| jstring s; |
| jchar *b = p; |
| while (*p) |
| p++; |
| s = (*e)->NewString((e), b, (jsize)(p - b)); |
| (*e)->SetObjectArrayElement((e), v, idx++, s); |
| } |
| } |
| free(vw); |
| } |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueI)(TCN_STDARGS, jlong key, |
| jstring name, jint val) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| DWORD v = (DWORD)val; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_DWORD, (CONST BYTE *)&v, sizeof(DWORD)); |
| TCN_FREE_WSTRING(name); |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueJ)(TCN_STDARGS, jlong key, |
| jstring name, jlong val) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| UINT64 v = (UINT64)val; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_QWORD, (CONST BYTE *)&v, sizeof(UINT64)); |
| TCN_FREE_WSTRING(name); |
| return rc; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueS)(TCN_STDARGS, jlong key, |
| jstring name, jstring val) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| TCN_ALLOC_WSTRING(val); |
| LONG rc; |
| DWORD len; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| TCN_INIT_WSTRING(val); |
| len = wcslen(J2W(val)); |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_SZ, |
| (CONST BYTE *)J2W(val), (len + 1) * 2); |
| TCN_FREE_WSTRING(name); |
| TCN_FREE_WSTRING(val); |
| return rc; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueE)(TCN_STDARGS, jlong key, |
| jstring name, jstring val) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| TCN_ALLOC_WSTRING(val); |
| LONG rc; |
| DWORD len; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| TCN_INIT_WSTRING(val); |
| len = wcslen(J2W(val)); |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_EXPAND_SZ, |
| (CONST BYTE *)J2W(val), (len + 1) * 2); |
| TCN_FREE_WSTRING(name); |
| TCN_FREE_WSTRING(val); |
| return rc; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueA)(TCN_STDARGS, jlong key, |
| jstring name, |
| jobjectArray vals) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| LONG rc; |
| jsize i, len; |
| jsize sl = 0; |
| jchar *msz, *p; |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| TCN_INIT_WSTRING(name); |
| len = (*e)->GetArrayLength((e), vals); |
| for (i = 0; i < len; i++) { |
| jstring s = (jstring)(*e)->GetObjectArrayElement((e), vals, i); |
| sl += (*e)->GetStringLength((e), s) + 1; |
| } |
| sl = (sl + 1) * 2; |
| p = msz = (jchar *)calloc(1, sl); |
| for (i = 0; i < len; i++) { |
| jsize l; |
| jstring s = (jstring)(*e)->GetObjectArrayElement((e), vals, i); |
| l = (*e)->GetStringLength((e), s); |
| wcsncpy(p, (*e)->GetStringChars(e, s, 0), l); |
| p += l + 1; |
| } |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_MULTI_SZ, |
| (CONST BYTE *)msz, sl); |
| TCN_FREE_WSTRING(name); |
| free(msz); |
| return rc; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, setValueB)(TCN_STDARGS, jlong key, |
| jstring name, |
| jbyteArray val) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| TCN_ALLOC_WSTRING(name); |
| jsize nbytes = (*e)->GetArrayLength(e, val); |
| jbyte *bytes = (*e)->GetByteArrayElements(e, val, NULL); |
| LONG rc; |
| |
| rc = RegSetValueExW(k->key, J2W(name), 0, REG_BINARY, |
| bytes, (DWORD)nbytes); |
| (*e)->ReleaseByteArrayElements(e, val, bytes, JNI_ABORT); |
| TCN_FREE_WSTRING(name); |
| return rc; |
| } |
| |
| #define MAX_VALUE_NAME 4096 |
| |
| TCN_IMPLEMENT_CALL(jobjectArray, Registry, enumKeys)(TCN_STDARGS, jlong key) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| LONG rc; |
| jobjectArray v = NULL; |
| jsize cnt = 0; |
| |
| WCHAR achKey[MAX_PATH]; |
| WCHAR achClass[MAX_PATH] = L""; |
| DWORD cchClassName = MAX_PATH; |
| DWORD cSubKeys; |
| DWORD cbMaxSubKey; |
| DWORD cchMaxClass; |
| DWORD cValues; |
| DWORD cchMaxValue; |
| DWORD cbMaxValueData; |
| DWORD cbSecurityDescriptor; |
| FILETIME ftLastWriteTime; |
| |
| DWORD cchValue = MAX_VALUE_NAME; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| rc = RegQueryInfoKeyW(k->key, |
| achClass, |
| &cchClassName, |
| NULL, |
| &cSubKeys, |
| &cbMaxSubKey, |
| &cchMaxClass, |
| &cValues, |
| &cchMaxValue, |
| &cbMaxValueData, |
| &cbSecurityDescriptor, |
| &ftLastWriteTime); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| cnt = cSubKeys; |
| if (cnt) { |
| jsize idx = 0; |
| v = tcn_new_arrays(e, cnt); |
| for (idx = 0; idx < cnt; idx++) { |
| jstring s; |
| DWORD achKeyLen = MAX_PATH; |
| rc = RegEnumKeyExW(k->key, |
| idx, |
| achKey, |
| &achKeyLen, |
| NULL, |
| NULL, |
| NULL, |
| &ftLastWriteTime); |
| if (rc == (DWORD)ERROR_SUCCESS) { |
| s = (*e)->NewString((e), achKey, wcslen(achKey)); |
| (*e)->SetObjectArrayElement((e), v, idx, s); |
| } |
| } |
| } |
| cleanup: |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jobjectArray, Registry, enumValues)(TCN_STDARGS, jlong key) |
| { |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| LONG rc; |
| jobjectArray v = NULL; |
| jsize cnt = 0; |
| |
| WCHAR achClass[MAX_PATH] = L""; |
| DWORD cchClassName = MAX_PATH; |
| DWORD cSubKeys; |
| DWORD cbMaxSubKey; |
| DWORD cchMaxClass; |
| DWORD cValues; |
| DWORD cchMaxValue; |
| DWORD cbMaxValueData; |
| DWORD cbSecurityDescriptor; |
| FILETIME ftLastWriteTime; |
| |
| WCHAR achValue[MAX_VALUE_NAME]; |
| DWORD cchValue = MAX_VALUE_NAME; |
| |
| UNREFERENCED(o); |
| TCN_ASSERT(key != 0); |
| /* Get the class name and the value count. */ |
| rc = RegQueryInfoKeyW(k->key, |
| achClass, |
| &cchClassName, |
| NULL, |
| &cSubKeys, |
| &cbMaxSubKey, |
| &cchMaxClass, |
| &cValues, |
| &cchMaxValue, |
| &cbMaxValueData, |
| &cbSecurityDescriptor, |
| &ftLastWriteTime); |
| if (rc != ERROR_SUCCESS) { |
| tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); |
| goto cleanup; |
| } |
| cnt = cValues; |
| if (cnt) { |
| jsize idx = 0; |
| v = tcn_new_arrays(e, cnt); |
| for (idx = 0; idx < cnt; idx++) { |
| jstring s; |
| cchValue = MAX_VALUE_NAME; |
| achValue[0] = '\0'; |
| rc = RegEnumValueW(k->key, idx, |
| achValue, |
| &cchValue, |
| NULL, |
| NULL, // &dwType, |
| NULL, // &bData, |
| NULL); // &bcData |
| if (rc == (DWORD)ERROR_SUCCESS) { |
| s = (*e)->NewString((e), achValue, wcslen(achValue)); |
| (*e)->SetObjectArrayElement((e), v, idx, s); |
| } |
| } |
| } |
| cleanup: |
| return v; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, deleteKey)(TCN_STDARGS, jint root, jstring name, |
| jboolean only_if_empty) |
| { |
| DWORD rv; |
| TCN_ALLOC_WSTRING(name); |
| |
| UNREFERENCED(o); |
| if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { |
| rv = EBADF; |
| goto cleanup; |
| } |
| if (only_if_empty) |
| rv = SHDeleteEmptyKeyW(TCN_KEYS[root].k, J2W(name)); |
| else |
| rv = SHDeleteKeyW(TCN_KEYS[root].k, J2W(name)); |
| cleanup: |
| TCN_FREE_WSTRING(name); |
| return rv; |
| } |
| |
| TCN_IMPLEMENT_CALL(jint, Registry, deleteValue)(TCN_STDARGS, jlong key, |
| jstring name) |
| { |
| LONG rv; |
| TCN_ALLOC_WSTRING(name); |
| tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); |
| |
| UNREFERENCED(o); |
| rv = RegDeleteValueW(k->key, J2W(name)); |
| TCN_FREE_WSTRING(name); |
| return (jint)rv; |
| } |