~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to os/win32/ap_regkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#ifdef WIN32
 
18
 
 
19
#include "apr.h"
 
20
#include "arch/win32/apr_arch_file_io.h"
 
21
#include "arch/win32/apr_arch_misc.h"
 
22
#include "ap_regkey.h"
 
23
 
 
24
struct ap_regkey_t {
 
25
    apr_pool_t *pool;
 
26
    HKEY        hkey;
 
27
};
 
28
 
 
29
 
 
30
AP_DECLARE(const ap_regkey_t *) ap_regkey_const(int i)
 
31
{
 
32
    static struct ap_regkey_t ap_regkey_consts[7] =
 
33
    {
 
34
        {NULL, HKEY_CLASSES_ROOT},
 
35
        {NULL, HKEY_CURRENT_CONFIG},
 
36
        {NULL, HKEY_CURRENT_USER},
 
37
        {NULL, HKEY_LOCAL_MACHINE},
 
38
        {NULL, HKEY_USERS},
 
39
        {NULL, HKEY_PERFORMANCE_DATA},
 
40
        {NULL, HKEY_DYN_DATA}
 
41
    };
 
42
    return ap_regkey_consts + i;
 
43
}
 
44
 
 
45
 
 
46
apr_status_t regkey_cleanup(void *key)
 
47
{
 
48
    ap_regkey_t *regkey = key;
 
49
 
 
50
    if (regkey->hkey && regkey->hkey != INVALID_HANDLE_VALUE) {
 
51
        RegCloseKey(regkey->hkey);
 
52
        regkey->hkey = INVALID_HANDLE_VALUE;
 
53
    }
 
54
    return APR_SUCCESS;
 
55
}
 
56
 
 
57
 
 
58
AP_DECLARE(apr_status_t) ap_regkey_open(ap_regkey_t **newkey,
 
59
                                        const ap_regkey_t *parentkey,
 
60
                                        const char *keyname,
 
61
                                        apr_int32_t flags,
 
62
                                        apr_pool_t *pool)
 
63
{
 
64
    DWORD access = KEY_QUERY_VALUE;
 
65
    DWORD exists;
 
66
    HKEY hkey;
 
67
    LONG rc;
 
68
 
 
69
    if (flags & APR_READ)
 
70
        access |= KEY_READ;
 
71
    if (flags & APR_WRITE)
 
72
        access |= KEY_WRITE;
 
73
 
 
74
#if APR_HAS_UNICODE_FS
 
75
    IF_WIN_OS_IS_UNICODE
 
76
    {
 
77
        apr_size_t keylen = strlen(keyname) + 1;
 
78
        apr_size_t wkeylen = 256;
 
79
        apr_wchar_t wkeyname[256];
 
80
        apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen);
 
81
        if (rv != APR_SUCCESS)
 
82
            return rv;
 
83
        else if (keylen)
 
84
            return APR_ENAMETOOLONG;
 
85
 
 
86
        if (flags & APR_CREATE)
 
87
            rc = RegCreateKeyExW(parentkey->hkey, wkeyname, 0, NULL, 0,
 
88
                                 access, NULL, &hkey, &exists);
 
89
        else
 
90
            rc = RegOpenKeyExW(parentkey->hkey, wkeyname, 0, access, &hkey);
 
91
    }
 
92
#endif /* APR_HAS_UNICODE_FS */
 
93
#if APR_HAS_ANSI_FS
 
94
    ELSE_WIN_OS_IS_ANSI
 
95
    {
 
96
        if (flags & APR_CREATE)
 
97
            rc = RegCreateKeyEx(parentkey->hkey, keyname, 0, NULL, 0,
 
98
                                access, NULL, &hkey, &exists);
 
99
        else
 
100
            rc = RegOpenKeyEx(parentkey->hkey, keyname, 0, access, &hkey);
 
101
    }
 
102
#endif
 
103
    if (rc != ERROR_SUCCESS) {
 
104
        return APR_FROM_OS_ERROR(rc);
 
105
    }
 
