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 |