| OLD | NEW |
| (Empty) |
| 1 #ifdef _WINDOWS | |
| 2 | |
| 3 /* Licensed to the Apache Software Foundation (ASF) under one or more | |
| 4 * contributor license agreements. See the NOTICE file distributed with | |
| 5 * this work for additional information regarding copyright ownership. | |
| 6 * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 7 * (the "License"); you may not use this file except in compliance with | |
| 8 * the License. You may obtain a copy of the License at | |
| 9 * | |
| 10 * http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 * | |
| 12 * Unless required by applicable law or agreed to in writing, software | |
| 13 * distributed under the License is distributed on an "AS IS" BASIS, | |
| 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 15 * See the License for the specific language governing permissions and | |
| 16 * limitations under the License. | |
| 17 */ | |
| 18 | |
| 19 /* | |
| 20 * | |
| 21 * @author Mladen Turk | |
| 22 * @version $Id: registry.c 1442587 2013-02-05 13:49:48Z rjung $ | |
| 23 */ | |
| 24 | |
| 25 #ifndef _WIN32_WINNT | |
| 26 #define _WIN32_WINNT 0x0501 | |
| 27 #endif | |
| 28 #include <winsock2.h> | |
| 29 #include <mswsock.h> | |
| 30 #include <ws2tcpip.h> | |
| 31 #include <shlwapi.h> | |
| 32 #include <tlhelp32.h> | |
| 33 | |
| 34 #include "apr.h" | |
| 35 #include "apr_pools.h" | |
| 36 #include "apr_arch_misc.h" /* for apr_os_level */ | |
| 37 #include "apr_arch_atime.h" /* for FileTimeToAprTime */ | |
| 38 | |
| 39 #include "tcn.h" | |
| 40 | |
| 41 #define SAFE_CLOSE_KEY(k) \ | |
| 42 if ((k) != NULL && (k) != INVALID_HANDLE_VALUE) { \ | |
| 43 RegCloseKey((k)); \ | |
| 44 (k) = NULL; \ | |
| 45 } | |
| 46 | |
| 47 typedef struct { | |
| 48 apr_pool_t *pool; | |
| 49 HKEY root; | |
| 50 HKEY key; | |
| 51 } tcn_nt_registry_t; | |
| 52 | |
| 53 | |
| 54 #define TCN_HKEY_CLASSES_ROOT 1 | |
| 55 #define TCN_HKEY_CURRENT_CONFIG 2 | |
| 56 #define TCN_HKEY_CURRENT_USER 3 | |
| 57 #define TCN_HKEY_LOCAL_MACHINE 4 | |
| 58 #define TCN_HKEY_USERS 5 | |
| 59 | |
| 60 static const struct { | |
| 61 HKEY k; | |
| 62 } TCN_KEYS[] = { | |
| 63 INVALID_HANDLE_VALUE, | |
| 64 HKEY_CLASSES_ROOT, | |
| 65 HKEY_CURRENT_CONFIG, | |
| 66 HKEY_CURRENT_USER, | |
| 67 HKEY_LOCAL_MACHINE, | |
| 68 HKEY_USERS, | |
| 69 INVALID_HANDLE_VALUE | |
| 70 }; | |
| 71 | |
| 72 #define TCN_KEY_ALL_ACCESS 0x0001 | |
| 73 #define TCN_KEY_CREATE_LINK 0x0002 | |
| 74 #define TCN_KEY_CREATE_SUB_KEY 0x0004 | |
| 75 #define TCN_KEY_ENUMERATE_SUB_KEYS 0x0008 | |
| 76 #define TCN_KEY_EXECUTE 0x0010 | |
| 77 #define TCN_KEY_NOTIFY 0x0020 | |
| 78 #define TCN_KEY_QUERY_VALUE 0x0040 | |
| 79 #define TCN_KEY_READ 0x0080 | |
| 80 #define TCN_KEY_SET_VALUE 0x0100 | |
| 81 #define TCN_KEY_WOW64_64KEY 0x0200 | |
| 82 #define TCN_KEY_WOW64_32KEY 0x0400 | |
| 83 #define TCN_KEY_WRITE 0x0800 | |
| 84 | |
| 85 #define TCN_REGSAM(s, x) \ | |
| 86 s = 0; \ | |
| 87 if (x & TCN_KEY_ALL_ACCESS) \ | |
| 88 s |= KEY_ALL_ACCESS; \ | |
| 89 if (x & TCN_KEY_CREATE_LINK) \ | |
| 90 s |= KEY_CREATE_LINK; \ | |
| 91 if (x & TCN_KEY_CREATE_SUB_KEY) \ | |
| 92 s |= KEY_CREATE_SUB_KEY; \ | |
| 93 if (x & TCN_KEY_ENUMERATE_SUB_KEYS) \ | |
| 94 s |= KEY_ENUMERATE_SUB_KEYS; \ | |
| 95 if (x & TCN_KEY_EXECUTE) \ | |
| 96 s |= KEY_EXECUTE; \ | |
| 97 if (x & TCN_KEY_NOTIFY) \ | |
| 98 s |= KEY_NOTIFY; \ | |
| 99 if (x & TCN_KEY_READ) \ | |
| 100 s |= KEY_READ; \ | |
| 101 if (x & TCN_KEY_SET_VALUE) \ | |
| 102 s |= KEY_SET_VALUE; \ | |
| 103 if (x & TCN_KEY_WOW64_64KEY) \ | |
| 104 s |= KEY_WOW64_64KEY; \ | |
| 105 if (x & TCN_KEY_WOW64_32KEY) \ | |
| 106 s |= KEY_WOW64_32KEY; \ | |
| 107 if (x & TCN_KEY_WRITE) \ | |
| 108 s |= KEY_WRITE | |
| 109 | |
| 110 #define TCN_REG_BINARY 1 | |
| 111 #define TCN_REG_DWORD 2 | |
| 112 #define TCN_REG_EXPAND_SZ 3 | |
| 113 #define TCN_REG_MULTI_SZ 4 | |
| 114 #define TCN_REG_QWORD 5 | |
| 115 #define TCN_REG_SZ 6 | |
| 116 | |
| 117 static const struct { | |
| 118 DWORD t; | |
| 119 } TCN_REGTYPES[] = { | |
| 120 REG_NONE, | |
| 121 REG_BINARY, | |
| 122 REG_DWORD, | |
| 123 REG_EXPAND_SZ, | |
| 124 REG_MULTI_SZ, | |
| 125 REG_QWORD, | |
| 126 REG_SZ, | |
| 127 REG_NONE | |
| 128 }; | |
| 129 | |
| 130 static apr_status_t registry_cleanup(void *data) | |
| 131 { | |
| 132 tcn_nt_registry_t *reg = (tcn_nt_registry_t *)data; | |
| 133 | |
| 134 if (reg) { | |
| 135 SAFE_CLOSE_KEY(reg->key); | |
| 136 } | |
| 137 return APR_SUCCESS; | |
| 138 } | |
| 139 | |
| 140 TCN_IMPLEMENT_CALL(jlong, Registry, create)(TCN_STDARGS, jint root, jstring name
, | |
| 141 jint sam, jlong pool) | |
| 142 { | |
| 143 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
| 144 tcn_nt_registry_t *reg = NULL; | |
| 145 TCN_ALLOC_WSTRING(name); | |
| 146 HKEY key; | |
| 147 LONG rc; | |
| 148 REGSAM s; | |
| 149 | |
| 150 UNREFERENCED(o); | |
| 151 TCN_ASSERT(pool != 0); | |
| 152 | |
| 153 if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { | |
| 154 tcn_ThrowException(e, "Invalid Registry Root Key"); | |
| 155 goto cleanup; | |
| 156 } | |
| 157 if (sam < TCN_KEY_ALL_ACCESS || root > TCN_KEY_WRITE) { | |
| 158 tcn_ThrowException(e, "Invalid Registry Key Security"); | |
| 159 goto cleanup; | |
| 160 } | |
| 161 reg = (tcn_nt_registry_t *)apr_palloc(p, sizeof(tcn_nt_registry_t)); | |
| 162 reg->pool = p; | |
| 163 reg->root = TCN_KEYS[root].k; | |
| 164 reg->key = NULL; | |
| 165 TCN_INIT_WSTRING(name); | |
| 166 TCN_REGSAM(s, sam); | |
| 167 rc = RegCreateKeyExW(reg->root, J2W(name), 0, NULL, REG_OPTION_NON_VOLATILE, | |
| 168 s, NULL, &key, NULL); | |
| 169 if (rc != ERROR_SUCCESS) { | |
| 170 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 171 goto cleanup; | |
| 172 } | |
| 173 reg->key = key; | |
| 174 apr_pool_cleanup_register(p, (const void *)reg, | |
| 175 registry_cleanup, | |
| 176 apr_pool_cleanup_null); | |
| 177 | |
| 178 cleanup: | |
| 179 TCN_FREE_WSTRING(name); | |
| 180 return P2J(reg); | |
| 181 } | |
| 182 | |
| 183 TCN_IMPLEMENT_CALL(jlong, Registry, open)(TCN_STDARGS, jint root, jstring name, | |
| 184 jint sam, jlong pool) | |
| 185 { | |
| 186 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
| 187 tcn_nt_registry_t *reg = NULL; | |
| 188 TCN_ALLOC_WSTRING(name); | |
| 189 HKEY key; | |
| 190 LONG rc; | |
| 191 REGSAM s; | |
| 192 | |
| 193 UNREFERENCED(o); | |
| 194 TCN_ASSERT(pool != 0); | |
| 195 | |
| 196 if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { | |
| 197 tcn_ThrowException(e, "Invalid Registry Root Key"); | |
| 198 goto cleanup; | |
| 199 } | |
| 200 if (sam < TCN_KEY_ALL_ACCESS || root > TCN_KEY_WRITE) { | |
| 201 tcn_ThrowException(e, "Invalid Registry Key Security"); | |
| 202 goto cleanup; | |
| 203 } | |
| 204 reg = (tcn_nt_registry_t *)apr_palloc(p, sizeof(tcn_nt_registry_t)); | |
| 205 reg->pool = p; | |
| 206 reg->root = TCN_KEYS[root].k; | |
| 207 reg->key = NULL; | |
| 208 TCN_INIT_WSTRING(name); | |
| 209 TCN_REGSAM(s, sam); | |
| 210 rc = RegOpenKeyExW(reg->root, J2W(name), 0, s, &key); | |
| 211 if (rc != ERROR_SUCCESS) { | |
| 212 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 213 goto cleanup; | |
| 214 } | |
| 215 reg->key = key; | |
| 216 apr_pool_cleanup_register(p, (const void *)reg, | |
| 217 registry_cleanup, | |
| 218 apr_pool_cleanup_null); | |
| 219 | |
| 220 cleanup: | |
| 221 TCN_FREE_WSTRING(name); | |
| 222 return P2J(reg); | |
| 223 } | |
| 224 | |
| 225 TCN_IMPLEMENT_CALL(jint, Registry, close)(TCN_STDARGS, jlong reg) | |
| 226 { | |
| 227 tcn_nt_registry_t *r = J2P(reg, tcn_nt_registry_t *); | |
| 228 UNREFERENCED_STDARGS; | |
| 229 | |
| 230 TCN_ASSERT(reg != 0); | |
| 231 | |
| 232 registry_cleanup(r); | |
| 233 apr_pool_cleanup_kill(r->pool, r, registry_cleanup); | |
| 234 return APR_SUCCESS; | |
| 235 } | |
| 236 | |
| 237 TCN_IMPLEMENT_CALL(jint, Registry, getType)(TCN_STDARGS, jlong key, | |
| 238 jstring name) | |
| 239 { | |
| 240 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 241 TCN_ALLOC_WSTRING(name); | |
| 242 LONG rc; | |
| 243 DWORD v; | |
| 244 | |
| 245 UNREFERENCED(o); | |
| 246 TCN_ASSERT(key != 0); | |
| 247 TCN_INIT_WSTRING(name); | |
| 248 rc = RegQueryValueExW(k->key, J2W(name), NULL, &v, NULL, NULL); | |
| 249 if (rc != ERROR_SUCCESS) | |
| 250 v = -rc; | |
| 251 TCN_FREE_WSTRING(name); | |
| 252 switch (v) { | |
| 253 case REG_BINARY: | |
| 254 v = TCN_REG_BINARY; | |
| 255 break; | |
| 256 case REG_DWORD: | |
| 257 v = TCN_REG_DWORD; | |
| 258 break; | |
| 259 case REG_EXPAND_SZ: | |
| 260 v = TCN_REG_EXPAND_SZ; | |
| 261 break; | |
| 262 case REG_MULTI_SZ: | |
| 263 v = TCN_REG_MULTI_SZ; | |
| 264 break; | |
| 265 case REG_QWORD: | |
| 266 v = TCN_REG_QWORD; | |
| 267 break; | |
| 268 case REG_SZ: | |
| 269 v = TCN_REG_SZ; | |
| 270 break; | |
| 271 case REG_DWORD_BIG_ENDIAN: | |
| 272 v = 0; | |
| 273 break; | |
| 274 } | |
| 275 return v; | |
| 276 } | |
| 277 | |
| 278 TCN_IMPLEMENT_CALL(jint, Registry, getSize)(TCN_STDARGS, jlong key, | |
| 279 jstring name) | |
| 280 { | |
| 281 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 282 TCN_ALLOC_WSTRING(name); | |
| 283 LONG rc; | |
| 284 DWORD v; | |
| 285 | |
| 286 UNREFERENCED(o); | |
| 287 TCN_ASSERT(key != 0); | |
| 288 TCN_INIT_WSTRING(name); | |
| 289 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, NULL, &v); | |
| 290 if (rc != ERROR_SUCCESS) | |
| 291 v = -rc; | |
| 292 TCN_FREE_WSTRING(name); | |
| 293 return v; | |
| 294 } | |
| 295 | |
| 296 TCN_IMPLEMENT_CALL(jint, Registry, getValueI)(TCN_STDARGS, jlong key, | |
| 297 jstring name) | |
| 298 { | |
| 299 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 300 TCN_ALLOC_WSTRING(name); | |
| 301 LONG rc; | |
| 302 DWORD t, l; | |
| 303 DWORD v = 0; | |
| 304 | |
| 305 UNREFERENCED(o); | |
| 306 TCN_ASSERT(key != 0); | |
| 307 TCN_INIT_WSTRING(name); | |
| 308 rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); | |
| 309 if (rc != ERROR_SUCCESS) { | |
| 310 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 311 goto cleanup; | |
| 312 } | |
| 313 if (t == REG_DWORD) { | |
| 314 l = sizeof(DWORD); | |
| 315 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&v, &l); | |
| 316 if (rc != ERROR_SUCCESS) { | |
| 317 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 318 goto cleanup; | |
| 319 } | |
| 320 } | |
| 321 else if (t == REG_SZ || t == REG_BINARY || | |
| 322 t == REG_MULTI_SZ || t == REG_EXPAND_SZ) | |
| 323 v = l; | |
| 324 else { | |
| 325 v = 0; | |
| 326 tcn_ThrowException(e, "Unable to convert the value to integer"); | |
| 327 } | |
| 328 cleanup: | |
| 329 TCN_FREE_WSTRING(name); | |
| 330 return v; | |
| 331 } | |
| 332 | |
| 333 TCN_IMPLEMENT_CALL(jlong, Registry, getValueJ)(TCN_STDARGS, jlong key, | |
| 334 jstring name) | |
| 335 { | |
| 336 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 337 TCN_ALLOC_WSTRING(name); | |
| 338 LONG rc; | |
| 339 DWORD t, l; | |
| 340 UINT64 v = 0; | |
| 341 | |
| 342 UNREFERENCED(o); | |
| 343 TCN_ASSERT(key != 0); | |
| 344 TCN_INIT_WSTRING(name); | |
| 345 rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); | |
| 346 if (rc != ERROR_SUCCESS) { | |
| 347 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 348 goto cleanup; | |
| 349 } | |
| 350 if (t == REG_DWORD) { | |
| 351 DWORD tv; | |
| 352 l = sizeof(DWORD); | |
| 353 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&tv, &l); | |
| 354 if (rc != ERROR_SUCCESS) { | |
| 355 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 356 goto cleanup; | |
| 357 } | |
| 358 v = tv; | |
| 359 } | |
| 360 else if (t == REG_QWORD) { | |
| 361 l = sizeof(UINT64); | |
| 362 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)&v, &l); | |
| 363 if (rc != ERROR_SUCCESS) { | |
| 364 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 365 goto cleanup; | |
| 366 } | |
| 367 } | |
| 368 else if (t == REG_SZ || t == REG_BINARY || | |
| 369 t == REG_MULTI_SZ || t == REG_EXPAND_SZ) | |
| 370 v = l; | |
| 371 else { | |
| 372 v = 0; | |
| 373 tcn_ThrowException(e, "Unable to convert the value to long"); | |
| 374 } | |
| 375 cleanup: | |
| 376 TCN_FREE_WSTRING(name); | |
| 377 return v; | |
| 378 } | |
| 379 | |
| 380 TCN_IMPLEMENT_CALL(jstring, Registry, getValueS)(TCN_STDARGS, jlong key, | |
| 381 jstring name) | |
| 382 { | |
| 383 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 384 TCN_ALLOC_WSTRING(name); | |
| 385 LONG rc; | |
| 386 DWORD t, l; | |
| 387 jstring v = NULL; | |
| 388 | |
| 389 UNREFERENCED(o); | |
| 390 TCN_ASSERT(key != 0); | |
| 391 TCN_INIT_WSTRING(name); | |
| 392 rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); | |
| 393 if (rc != ERROR_SUCCESS) { | |
| 394 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 395 goto cleanup; | |
| 396 } | |
| 397 if (t == REG_SZ || t == REG_EXPAND_SZ) { | |
| 398 jchar *vw = (jchar *)malloc(l); | |
| 399 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)vw, &l); | |
| 400 if (rc != ERROR_SUCCESS) { | |
| 401 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 402 free(vw); | |
| 403 goto cleanup; | |
| 404 } | |
| 405 v = (*e)->NewString((e), vw, lstrlenW(vw)); | |
| 406 free(vw); | |
| 407 } | |
| 408 cleanup: | |
| 409 TCN_FREE_WSTRING(name); | |
| 410 return v; | |
| 411 } | |
| 412 | |
| 413 TCN_IMPLEMENT_CALL(jbyteArray, Registry, getValueB)(TCN_STDARGS, jlong key, | |
| 414 jstring name) | |
| 415 { | |
| 416 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 417 TCN_ALLOC_WSTRING(name); | |
| 418 LONG rc; | |
| 419 DWORD t, l; | |
| 420 jbyteArray v = NULL; | |
| 421 | |
| 422 UNREFERENCED(o); | |
| 423 TCN_ASSERT(key != 0); | |
| 424 TCN_INIT_WSTRING(name); | |
| 425 rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); | |
| 426 if (rc != ERROR_SUCCESS) { | |
| 427 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 428 goto cleanup; | |
| 429 } | |
| 430 if (t == REG_BINARY) { | |
| 431 BYTE *b = (BYTE *)malloc(l); | |
| 432 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, b, &l); | |
| 433 if (rc != ERROR_SUCCESS) { | |
| 434 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 435 free(b); | |
| 436 goto cleanup; | |
| 437 } | |
| 438 v = tcn_new_arrayb(e, b, l); | |
| 439 free(b); | |
| 440 } | |
| 441 cleanup: | |
| 442 TCN_FREE_WSTRING(name); | |
| 443 return v; | |
| 444 } | |
| 445 | |
| 446 static jsize get_multi_sz_count(LPCWSTR str) | |
| 447 { | |
| 448 LPCWSTR p = str; | |
| 449 jsize cnt = 0; | |
| 450 for ( ; p && *p; p++) { | |
| 451 cnt++; | |
| 452 while (*p) | |
| 453 p++; | |
| 454 } | |
| 455 return cnt; | |
| 456 } | |
| 457 | |
| 458 TCN_IMPLEMENT_CALL(jobjectArray, Registry, getValueA)(TCN_STDARGS, jlong key, | |
| 459 jstring name) | |
| 460 { | |
| 461 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 462 TCN_ALLOC_WSTRING(name); | |
| 463 LONG rc; | |
| 464 DWORD t, l; | |
| 465 jobjectArray v = NULL; | |
| 466 | |
| 467 UNREFERENCED(o); | |
| 468 TCN_ASSERT(key != 0); | |
| 469 TCN_INIT_WSTRING(name); | |
| 470 rc = RegQueryValueExW(k->key, J2W(name), NULL, &t, NULL, &l); | |
| 471 if (rc != ERROR_SUCCESS) { | |
| 472 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 473 goto cleanup; | |
| 474 } | |
| 475 if (t == REG_MULTI_SZ) { | |
| 476 jsize cnt = 0; | |
| 477 jchar *p; | |
| 478 jchar *vw = (jchar *)malloc(l); | |
| 479 rc = RegQueryValueExW(k->key, J2W(name), NULL, NULL, (LPBYTE)vw, &l); | |
| 480 if (rc != ERROR_SUCCESS) { | |
| 481 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 482 free(vw); | |
| 483 goto cleanup; | |
| 484 } | |
| 485 cnt = get_multi_sz_count(vw); | |
| 486 if (cnt) { | |
| 487 jsize idx = 0; | |
| 488 v = tcn_new_arrays(e, cnt); | |
| 489 for (p = vw ; p && *p; p++) { | |
| 490 jstring s; | |
| 491 jchar *b = p; | |
| 492 while (*p) | |
| 493 p++; | |
| 494 s = (*e)->NewString((e), b, (jsize)(p - b)); | |
| 495 (*e)->SetObjectArrayElement((e), v, idx++, s); | |
| 496 } | |
| 497 } | |
| 498 free(vw); | |
| 499 } | |
| 500 cleanup: | |
| 501 TCN_FREE_WSTRING(name); | |
| 502 return v; | |
| 503 } | |
| 504 | |
| 505 TCN_IMPLEMENT_CALL(jint, Registry, setValueI)(TCN_STDARGS, jlong key, | |
| 506 jstring name, jint val) | |
| 507 { | |
| 508 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 509 TCN_ALLOC_WSTRING(name); | |
| 510 LONG rc; | |
| 511 DWORD v = (DWORD)val; | |
| 512 | |
| 513 UNREFERENCED(o); | |
| 514 TCN_ASSERT(key != 0); | |
| 515 TCN_INIT_WSTRING(name); | |
| 516 rc = RegSetValueExW(k->key, J2W(name), 0, REG_DWORD, (CONST BYTE *)&v, sizeo
f(DWORD)); | |
| 517 TCN_FREE_WSTRING(name); | |
| 518 return v; | |
| 519 } | |
| 520 | |
| 521 TCN_IMPLEMENT_CALL(jint, Registry, setValueJ)(TCN_STDARGS, jlong key, | |
| 522 jstring name, jlong val) | |
| 523 { | |
| 524 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 525 TCN_ALLOC_WSTRING(name); | |
| 526 LONG rc; | |
| 527 UINT64 v = (UINT64)val; | |
| 528 | |
| 529 UNREFERENCED(o); | |
| 530 TCN_ASSERT(key != 0); | |
| 531 TCN_INIT_WSTRING(name); | |
| 532 rc = RegSetValueExW(k->key, J2W(name), 0, REG_QWORD, (CONST BYTE *)&v, sizeo
f(UINT64)); | |
| 533 TCN_FREE_WSTRING(name); | |
| 534 return rc; | |
| 535 } | |
| 536 | |
| 537 TCN_IMPLEMENT_CALL(jint, Registry, setValueS)(TCN_STDARGS, jlong key, | |
| 538 jstring name, jstring val) | |
| 539 { | |
| 540 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 541 TCN_ALLOC_WSTRING(name); | |
| 542 TCN_ALLOC_WSTRING(val); | |
| 543 LONG rc; | |
| 544 DWORD len; | |
| 545 | |
| 546 UNREFERENCED(o); | |
| 547 TCN_ASSERT(key != 0); | |
| 548 TCN_INIT_WSTRING(name); | |
| 549 TCN_INIT_WSTRING(val); | |
| 550 len = lstrlenW(J2W(val)); | |
| 551 rc = RegSetValueExW(k->key, J2W(name), 0, REG_SZ, | |
| 552 (CONST BYTE *)J2W(val), (len + 1) * 2); | |
| 553 TCN_FREE_WSTRING(name); | |
| 554 TCN_FREE_WSTRING(val); | |
| 555 return rc; | |
| 556 } | |
| 557 | |
| 558 TCN_IMPLEMENT_CALL(jint, Registry, setValueE)(TCN_STDARGS, jlong key, | |
| 559 jstring name, jstring val) | |
| 560 { | |
| 561 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 562 TCN_ALLOC_WSTRING(name); | |
| 563 TCN_ALLOC_WSTRING(val); | |
| 564 LONG rc; | |
| 565 DWORD len; | |
| 566 | |
| 567 UNREFERENCED(o); | |
| 568 TCN_ASSERT(key != 0); | |
| 569 TCN_INIT_WSTRING(name); | |
| 570 TCN_INIT_WSTRING(val); | |
| 571 len = lstrlenW(J2W(val)); | |
| 572 rc = RegSetValueExW(k->key, J2W(name), 0, REG_EXPAND_SZ, | |
| 573 (CONST BYTE *)J2W(val), (len + 1) * 2); | |
| 574 TCN_FREE_WSTRING(name); | |
| 575 TCN_FREE_WSTRING(val); | |
| 576 return rc; | |
| 577 } | |
| 578 | |
| 579 TCN_IMPLEMENT_CALL(jint, Registry, setValueA)(TCN_STDARGS, jlong key, | |
| 580 jstring name, | |
| 581 jobjectArray vals) | |
| 582 { | |
| 583 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 584 TCN_ALLOC_WSTRING(name); | |
| 585 LONG rc; | |
| 586 jsize i, len; | |
| 587 jsize sl = 0; | |
| 588 jchar *msz, *p; | |
| 589 UNREFERENCED(o); | |
| 590 TCN_ASSERT(key != 0); | |
| 591 TCN_INIT_WSTRING(name); | |
| 592 len = (*e)->GetArrayLength((e), vals); | |
| 593 for (i = 0; i < len; i++) { | |
| 594 jstring s = (jstring)(*e)->GetObjectArrayElement((e), vals, i); | |
| 595 sl += (*e)->GetStringLength((e), s) + 1; | |
| 596 } | |
| 597 sl = (sl + 1) * 2; | |
| 598 p = msz = (jchar *)calloc(1, sl); | |
| 599 for (i = 0; i < len; i++) { | |
| 600 jsize l; | |
| 601 jstring s = (jstring)(*e)->GetObjectArrayElement((e), vals, i); | |
| 602 l = (*e)->GetStringLength((e), s); | |
| 603 wcsncpy(p, (*e)->GetStringChars(e, s, 0), l); | |
| 604 p += l + 1; | |
| 605 } | |
| 606 rc = RegSetValueExW(k->key, J2W(name), 0, REG_MULTI_SZ, | |
| 607 (CONST BYTE *)msz, sl); | |
| 608 TCN_FREE_WSTRING(name); | |
| 609 free(msz); | |
| 610 return rc; | |
| 611 } | |
| 612 | |
| 613 TCN_IMPLEMENT_CALL(jint, Registry, setValueB)(TCN_STDARGS, jlong key, | |
| 614 jstring name, | |
| 615 jbyteArray val) | |
| 616 { | |
| 617 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 618 TCN_ALLOC_WSTRING(name); | |
| 619 jsize nbytes = (*e)->GetArrayLength(e, val); | |
| 620 jbyte *bytes = (*e)->GetByteArrayElements(e, val, NULL); | |
| 621 LONG rc; | |
| 622 | |
| 623 rc = RegSetValueExW(k->key, J2W(name), 0, REG_BINARY, | |
| 624 bytes, (DWORD)nbytes); | |
| 625 (*e)->ReleaseByteArrayElements(e, val, bytes, JNI_ABORT); | |
| 626 TCN_FREE_WSTRING(name); | |
| 627 return rc; | |
| 628 } | |
| 629 | |
| 630 #define MAX_VALUE_NAME 4096 | |
| 631 | |
| 632 TCN_IMPLEMENT_CALL(jobjectArray, Registry, enumKeys)(TCN_STDARGS, jlong key) | |
| 633 { | |
| 634 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 635 LONG rc; | |
| 636 jobjectArray v = NULL; | |
| 637 jsize cnt = 0; | |
| 638 | |
| 639 WCHAR achKey[MAX_PATH]; | |
| 640 WCHAR achClass[MAX_PATH] = L""; | |
| 641 DWORD cchClassName = MAX_PATH; | |
| 642 DWORD cSubKeys; | |
| 643 DWORD cbMaxSubKey; | |
| 644 DWORD cchMaxClass; | |
| 645 DWORD cValues; | |
| 646 DWORD cchMaxValue; | |
| 647 DWORD cbMaxValueData; | |
| 648 DWORD cbSecurityDescriptor; | |
| 649 FILETIME ftLastWriteTime; | |
| 650 | |
| 651 DWORD cchValue = MAX_VALUE_NAME; | |
| 652 | |
| 653 UNREFERENCED(o); | |
| 654 TCN_ASSERT(key != 0); | |
| 655 rc = RegQueryInfoKeyW(k->key, | |
| 656 achClass, | |
| 657 &cchClassName, | |
| 658 NULL, | |
| 659 &cSubKeys, | |
| 660 &cbMaxSubKey, | |
| 661 &cchMaxClass, | |
| 662 &cValues, | |
| 663 &cchMaxValue, | |
| 664 &cbMaxValueData, | |
| 665 &cbSecurityDescriptor, | |
| 666 &ftLastWriteTime); | |
| 667 if (rc != ERROR_SUCCESS) { | |
| 668 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 669 goto cleanup; | |
| 670 } | |
| 671 cnt = cSubKeys; | |
| 672 if (cnt) { | |
| 673 jsize idx = 0; | |
| 674 v = tcn_new_arrays(e, cnt); | |
| 675 for (idx = 0; idx < cnt; idx++) { | |
| 676 jstring s; | |
| 677 DWORD achKeyLen = MAX_PATH; | |
| 678 rc = RegEnumKeyExW(k->key, | |
| 679 idx, | |
| 680 achKey, | |
| 681 &achKeyLen, | |
| 682 NULL, | |
| 683 NULL, | |
| 684 NULL, | |
| 685 &ftLastWriteTime); | |
| 686 if (rc == (DWORD)ERROR_SUCCESS) { | |
| 687 s = (*e)->NewString((e), achKey, lstrlenW(achKey)); | |
| 688 (*e)->SetObjectArrayElement((e), v, idx, s); | |
| 689 } | |
| 690 } | |
| 691 } | |
| 692 cleanup: | |
| 693 return v; | |
| 694 } | |
| 695 | |
| 696 TCN_IMPLEMENT_CALL(jobjectArray, Registry, enumValues)(TCN_STDARGS, jlong key) | |
| 697 { | |
| 698 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 699 LONG rc; | |
| 700 jobjectArray v = NULL; | |
| 701 jsize cnt = 0; | |
| 702 | |
| 703 WCHAR achClass[MAX_PATH] = L""; | |
| 704 DWORD cchClassName = MAX_PATH; | |
| 705 DWORD cSubKeys; | |
| 706 DWORD cbMaxSubKey; | |
| 707 DWORD cchMaxClass; | |
| 708 DWORD cValues; | |
| 709 DWORD cchMaxValue; | |
| 710 DWORD cbMaxValueData; | |
| 711 DWORD cbSecurityDescriptor; | |
| 712 FILETIME ftLastWriteTime; | |
| 713 | |
| 714 WCHAR achValue[MAX_VALUE_NAME]; | |
| 715 DWORD cchValue = MAX_VALUE_NAME; | |
| 716 | |
| 717 UNREFERENCED(o); | |
| 718 TCN_ASSERT(key != 0); | |
| 719 /* Get the class name and the value count. */ | |
| 720 rc = RegQueryInfoKeyW(k->key, | |
| 721 achClass, | |
| 722 &cchClassName, | |
| 723 NULL, | |
| 724 &cSubKeys, | |
| 725 &cbMaxSubKey, | |
| 726 &cchMaxClass, | |
| 727 &cValues, | |
| 728 &cchMaxValue, | |
| 729 &cbMaxValueData, | |
| 730 &cbSecurityDescriptor, | |
| 731 &ftLastWriteTime); | |
| 732 if (rc != ERROR_SUCCESS) { | |
| 733 tcn_ThrowAPRException(e, APR_FROM_OS_ERROR(rc)); | |
| 734 goto cleanup; | |
| 735 } | |
| 736 cnt = cValues; | |
| 737 if (cnt) { | |
| 738 jsize idx = 0; | |
| 739 v = tcn_new_arrays(e, cnt); | |
| 740 for (idx = 0; idx < cnt; idx++) { | |
| 741 jstring s; | |
| 742 cchValue = MAX_VALUE_NAME; | |
| 743 achValue[0] = '\0'; | |
| 744 rc = RegEnumValueW(k->key, idx, | |
| 745 achValue, | |
| 746 &cchValue, | |
| 747 NULL, | |
| 748 NULL, // &dwType, | |
| 749 NULL, // &bData, | |
| 750 NULL); // &bcData | |
| 751 if (rc == (DWORD)ERROR_SUCCESS) { | |
| 752 s = (*e)->NewString((e), achValue, lstrlenW(achValue)); | |
| 753 (*e)->SetObjectArrayElement((e), v, idx, s); | |
| 754 } | |
| 755 } | |
| 756 } | |
| 757 cleanup: | |
| 758 return v; | |
| 759 } | |
| 760 | |
| 761 TCN_IMPLEMENT_CALL(jint, Registry, deleteKey)(TCN_STDARGS, jint root, jstring na
me, | |
| 762 jboolean only_if_empty) | |
| 763 { | |
| 764 DWORD rv; | |
| 765 TCN_ALLOC_WSTRING(name); | |
| 766 | |
| 767 UNREFERENCED(o); | |
| 768 if (root < TCN_HKEY_CLASSES_ROOT || root > TCN_HKEY_USERS) { | |
| 769 rv = EBADF; | |
| 770 goto cleanup; | |
| 771 } | |
| 772 TCN_INIT_WSTRING(name); | |
| 773 if (only_if_empty) | |
| 774 rv = SHDeleteEmptyKeyW(TCN_KEYS[root].k, J2W(name)); | |
| 775 else | |
| 776 rv = SHDeleteKeyW(TCN_KEYS[root].k, J2W(name)); | |
| 777 cleanup: | |
| 778 TCN_FREE_WSTRING(name); | |
| 779 return rv; | |
| 780 } | |
| 781 | |
| 782 TCN_IMPLEMENT_CALL(jint, Registry, deleteValue)(TCN_STDARGS, jlong key, | |
| 783 jstring name) | |
| 784 { | |
| 785 LONG rv; | |
| 786 TCN_ALLOC_WSTRING(name); | |
| 787 tcn_nt_registry_t *k = J2P(key, tcn_nt_registry_t *); | |
| 788 | |
| 789 UNREFERENCED(o); | |
| 790 TCN_INIT_WSTRING(name); | |
| 791 rv = RegDeleteValueW(k->key, J2W(name)); | |
| 792 TCN_FREE_WSTRING(name); | |
| 793 return (jint)rv; | |
| 794 } | |
| 795 | |
| 796 #endif | |
| 797 | |
| OLD | NEW |