106
    if ((flags & APR_EXCL) && (exists == REG_OPENED_EXISTING_KEY)) {
 
107
        RegCloseKey(hkey);
 
108
        return APR_EEXIST;
 
109
    }
 
110
 
 
111
    *newkey = apr_palloc(pool, sizeof(**newkey));
 
112
    (*newkey)->pool = pool;
 
113
    (*newkey)->hkey = hkey;
 
114
    apr_pool_cleanup_register((*newkey)->pool, (void *)(*newkey),
 
115
                              regkey_cleanup, apr_pool_cleanup_null);
 
116
    return APR_SUCCESS;
 
117
}
 
118
 
 
119
 
 
120
AP_DECLARE(apr_status_t) ap_regkey_close(ap_regkey_t *regkey)
 
121
{
 
122
    apr_status_t stat;
 
123
    if ((stat = regkey_cleanup(regkey)) == APR_SUCCESS) {
 
124
        apr_pool_cleanup_kill(regkey->pool, regkey, regkey_cleanup);
 
125
    }
 
126
    return stat;
 
127
}
 
128
 
 
129
 
 
130
AP_DECLARE(apr_status_t) ap_regkey_remove(const ap_regkey_t *parent,
 
131
                                          const char *keyname,
 
132
                                          apr_pool_t *pool)
 
133
{
 
134
    LONG rc;
 
135
 
 
136
#if APR_HAS_UNICODE_FS
 
137
    IF_WIN_OS_IS_UNICODE
 
138
    {
 
139
        apr_size_t keylen = strlen(keyname) + 1;
 
140
        apr_size_t wkeylen = 256;
 
141
        apr_wchar_t wkeyname[256];
 
142
        apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen);
 
143
        if (rv != APR_SUCCESS)
 
144
            return rv;
 
145
        else if (keylen)
 
146
            return APR_ENAMETOOLONG;
 
147
        rc = RegDeleteKeyW(parent->hkey, wkeyname);
 
148
    }
 
149
#endif /* APR_HAS_UNICODE_FS */
 
150
#if APR_HAS_ANSI_FS
 
151
    ELSE_WIN_OS_IS_ANSI
 
152
    {
 
153
        /* We need to determine if subkeys exist on Win9x, to provide
 
154
         * consistent behavior with NT, which returns access denied
 
155
         * if subkeys exist when attempting to delete a key.
 
156
         */
 
157
        DWORD subkeys;
 
158
        HKEY hkey;
 
159
        rc = RegOpenKeyEx(parent->hkey, keyname, 0, KEY_READ, &hkey);
 
160
        if (rc != ERROR_SUCCESS)
 
161
            return APR_FROM_OS_ERROR(rc);
 
162
        rc = RegQueryInfoKey(hkey, NULL, NULL, NULL, &subkeys, NULL, NULL,
 
163
                             NULL, NULL, NULL, NULL, NULL);
 
164
        RegCloseKey(hkey);
 
165
        if (rc != ERROR_SUCCESS)
 
166
            return APR_FROM_OS_ERROR(rc);
 
167
        else if (subkeys)
 
168
            return APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED);
 
169
        rc = RegDeleteKey(parent->hkey, keyname);
 
170
    }
 
171
#endif
 
172
    if (rc != ERROR_SUCCESS) {
 
173
        return APR_FROM_OS_ERROR(rc);
 
174
    }
 
175
    return APR_SUCCESS;
 
176
}
 
177
 
 
178
 
 
179
AP_DECLARE(apr_status_t) ap_regkey_value_get(char **result,
 
180
                                             ap_regkey_t *key,
 
181
                                             const char *valuename,
 
182
                                             apr_pool_t *pool)
 
