00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef WIN32
00018
00019 #include "apr.h"
00020 #include "arch/win32/apr_arch_file_io.h"
00021 #include "arch/win32/apr_arch_misc.h"
00022 #include "ap_regkey.h"
00023
00024 struct ap_regkey_t {
00025 apr_pool_t *pool;
00026 HKEY hkey;
00027 };
00028
00029
00030 AP_DECLARE(const ap_regkey_t *) ap_regkey_const(int i)
00031 {
00032 static struct ap_regkey_t ap_regkey_consts[7] =
00033 {
00034 {NULL, HKEY_CLASSES_ROOT},
00035 {NULL, HKEY_CURRENT_CONFIG},
00036 {NULL, HKEY_CURRENT_USER},
00037 {NULL, HKEY_LOCAL_MACHINE},
00038 {NULL, HKEY_USERS},
00039 {NULL, HKEY_PERFORMANCE_DATA},
00040 {NULL, HKEY_DYN_DATA}
00041 };
00042 return ap_regkey_consts + i;
00043 }
00044
00045
00046 apr_status_t regkey_cleanup(void *key)
00047 {
00048 ap_regkey_t *regkey = key;
00049
00050 if (regkey->hkey && regkey->hkey != INVALID_HANDLE_VALUE) {
00051 RegCloseKey(regkey->hkey);
00052 regkey->hkey = INVALID_HANDLE_VALUE;
00053 }
00054 return APR_SUCCESS;
00055 }
00056
00057
00058 AP_DECLARE(apr_status_t) ap_regkey_open(ap_regkey_t **newkey,
00059 const ap_regkey_t *parentkey,
00060 const char *keyname,
00061 apr_int32_t flags,
00062 apr_pool_t *pool)
00063 {
00064 DWORD access = KEY_QUERY_VALUE;
00065 DWORD exists;
00066 HKEY hkey;
00067 LONG rc;
00068
00069 if (flags & APR_READ)
00070 access |= KEY_READ;
00071 if (flags & APR_WRITE)
00072 access |= KEY_WRITE;
00073
00074 #if APR_HAS_UNICODE_FS
00075 IF_WIN_OS_IS_UNICODE
00076 {
00077 apr_size_t keylen = strlen(keyname) + 1;
00078 apr_size_t wkeylen = 256;
00079 apr_wchar_t wkeyname[256];
00080 apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen);
00081 if (rv != APR_SUCCESS)
00082 return rv;
00083 else if (keylen)
00084 return APR_ENAMETOOLONG;
00085
00086 if (flags & APR_CREATE)
00087 rc = RegCreateKeyExW(parentkey->hkey, wkeyname, 0, NULL, 0,
00088 access, NULL, &hkey, &exists);
00089 else
00090 rc = RegOpenKeyExW(parentkey->hkey, wkeyname, 0, access, &hkey);
00091 }
00092 #endif
00093 #if APR_HAS_ANSI_FS
00094 ELSE_WIN_OS_IS_ANSI
00095 {
00096 if (flags & APR_CREATE)
00097 rc = RegCreateKeyEx(parentkey->hkey, keyname, 0, NULL, 0,
00098 access, NULL, &hkey, &exists);
00099 else
00100 rc = RegOpenKeyEx(parentkey->hkey, keyname, 0, access, &hkey);
00101 }
00102 #endif
00103 if (rc != ERROR_SUCCESS) {
00104 return APR_FROM_OS_ERROR(rc);
00105 }
00106 if ((flags & APR_EXCL) && (exists == REG_OPENED_EXISTING_KEY)) {
00107 RegCloseKey(hkey);
00108 return APR_EEXIST;
00109 }
00110
00111 *newkey = apr_palloc(pool, sizeof(**newkey));
00112 (*newkey)->pool = pool;
00113 (*newkey)->hkey = hkey;
00114 apr_pool_cleanup_register((*newkey)->pool, (void *)(*newkey),
00115 regkey_cleanup, apr_pool_cleanup_null);
00116 return APR_SUCCESS;
00117 }
00118
00119
00120 AP_DECLARE(apr_status_t) ap_regkey_close(ap_regkey_t *regkey)
00121 {
00122 apr_status_t stat;
00123 if ((stat = regkey_cleanup(regkey)) == APR_SUCCESS) {
00124 apr_pool_cleanup_kill(regkey->pool, regkey, regkey_cleanup);
00125 }
00126 return stat;
00127 }
00128
00129
00130 AP_DECLARE(apr_status_t) ap_regkey_remove(const ap_regkey_t *parent,
00131 const char *keyname,
00132 apr_pool_t *pool)
00133 {
00134 LONG rc;
00135
00136 #if APR_HAS_UNICODE_FS
00137 IF_WIN_OS_IS_UNICODE
00138 {
00139 apr_size_t keylen = strlen(keyname) + 1;
00140 apr_size_t wkeylen = 256;
00141 apr_wchar_t wkeyname[256];
00142 apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen);
00143 if (rv != APR_SUCCESS)
00144 return rv;
00145 else if (keylen)
00146 return APR_ENAMETOOLONG;
00147 rc = RegDeleteKeyW(parent->hkey, wkeyname);
00148 }
00149 #endif
00150 #if APR_HAS_ANSI_FS
00151 ELSE_WIN_OS_IS_ANSI
00152 {
00153
00154
00155
00156
00157 DWORD subkeys;
00158 HKEY hkey;
00159 rc = RegOpenKeyEx(parent->hkey, keyname, 0, KEY_READ, &hkey);
00160 if (rc != ERROR_SUCCESS)
00161 return APR_FROM_OS_ERROR(rc);
00162 rc = RegQueryInfoKey(hkey, NULL, NULL, NULL, &subkeys, NULL, NULL,
00163 NULL, NULL, NULL, NULL, NULL);
00164 RegCloseKey(hkey);
00165 if (rc != ERROR_SUCCESS)
00166 return APR_FROM_OS_ERROR(rc);
00167 else if (subkeys)
00168 return APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED);
00169 rc = RegDeleteKey(parent->hkey, keyname);
00170 }
00171 #endif
00172 if (rc != ERROR_SUCCESS) {
00173 return APR_FROM_OS_ERROR(rc);
00174 }
00175 return APR_SUCCESS;
00176 }
00177
00178
00179 AP_DECLARE(apr_status_t) ap_regkey_value_get(char **result,
00180 ap_regkey_t *key,
00181 const char *valuename,
00182 apr_pool_t *pool)
00183 {
00184
00185
00186
00187 LONG rc;
00188 DWORD type;
00189 DWORD size = 0;
00190
00191 #if APR_HAS_UNICODE_FS
00192 IF_WIN_OS_IS_UNICODE
00193 {
00194 apr_size_t valuelen = strlen(valuename) + 1;
00195 apr_size_t wvallen = 256;
00196 apr_wchar_t wvalname[256];
00197 apr_wchar_t *wvalue;
00198 apr_status_t rv;
00199 rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
00200 if (rv != APR_SUCCESS)
00201 return rv;
00202 else if (valuelen)
00203 return APR_ENAMETOOLONG;
00204
00205 rc = RegQueryValueExW(key->hkey, wvalname, 0, &type, NULL, &size);
00206 if (rc != ERROR_SUCCESS) {
00207 return APR_FROM_OS_ERROR(rc);
00208 }
00209 if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
00210 return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER);
00211 }
00212
00213 wvalue = apr_palloc(pool, size);
00214
00215 rc = RegQueryValueExW(key->hkey, wvalname, 0, &type,
00216 (LPBYTE)wvalue, &size);
00217 if (rc != ERROR_SUCCESS) {
00218 return APR_FROM_OS_ERROR(rc);
00219 }
00220 if (type == REG_EXPAND_SZ) {
00221 apr_wchar_t zbuf[1];
00222 size = ExpandEnvironmentStringsW(wvalue, zbuf, 0);
00223 if (size) {
00224 apr_wchar_t *tmp = wvalue;
00225
00226 wvalue = apr_palloc(pool, size * 2);
00227 size = ExpandEnvironmentStringsW(tmp, wvalue, size);
00228 }
00229 }
00230 else {
00231
00232 size /= 2;
00233 }
00234
00235
00236
00237
00238 valuelen = (size - 1) * 3 + 1;
00239 *result = apr_palloc(pool, valuelen);
00240 rv = apr_conv_ucs2_to_utf8(wvalue, &size, *result, &valuelen);
00241 if (rv != APR_SUCCESS)
00242 return rv;
00243 else if (size)
00244 return APR_ENAMETOOLONG;
00245 }
00246 #endif
00247 #if APR_HAS_ANSI_FS
00248 ELSE_WIN_OS_IS_ANSI
00249 {
00250
00251 rc = RegQueryValueEx(key->hkey, valuename, 0, &type, NULL, &size);
00252 if (rc != ERROR_SUCCESS)
00253 return APR_FROM_OS_ERROR(rc);
00254
00255 if ((size < 1) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
00256 return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER);
00257 }
00258
00259 *result = apr_palloc(pool, size);
00260
00261 rc = RegQueryValueEx(key->hkey, valuename, 0, &type, *result, &size);
00262 if (rc != ERROR_SUCCESS)
00263 return APR_FROM_OS_ERROR(rc);
00264
00265 if (type == REG_EXPAND_SZ) {
00266
00267
00268
00269 char zbuf[1];
00270 size = ExpandEnvironmentStrings(*result, zbuf, 0);
00271 if (size) {
00272 char *tmp = *result;
00273 *result = apr_palloc(pool, size);
00274 size = ExpandEnvironmentStrings(tmp, *result, size);
00275 }
00276 }
00277 }
00278 #endif
00279 return APR_SUCCESS;
00280 }
00281
00282
00283 AP_DECLARE(apr_status_t) ap_regkey_value_set(ap_regkey_t *key,
00284 const char *valuename,
00285 const char *value,
00286 apr_int32_t flags,
00287 apr_pool_t *pool)
00288 {
00289
00290
00291
00292 LONG rc;
00293 DWORD size = strlen(value) + 1;
00294 DWORD type = (flags & AP_REGKEY_EXPAND) ? REG_EXPAND_SZ : REG_SZ;
00295
00296 #if APR_HAS_UNICODE_FS
00297 IF_WIN_OS_IS_UNICODE
00298 {
00299 apr_size_t alloclen;
00300 apr_size_t valuelen = strlen(valuename) + 1;
00301 apr_size_t wvallen = 256;
00302 apr_wchar_t wvalname[256];
00303 apr_wchar_t *wvalue;
00304 apr_status_t rv;
00305 rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
00306 if (rv != APR_SUCCESS)
00307 return rv;
00308 else if (valuelen)
00309 return APR_ENAMETOOLONG;
00310
00311 wvallen = alloclen = size;
00312 wvalue = apr_palloc(pool, alloclen * 2);
00313 rv = apr_conv_utf8_to_ucs2(value, &size, wvalue, &wvallen);
00314 if (rv != APR_SUCCESS)
00315 return rv;
00316 else if (size)
00317 return APR_ENAMETOOLONG;
00318
00319
00320
00321
00322 size = (alloclen - wvallen) * 2;
00323 rc = RegSetValueExW(key->hkey, wvalname, 0, type,
00324 (LPBYTE)wvalue, size);
00325 if (rc != ERROR_SUCCESS)
00326 return APR_FROM_OS_ERROR(rc);
00327 }
00328 #endif
00329 #if APR_HAS_ANSI_FS
00330 ELSE_WIN_OS_IS_ANSI
00331 {
00332 rc = RegSetValueEx(key->hkey, valuename, 0, type, value, size);
00333 if (rc != ERROR_SUCCESS)
00334 return APR_FROM_OS_ERROR(rc);
00335 }
00336 #endif
00337 return APR_SUCCESS;
00338 }
00339
00340
00341 AP_DECLARE(apr_status_t) ap_regkey_value_raw_get(void **result,
00342 apr_size_t *resultsize,
00343 apr_int32_t *resulttype,
00344 ap_regkey_t *key,
00345 const char *valuename,
00346 apr_pool_t *pool)
00347 {
00348
00349
00350
00351 LONG rc;
00352
00353 #if APR_HAS_UNICODE_FS
00354 IF_WIN_OS_IS_UNICODE
00355 {
00356 apr_size_t valuelen = strlen(valuename) + 1;
00357 apr_size_t wvallen = 256;
00358 apr_wchar_t wvalname[256];
00359 apr_status_t rv;
00360 rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
00361 if (rv != APR_SUCCESS)
00362 return rv;
00363 else if (valuelen)
00364 return APR_ENAMETOOLONG;
00365
00366 rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype,
00367 NULL, resultsize);
00368 if (rc != ERROR_SUCCESS) {
00369 return APR_FROM_OS_ERROR(rc);
00370 }
00371
00372
00373 *result = apr_palloc(pool, *resultsize);
00374 rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype,
00375 (LPBYTE)*result, resultsize);
00376 }
00377 #endif
00378 #if APR_HAS_ANSI_FS
00379 ELSE_WIN_OS_IS_ANSI
00380 {
00381
00382 rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype,
00383 NULL, resultsize);
00384 if (rc != ERROR_SUCCESS)
00385 return APR_FROM_OS_ERROR(rc);
00386
00387
00388 *result = apr_palloc(pool, *resultsize);
00389 rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype,
00390 (LPBYTE)*result, resultsize);
00391 if (rc != ERROR_SUCCESS)
00392 return APR_FROM_OS_ERROR(rc);
00393 }
00394 #endif
00395 if (rc != ERROR_SUCCESS) {
00396 return APR_FROM_OS_ERROR(rc);
00397 }
00398
00399 return APR_SUCCESS;
00400 }
00401
00402
00403 AP_DECLARE(apr_status_t) ap_regkey_value_raw_set(ap_regkey_t *key,
00404 const char *valuename,
00405 const void *value,
00406 apr_size_t valuesize,
00407 apr_int32_t valuetype,
00408 apr_pool_t *pool)
00409 {
00410 LONG rc;
00411
00412 #if APR_HAS_UNICODE_FS
00413 IF_WIN_OS_IS_UNICODE
00414 {
00415 apr_size_t valuelen = strlen(valuename) + 1;
00416 apr_size_t wvallen = 256;
00417 apr_wchar_t wvalname[256];
00418 apr_status_t rv;
00419 rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
00420 if (rv != APR_SUCCESS)
00421 return rv;
00422 else if (valuelen)
00423 return APR_ENAMETOOLONG;
00424
00425 rc = RegSetValueExW(key->hkey, wvalname, 0, valuetype,
00426 (LPBYTE)value, valuesize);
00427 }
00428 #endif
00429 #if APR_HAS_ANSI_FS
00430 ELSE_WIN_OS_IS_ANSI
00431 {
00432 rc = RegSetValueEx(key->hkey, valuename, 0, valuetype,
00433 (LPBYTE)value, valuesize);
00434 }
00435 #endif
00436 if (rc != ERROR_SUCCESS) {
00437 return APR_FROM_OS_ERROR(rc);
00438 }
00439 return APR_SUCCESS;
00440 }
00441
00442
00443 AP_DECLARE(apr_status_t) ap_regkey_value_array_get(apr_array_header_t **result,
00444 ap_regkey_t *key,
00445 const char *valuename,
00446 apr_pool_t *pool)
00447 {
00448
00449
00450
00451 apr_status_t rv;
00452 void *value;
00453 char *buf;
00454 char *tmp;
00455 DWORD type;
00456 DWORD size = 0;
00457
00458 rv = ap_regkey_value_raw_get(&value, &size, &type, key, valuename, pool);
00459 if (rv != APR_SUCCESS) {
00460 return rv;
00461 }
00462 else if (type != REG_MULTI_SZ) {
00463 return APR_EINVAL;
00464 }
00465
00466 #if APR_HAS_UNICODE_FS
00467 IF_WIN_OS_IS_UNICODE
00468 {
00469 apr_size_t alloclen;
00470 apr_size_t valuelen = strlen(valuename) + 1;
00471 apr_size_t wvallen = 256;
00472 apr_wchar_t *wvalue = (apr_wchar_t *)value;
00473
00474
00475
00476
00477
00478 size /= 2;
00479 alloclen = valuelen = size * 3 + 2;
00480 buf = apr_palloc(pool, valuelen);
00481 rv = apr_conv_ucs2_to_utf8(value, &size, buf, &valuelen);
00482 if (rv != APR_SUCCESS)
00483 return rv;
00484 else if (size)
00485 return APR_ENAMETOOLONG;
00486 buf[(alloclen - valuelen)] = '\0';
00487 buf[(alloclen - valuelen) + 1] = '\0';
00488 }
00489 #endif
00490 #if APR_HAS_ANSI_FS
00491 ELSE_WIN_OS_IS_ANSI
00492 {
00493
00494
00495
00496 buf = (char *)value;
00497 if (size < 2 || buf[size - 1] != '\0' || buf[size - 2] != '\0') {
00498 buf = apr_palloc(pool, size + 2);
00499 memcpy(buf, value, size);
00500 buf[size + 1] = '\0';
00501 buf[size] = '\0';
00502 }
00503 }
00504 #endif
00505
00506 size = 0;
00507 for (tmp = buf; *tmp; ++tmp) {
00508 ++size;
00509 while (*tmp) {
00510 ++tmp;
00511 }
00512 }
00513
00514 *result = apr_array_make(pool, size, sizeof(char *));
00515 for (tmp = buf; *tmp; ++tmp) {
00516 char **newelem = (char **) apr_array_push(*result);
00517 *newelem = tmp;
00518 while (*tmp) {
00519 ++tmp;
00520 }
00521 }
00522
00523 return APR_SUCCESS;
00524 }
00525
00526
00527 AP_DECLARE(apr_status_t) ap_regkey_value_array_set(ap_regkey_t *key,
00528 const char *valuename,
00529 int nelts,
00530 const char * const * elts,
00531 apr_pool_t *pool)
00532 {
00533
00534
00535
00536 int i;
00537 const void *value;
00538 apr_size_t bufsize;
00539
00540 #if APR_HAS_UNICODE_FS
00541 IF_WIN_OS_IS_UNICODE
00542 {
00543 apr_status_t rv;
00544 apr_wchar_t *buf;
00545 apr_wchar_t *tmp;
00546 apr_size_t bufrem;
00547
00548 bufsize = 1;
00549 for (i = 0; i < nelts; ++i) {
00550 bufsize += strlen(elts[i]) + 1;
00551 }
00552 if (!nelts) {
00553 ++bufsize;
00554 }
00555
00556 bufrem = bufsize;
00557 buf = apr_palloc(pool, bufsize * 2);
00558 tmp = buf;
00559 for (i = 0; i < nelts; ++i) {
00560 apr_size_t eltsize = strlen(elts[i]) + 1;
00561 apr_size_t size = eltsize;
00562 rv = apr_conv_utf8_to_ucs2(elts[i], &size, tmp, &bufrem);
00563 if (rv != APR_SUCCESS)
00564 return rv;
00565 else if (size)
00566 return APR_ENAMETOOLONG;
00567 tmp += eltsize;
00568 }
00569 if (!nelts) {
00570 --bufrem;
00571 (*tmp++) = L'\0';
00572 }
00573 --bufrem;
00574 *tmp = L'\0';
00575
00576 bufsize = (bufsize - bufrem) * 2;
00577 value = (void*)buf;
00578 }
00579 #endif
00580 #if APR_HAS_ANSI_FS
00581 ELSE_WIN_OS_IS_ANSI
00582 {
00583 char *buf;
00584 char *tmp;
00585
00586 bufsize = 1;
00587 for (i = 0; i < nelts; ++i) {
00588 bufsize += strlen(elts[i]) + 1;
00589 }
00590 if (!nelts) {
00591 ++bufsize;
00592 }
00593 buf = apr_palloc(pool, bufsize);
00594 tmp = buf;
00595 for (i = 0; i < nelts; ++i) {
00596 apr_size_t len = strlen(elts[i]) + 1;
00597 memcpy(tmp, elts[i], len);
00598 tmp += len;
00599 }
00600 if (!nelts) {
00601 (*tmp++) = '\0';
00602 }
00603 *tmp = '\0';
00604 value = buf;
00605 }
00606 #endif
00607 return ap_regkey_value_raw_set(key, valuename, value,
00608 bufsize, REG_MULTI_SZ, pool);
00609 }
00610
00611
00612 AP_DECLARE(apr_status_t) ap_regkey_value_remove(const ap_regkey_t *key,
00613 const char *valuename,
00614 apr_pool_t *pool)
00615 {
00616 LONG rc;
00617
00618 #if APR_HAS_UNICODE_FS
00619 IF_WIN_OS_IS_UNICODE
00620 {
00621 apr_size_t valuelen = strlen(valuename) + 1;
00622 apr_size_t wvallen = 256;
00623 apr_wchar_t wvalname[256];
00624 apr_status_t rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
00625 if (rv != APR_SUCCESS)
00626 return rv;
00627 else if (valuelen)
00628 return APR_ENAMETOOLONG;
00629 rc = RegDeleteValueW(key->hkey, wvalname);
00630 }
00631 #endif
00632 #if APR_HAS_ANSI_FS
00633 ELSE_WIN_OS_IS_ANSI
00634 {
00635 rc = RegDeleteValue(key->hkey, valuename);
00636 }
00637 #endif
00638 if (rc != ERROR_SUCCESS) {
00639 return APR_FROM_OS_ERROR(rc);
00640 }
00641 return APR_SUCCESS;
00642 }
00643
00644 #endif