183
{
 
184
    /* Retrieve a registry string value, and explode any envvars
 
185
     * that the system has configured (e.g. %SystemRoot%/someapp.exe)
 
186
     */
 
187
    LONG rc;
 
188
    DWORD type;
 
189
    apr_size_t size = 0;
 
190
 
 
191
#if APR_HAS_UNICODE_FS
 
192
    IF_WIN_OS_IS_UNICODE
 
193
    {
 
194
        apr_size_t valuelen = strlen(valuename) + 1;
 
195
        apr_size_t wvallen = 256;
 
196
        apr_wchar_t wvalname[256];
 
197
        apr_wchar_t *wvalue;
 
198
        apr_status_t rv;
 
199
        rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
 
200
        if (rv != APR_SUCCESS)
 
201
            return rv;
 
202
        else if (valuelen)
 
203
            return APR_ENAMETOOLONG;
 
204
        /* Read to NULL buffer to determine value size */
 
205
        rc = RegQueryValueExW(key->hkey, wvalname, 0, &type, NULL, (DWORD *)&size);
 
206
        if (rc != ERROR_SUCCESS) {
 
207
            return APR_FROM_OS_ERROR(rc);
 
208
        }
 
209
        if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
 
210
            return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER);
 
211
        }
 
212
 
 
213
        wvalue = apr_palloc(pool, size);
 
214
        /* Read value based on size query above */
 
215
        rc = RegQueryValueExW(key->hkey, wvalname, 0, &type,
 
216
                              (LPBYTE)wvalue, (DWORD *)&size);
 
217
        if (rc != ERROR_SUCCESS) {
 
218
            return APR_FROM_OS_ERROR(rc);
 
219
        }
 
220
        if (type == REG_EXPAND_SZ) {
 
221
            apr_wchar_t zbuf[1];
 
222
            size = ExpandEnvironmentStringsW(wvalue, zbuf, 0);
 
223
            if (size) {
 
224
                apr_wchar_t *tmp = wvalue;
 
225
                /* The size returned by ExpandEnvironmentStringsW is wchars */
 
226
                wvalue = apr_palloc(pool, size * 2);
 
227
                size = ExpandEnvironmentStringsW(tmp, wvalue, (DWORD)size);
 
228
            }
 
229
        }
 
230
        else {
 
231
            /* count wchars from RegQueryValueExW, rather than bytes */
 
232
            size /= 2;
 
233
        }
 
234
        /* ###: deliberately overallocate all but the trailing null.
 
235
         * We could precalculate the exact buffer here instead, the question
 
236
         * is a matter of storage v.s. cpu cycles.
 
237
         */
 
238
        valuelen = (size - 1) * 3 + 1;
 
239
        *result = apr_palloc(pool, valuelen);
 
240
        rv = apr_conv_ucs2_to_utf8(wvalue, &size, *result, &valuelen);
 
241
        if (rv != APR_SUCCESS)
 
242
            return rv;
 
243
        else if (size)
 
244
            return APR_ENAMETOOLONG;
 
245
    }
 
246
#endif /* APR_HAS_UNICODE_FS */
 
247
#if APR_HAS_ANSI_FS
 
248
    ELSE_WIN_OS_IS_ANSI
 
249
    {
 
250
        /* Read to NULL buffer to determine value size */
 
251
        rc = RegQueryValueEx(key->hkey, valuename, 0, &type, NULL, (DWORD *)&size);
 
252
        if (rc != ERROR_SUCCESS)
 
253
            return APR_FROM_OS_ERROR(rc);
 
254
 
 
255
        if ((size < 1) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
 
256
            return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER);
 
257
        }
 
258
 
 
259
        *result = apr_palloc(pool, size);
 
260
        /* Read value based on size query above */
 
261
        rc = RegQueryValueEx(key->hkey, valuename, 0, &type, *result, (DWORD *)&size);
 
262
        if (rc != ERROR_SUCCESS)
 
263
            return APR_FROM_OS_ERROR(rc);
 
264
 
 
265
        if (type == REG_EXPAND_SZ) {
 
266
            /* Advise ExpandEnvironmentStrings that we have a zero char
 
267
             * buffer to force computation of the required length.
 
268
             */
 
269
            char zbuf[1];
 
270
            size = ExpandEnvironmentStrings(*result, zbuf, 0);
 
271
            if (size) {
 
272
                char *tmp = *result;
 
273
                *result = apr_palloc(pool, size);
 
274
                size = ExpandEnvironmentStrings(tmp, *result, (DWORD)size);
 
275
            }
 
276
        }
 
277
    }
 
278
#endif
 
279
    return APR_SUCCESS;
 
280
}
 
281
 
 
282
 
 
283
AP_DECLARE(apr_status_t) ap_regkey_value_set(ap_regkey_t *key,
 
284
                                             const char *valuename,
 
285
                                             const char *value,
 
286
                                             apr_int32_t flags,
 
287
                                             apr_pool_t *pool)
 
288
{
 
289
    /* Retrieve a registry string value, and explode any envvars
 
290
     * that the system has configured (e.g. %SystemRoot%/someapp.exe)
 
291
     */
 
292
    LONG rc;
 
293
    apr_size_t size = strlen(value) + 1;
 
294
    DWORD type = (flags & AP_REGKEY_EXPAND) ? REG_EXPAND_SZ : REG_SZ;
 
295
 
 
296
#if APR_HAS_UNICODE_FS
 
297
    IF_WIN_OS_IS_UNICODE
 
298
    {
 
299
        apr_size_t alloclen;
 
300
        apr_size_t valuelen = strlen(valuename) + 1;
 
301
        apr_size_t wvallen = 256;
 
302
        apr_wchar_t wvalname[256];
 
303
        apr_wchar_t *wvalue;
 
304
        apr_status_t rv;
 
305
        rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
 
306
        if (rv != APR_SUCCESS)
 
307
            return rv;
 
308
        else if (valuelen)
 
309
            return APR_ENAMETOOLONG;
 
310
 
 
311
        wvallen = alloclen = size;
 
312
        wvalue = apr_palloc(pool, alloclen * 2);
 
313
        rv = apr_conv_utf8_to_ucs2(value, &size, wvalue, &wvallen);
 
314
        if (rv != APR_SUCCESS)
 
315
            return rv;
 
316
        else if (size)
 
317
            return APR_ENAMETOOLONG;
 
318
 
 
319
        /* The size is the number of wchars consumed by apr_conv_utf8_to_ucs2
 
320
         * converted to bytes; the trailing L'\0' continues to be counted.
 
321
         */
 
322
        size = (alloclen - wvallen) * 2;
 
323
        rc = RegSetValueExW(key->hkey, wvalname, 0, type,
 
324
                            (LPBYTE)wvalue, (DWORD)size);
 
325
        if (rc != ERROR_SUCCESS)
 
326
            return APR_FROM_OS_ERROR(rc);
 
327
    }
 
328
#endif /* APR_HAS_UNICODE_FS */
 
329
#if APR_HAS_ANSI_FS
 
330
    ELSE_WIN_OS_IS_ANSI
 
331
    {
 
332
        rc = RegSetValueEx(key->hkey, valuename, 0, type, value, (DWORD)size);
 
333
        if (rc != ERROR_SUCCESS)
 
334
            return APR_FROM_OS_ERROR(rc);
 
335
    }
 
336
#endif
 
337
    return APR_SUCCESS;
 
338
}
 
339
 
 
340
 
 
341
AP_DECLARE(apr_status_t) ap_regkey_value_raw_get(void **result,
 
342
                                                 apr_size_t *resultsize,
 
343
                                                 apr_int32_t *resulttype,
 
344
                                                 ap_regkey_t *key,
 
345
                                                 const char *valuename,
 
346
                                                 apr_pool_t *pool)
 
347
{
 
348
    /* Retrieve a registry string value, and explode any envvars
 
349
     * that the system has configured (e.g. %SystemRoot%/someapp.exe)
 
350
     */
 
351
    LONG rc;
 
352
 
 
353
#if APR_HAS_UNICODE_FS
 
354
    IF_WIN_OS_IS_UNICODE
 
355
    {
 
356
        apr_size_t valuelen = strlen(valuename) + 1;
 
357
        apr_size_t wvallen = 256;
 
358
        apr_wchar_t wvalname[256];
 
359
        apr_status_t rv;
 
360
        rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
 
361
        if (rv != APR_SUCCESS)
 
362
            return rv;
 
363
        else if (valuelen)
 
364
            return APR_ENAMETOOLONG;
 
365
        /* Read to NULL buffer to determine value size */
 
366
        rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype,
 
367
                              NULL, (LPDWORD)resultsize);
 
368
        if (rc != ERROR_SUCCESS) {
 
369
            return APR_FROM_OS_ERROR(rc);
 
370
        }
 
371
 
 
372
        /* Read value based on size query above */
 
373
        *result = apr_palloc(pool, *resultsize);
 
374
        rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype,
 
375
                             (LPBYTE)*result, (LPDWORD)resultsize);
 
376
    }
 
377
#endif /* APR_HAS_UNICODE_FS */
 
378
#if APR_HAS_ANSI_FS
 
379
    ELSE_WIN_OS_IS_ANSI
 
380
    {
 
381
        /* Read to NULL buffer to determine value size */
 
382
        rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype,
 
383
                             NULL, (LPDWORD)resultsize);
 
384
        if (rc != ERROR_SUCCESS)
 
385
            return APR_FROM_OS_ERROR(rc);
 
386
 
 
387
        /* Read value based on size query above */
 
388
        *result = apr_palloc(pool, *resultsize);
 
389
        rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype,
 
390
                             (LPBYTE)*result, (LPDWORD)resultsize);
 
391
        if (rc != ERROR_SUCCESS)
 
392
            return APR_FROM_OS_ERROR(rc);
 
393
    }
 
394
#endif
 
395
    if (rc != ERROR_SUCCESS) {
 
396
        return APR_FROM_OS_ERROR(rc);
 
397
    }
 
398
 
 
399
    return APR_SUCCESS;
 
400
}
 
401
 
 
402
 
 
403
AP_DECLARE(apr_status_t) ap_regkey_value_raw_set(ap_regkey_t *key,
 
404
                                                 const char *valuename,
 
405
                                                 const void *value,
 
406
                                                 apr_size_t valuesize,
 
407
                                                 apr_int32_t valuetype,
 
408
                                                 apr_pool_t *pool)
 
409
{
 
410
    LONG rc;
 
411
 
 
412
#if APR_HAS_UNICODE_FS
 
413
    IF_WIN_OS_IS_UNICODE
 
414
    {
 
415
        apr_size_t valuelen = strlen(valuename) + 1;
 
416
        apr_size_t wvallen = 256;
 
417
        apr_wchar_t wvalname[256];
 
418
        apr_status_t rv;
 
419
        rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
 
420
        if (rv != APR_SUCCESS)
 
421
            return rv;
 
422
        else if (valuelen)
 
423
            return APR_ENAMETOOLONG;
 
424
 
 
425
        rc = RegSetValueExW(key->hkey, wvalname, 0, valuetype,
 
426
                            (LPBYTE)value, (DWORD)valuesize);
 
427
    }
 
428
#endif /* APR_HAS_UNICODE_FS */
 
429
#if APR_HAS_ANSI_FS
 
430
    ELSE_WIN_OS_IS_ANSI
 
431
    {
 
432
        rc = RegSetValueEx(key->hkey, valuename, 0, valuetype,
 
433
                            (LPBYTE)value, (DWORD)valuesize);
 
434
    }
 
435
#endif
 
436
    if (rc != ERROR_SUCCESS) {
 
437
        return APR_FROM_OS_ERROR(rc);
 
438
    }
 
439
    return APR_SUCCESS;
 
440
}
 
441
 
 
442
 
 
443
AP_DECLARE(apr_status_t) ap_regkey_value_array_get(apr_array_header_t **result,
 
444
                                                   ap_regkey_t *key,
 
445
                                                   const char *valuename,
 
446
                                                   apr_pool_t *pool)
 
447
{
 
448
    /* Retrieve a registry string value, and explode any envvars
 
449
     * that the system has configured (e.g. %SystemRoot%/someapp.exe)
 
450
     */
 
451
    apr_status_t rv;
 
452
    void *value;
 
453
    char *buf;
 
454
    char *tmp;
 
455
    DWORD type;
 
456
    apr_size_t size = 0;
 
457
 
 
458
    rv = ap_regkey_value_raw_get(&value, &size, &type, key, valuename, pool);
 
459
    if (rv != APR_SUCCESS) {
 
460
        return rv;
 
461
    }
 
462
    else if (type != REG_MULTI_SZ) {
 
463
        return APR_EINVAL;
 
464
    }
 
465
 
 
466
#if APR_HAS_UNICODE_FS
 
467
    IF_WIN_OS_IS_UNICODE
 
468
    {
 
469
        apr_size_t alloclen;
 
470
        apr_size_t valuelen = strlen(valuename) + 1;
 
471
        apr_size_t wvallen = 256;
 
472
        apr_wchar_t *wvalue = (apr_wchar_t *)value;
 
473
 
 
474
        /* ###: deliberately overallocate plus two extra nulls.
 
475
         * We could precalculate the exact buffer here instead, the question
 
476
         * is a matter of storage v.s. cpu cycles.
 
477
         */
 
478
        size /= 2;
 
479
        alloclen = valuelen = size * 3 + 2;
 
480
        buf = apr_palloc(pool, valuelen);
 
481
        rv = apr_conv_ucs2_to_utf8(value, &size, buf, &valuelen);
 
482
        if (rv != APR_SUCCESS)
 
483
            return rv;
 
484
        else if (size)
 
485
            return APR_ENAMETOOLONG;
 
486
        buf[(alloclen - valuelen)] = '\0';
 
487
        buf[(alloclen - valuelen) + 1] = '\0';
 
488
    }
 
489
#endif /* APR_HAS_UNICODE_FS */
 
490
#if APR_HAS_ANSI_FS
 
491
    ELSE_WIN_OS_IS_ANSI
 
492
    {
 
493
        /* Small possiblity the array is either unterminated
 
494
         * or single NULL terminated.  Avert.
 
495
         */
 
496
        buf = (char *)value;
 
497
        if (size < 2 || buf[size - 1] != '\0' || buf[size - 2] != '\0') {
 
498
            buf = apr_palloc(pool, size + 2);
 
499
            memcpy(buf, value, size);
 
500
            buf[size + 1] = '\0';
 
501
            buf[size] = '\0';
 
502
        }
 
503
    }
 
504
#endif
 
505
 
 
506
    size = 0;    /* Element Count */
 
507
    for (tmp = buf; *tmp; ++tmp) {
 
508
        ++size;
 
509
        while (*tmp) {
 
510
            ++tmp;
 
511
        }
 
512
    }
 
513
 
 
514
    *result = apr_array_make(pool, (int)size, sizeof(char *));
 
515
    for (tmp = buf; *tmp; ++tmp) {
 
516
        char **newelem = (char **) apr_array_push(*result);
 
517
        *newelem = tmp;
 
518
        while (*tmp) {
 
519
            ++tmp;
 
520
        }
 
521
    }
 
522
 
 
523
   return APR_SUCCESS;
 
524
}
 
525
 
 
526
 
 
527
AP_DECLARE(apr_status_t) ap_regkey_value_array_set(ap_regkey_t *key,
 
528
                                                   const char *valuename,
 
529
                                                   int nelts,
 
530
                                                   const char * const * elts,
 
531
                                                   apr_pool_t *pool)
 
532
{
 
533
    /* Retrieve a registry string value, and explode any envvars
 
534
     * that the system has configured (e.g. %SystemRoot%/someapp.exe)
 
535
     */
 
536
    int i;
 
537
    const void *value;
 
538
    apr_size_t bufsize;
 
539
 
 
540
#if APR_HAS_UNICODE_FS
 
541
    IF_WIN_OS_IS_UNICODE
 
542
    {
 
543
        apr_status_t rv;
 
544
        apr_wchar_t *buf;
 
545
        apr_wchar_t *tmp;
 
546
        apr_size_t bufrem;
 
547
 
 
548
        bufsize = 1; /* For trailing second null */
 
549
        for (i = 0; i < nelts; ++i) {
 
550
            bufsize += strlen(elts[i]) + 1;
 
551
        }
 
552
        if (!nelts) {
 
553
            ++bufsize;
 
554
        }
 
555
 
 
556
        bufrem = bufsize;
 
557
        buf = apr_palloc(pool, bufsize * 2);
 
558
        tmp = buf;
 
559
        for (i = 0; i < nelts; ++i) {
 
560
            apr_size_t eltsize = strlen(elts[i]) + 1;
 
561
            apr_size_t size = eltsize;
 
562
            rv = apr_conv_utf8_to_ucs2(elts[i], &size, tmp, &bufrem);
 
563
            if (rv != APR_SUCCESS)
 
564
                return rv;
 
565
            else if (size)
 
566
                return APR_ENAMETOOLONG;
 
567
            tmp += eltsize;
 
568
        }
 
569
        if (!nelts) {
 
570
            --bufrem;
 
571
            (*tmp++) = L'\0';
 
572
        }
 
573
        --bufrem;
 
574
        *tmp = L'\0'; /* Trailing second null */
 
575
 
 
576
        bufsize = (bufsize - bufrem) * 2;
 
577
        value = (void*)buf;
 
578
    }
 
579
#endif /* APR_HAS_UNICODE_FS */
 
580
#if APR_HAS_ANSI_FS
 
581
    ELSE_WIN_OS_IS_ANSI
 
582
    {
 
583
        char *buf;
 
584
        char *tmp;
 
585
 
 
586
        bufsize = 1; /* For trailing second null */
 
587
        for (i = 0; i < nelts; ++i) {
 
588
            bufsize += strlen(elts[i]) + 1;
 
589
        }
 
590
        if (!nelts) {
 
591
            ++bufsize;
 
592
        }
 
593
        buf = apr_palloc(pool, bufsize);
 
594
        tmp = buf;
 
595
        for (i = 0; i < nelts; ++i) {
 
596
            apr_size_t len = strlen(elts[i]) + 1;
 
597
            memcpy(tmp, elts[i], len);
 
598
            tmp += len;
 
599
        }
 
600
        if (!nelts) {
 
601
            (*tmp++) = '\0';
 
602
        }
 
603
        *tmp = '\0'; /* Trailing second null */
 
604
        value = buf;
 
605
    }
 
606
#endif
 
607
    return ap_regkey_value_raw_set(key, valuename, value,
 
608
                                   bufsize, REG_MULTI_SZ, pool);
 
609
}
 
610
 
 
611
 
 
612
AP_DECLARE(apr_status_t) ap_regkey_value_remove(const ap_regkey_t *key,
 
613
                                                const char *valuename,
 
614
                                                apr_pool_t *pool)
 
615
{
 
616
    LONG rc;
 
617
 
 
618
#if APR_HAS_UNICODE_FS
 
619
    IF_WIN_OS_IS_UNICODE
 
620
    {
 
621
        apr_size_t valuelen = strlen(valuename) + 1;
 
622
        apr_size_t wvallen = 256;
 
623
        apr_wchar_t wvalname[256];
 
624
        apr_status_t rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen);
 
625
        if (rv != APR_SUCCESS)
 
626
            return rv;
 
627
        else if (valuelen)
 
628
            return APR_ENAMETOOLONG;
 
629
        rc = RegDeleteValueW(key->hkey, wvalname);
 
630
    }
 
631
#endif /* APR_HAS_UNICODE_FS */
 
632
#if APR_HAS_ANSI_FS
 
633
    ELSE_WIN_OS_IS_ANSI
 
634
    {
 
635
        rc = RegDeleteValue(key->hkey, valuename);
 
636
    }
 
637
#endif
 
638
    if (rc != ERROR_SUCCESS) {
 
639
        return APR_FROM_OS_ERROR(rc);
 
640
    }
 
641
    return APR_SUCCESS;
 
642
}
 
643
 
 
644
#endif /* defined WIN32 */