~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/registry/reg_api.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  Virtual Windows Registry Layer
 
4
 *  Copyright (C) Volker Lendecke 2006
 
5
 *  Copyright (C) Michael Adam 2007-2008
 
6
 *
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation; either version 3 of the License, or
 
10
 *  (at your option) any later version.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
/* Attempt to wrap the existing API in a more winreg.idl-like way */
 
22
 
 
23
/*
 
24
 * Here is a list of winreg.idl functions and corresponding implementations
 
25
 * provided here:
 
26
 *
 
27
 * 0x00         winreg_OpenHKCR
 
28
 * 0x01         winreg_OpenHKCU
 
29
 * 0x02         winreg_OpenHKLM
 
30
 * 0x03         winreg_OpenHKPD
 
31
 * 0x04         winreg_OpenHKU
 
32
 * 0x05         winreg_CloseKey
 
33
 * 0x06         winreg_CreateKey                        reg_createkey
 
34
 * 0x07         winreg_DeleteKey                        reg_deletekey
 
35
 * 0x08         winreg_DeleteValue                      reg_deletevalue
 
36
 * 0x09         winreg_EnumKey                          reg_enumkey
 
37
 * 0x0a         winreg_EnumValue                        reg_enumvalue
 
38
 * 0x0b         winreg_FlushKey
 
39
 * 0x0c         winreg_GetKeySecurity                   reg_getkeysecurity
 
40
 * 0x0d         winreg_LoadKey
 
41
 * 0x0e         winreg_NotifyChangeKeyValue
 
42
 * 0x0f         winreg_OpenKey                          reg_openkey
 
43
 * 0x10         winreg_QueryInfoKey                     reg_queryinfokey
 
44
 * 0x11         winreg_QueryValue                       reg_queryvalue
 
45
 * 0x12         winreg_ReplaceKey
 
46
 * 0x13         winreg_RestoreKey                       reg_restorekey
 
47
 * 0x14         winreg_SaveKey                          reg_savekey
 
48
 * 0x15         winreg_SetKeySecurity                   reg_setkeysecurity
 
49
 * 0x16         winreg_SetValue                         reg_setvalue
 
50
 * 0x17         winreg_UnLoadKey
 
51
 * 0x18         winreg_InitiateSystemShutdown
 
52
 * 0x19         winreg_AbortSystemShutdown
 
53
 * 0x1a         winreg_GetVersion                       reg_getversion
 
54
 * 0x1b         winreg_OpenHKCC
 
55
 * 0x1c         winreg_OpenHKDD
 
56
 * 0x1d         winreg_QueryMultipleValues
 
57
 * 0x1e         winreg_InitiateSystemShutdownEx
 
58
 * 0x1f         winreg_SaveKeyEx
 
59
 * 0x20         winreg_OpenHKPT
 
60
 * 0x21         winreg_OpenHKPN
 
61
 * 0x22         winreg_QueryMultipleValues2
 
62
 *
 
63
 */
 
64
 
 
65
#include "includes.h"
 
66
#include "regfio.h"
 
67
 
 
68
#undef DBGC_CLASS
 
69
#define DBGC_CLASS DBGC_REGISTRY
 
70
 
 
71
 
 
72
/**********************************************************************
 
73
 * Helper functions
 
74
 **********************************************************************/
 
75
 
 
76
static WERROR fill_value_cache(struct registry_key *key)
 
77
{
 
78
        if (key->values != NULL) {
 
79
                if (!reg_values_need_update(key->key, key->values)) {
 
80
                        return WERR_OK;
 
81
                }
 
82
        }
 
83
 
 
84
        if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
 
85
                return WERR_NOMEM;
 
86
        }
 
87
        if (fetch_reg_values(key->key, key->values) == -1) {
 
88
                TALLOC_FREE(key->values);
 
89
                return WERR_BADFILE;
 
90
        }
 
91
 
 
92
        return WERR_OK;
 
93
}
 
94
 
 
95
static WERROR fill_subkey_cache(struct registry_key *key)
 
96
{
 
97
        WERROR werr;
 
98
 
 
99
        if (key->subkeys != NULL) {
 
100
                if (!reg_subkeys_need_update(key->key, key->subkeys)) {
 
101
                        return WERR_OK;
 
102
                }
 
103
        }
 
104
 
 
105
        werr = regsubkey_ctr_init(key, &(key->subkeys));
 
106
        W_ERROR_NOT_OK_RETURN(werr);
 
107
 
 
108
        if (fetch_reg_keys(key->key, key->subkeys) == -1) {
 
109
                TALLOC_FREE(key->subkeys);
 
110
                return WERR_NO_MORE_ITEMS;
 
111
        }
 
112
 
 
113
        return WERR_OK;
 
114
}
 
115
 
 
116
static int regkey_destructor(REGISTRY_KEY *key)
 
117
{
 
118
        return regdb_close();
 
119
}
 
120
 
 
121
static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, 
 
122
                                   struct registry_key *parent,
 
123
                                   const char *name,
 
124
                                   const struct nt_user_token *token,
 
125
                                   uint32 access_desired,
 
126
                                   struct registry_key **pregkey)
 
127
{
 
128
        WERROR          result = WERR_OK;
 
129
        struct registry_key *regkey;
 
130
        REGISTRY_KEY *key;
 
131
        struct regsubkey_ctr    *subkeys = NULL;
 
132
 
 
133
        DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
 
134
 
 
135
        SMB_ASSERT(strchr(name, '\\') == NULL);
 
136
 
 
137
        if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
 
138
            !(regkey->token = dup_nt_token(regkey, token)) ||
 
139
            !(regkey->key = TALLOC_ZERO_P(regkey, REGISTRY_KEY))) {
 
140
                result = WERR_NOMEM;
 
141
                goto done;
 
142
        }
 
143
 
 
144
        if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
 
145
                goto done;
 
146
        }
 
147
 
 
148
        key = regkey->key;
 
149
        talloc_set_destructor(key, regkey_destructor);
 
150
                
 
151
        /* initialization */
 
152
        
 
153
        key->type = REG_KEY_GENERIC;
 
154
 
 
155
        if (name[0] == '\0') {
 
156
                /*
 
157
                 * Open a copy of the parent key
 
158
                 */
 
159
                if (!parent) {
 
160
                        result = WERR_BADFILE;
 
161
                        goto done;
 
162
                }
 
163
                key->name = talloc_strdup(key, parent->key->name);
 
164
        }
 
165
        else {
 
166
                /*
 
167
                 * Normal subkey open
 
168
                 */
 
169
                key->name = talloc_asprintf(key, "%s%s%s",
 
170
                                            parent ? parent->key->name : "",
 
171
                                            parent ? "\\": "",
 
172
                                            name);
 
173
        }
 
174
 
 
175
        if (key->name == NULL) {
 
176
                result = WERR_NOMEM;
 
177
                goto done;
 
178
        }
 
179
 
 
180
        /* Tag this as a Performance Counter Key */
 
181
 
 
182
        if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
 
183
                key->type = REG_KEY_HKPD;
 
184
        
 
185
        /* Look up the table of registry I/O operations */
 
186
 
 
187
        if ( !(key->ops = reghook_cache_find( key->name )) ) {
 
188
                DEBUG(0,("reg_open_onelevel: Failed to assign "
 
189
                         "REGISTRY_OPS to [%s]\n", key->name ));
 
190
                result = WERR_BADFILE;
 
191
                goto done;
 
192
        }
 
193
 
 
194
        /* check if the path really exists; failed is indicated by -1 */
 
195
        /* if the subkey count failed, bail out */
 
196
 
 
197
        result = regsubkey_ctr_init(key, &subkeys);
 
198
        if (!W_ERROR_IS_OK(result)) {
 
199
                goto done;
 
200
        }
 
201
 
 
202
        if ( fetch_reg_keys( key, subkeys ) == -1 )  {
 
203
                result = WERR_BADFILE;
 
204
                goto done;
 
205
        }
 
206
 
 
207
        TALLOC_FREE( subkeys );
 
208
 
 
209
        if ( !regkey_access_check( key, access_desired, &key->access_granted,
 
210
                                   token ) ) {
 
211
                result = WERR_ACCESS_DENIED;
 
212
                goto done;
 
213
        }
 
214
 
 
215
        *pregkey = regkey;
 
216
        result = WERR_OK;
 
217
        
 
218
done:
 
219
        if ( !W_ERROR_IS_OK(result) ) {
 
220
                TALLOC_FREE(regkey);
 
221
        }
 
222
 
 
223
        return result;
 
224
}
 
225
 
 
226
WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
 
227
                    uint32 desired_access,
 
228
                    const struct nt_user_token *token,
 
229
                    struct registry_key **pkey)
 
230
{
 
231
        SMB_ASSERT(hive != NULL);
 
232
        SMB_ASSERT(hive[0] != '\0');
 
233
        SMB_ASSERT(strchr(hive, '\\') == NULL);
 
234
 
 
235
        return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
 
236
                                    pkey);
 
237
}
 
238
 
 
239
 
 
240
/**********************************************************************
 
241
 * The API functions
 
242
 **********************************************************************/
 
243
 
 
244
WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
 
245
                   const char *name, uint32 desired_access,
 
246
                   struct registry_key **pkey)
 
247
{
 
248
        struct registry_key *direct_parent = parent;
 
249
        WERROR err;
 
250
        char *p, *path, *to_free;
 
251
        size_t len;
 
252
 
 
253
        if (!(path = SMB_STRDUP(name))) {
 
254
                return WERR_NOMEM;
 
255
        }
 
256
        to_free = path;
 
257
 
 
258
        len = strlen(path);
 
259
 
 
260
        if ((len > 0) && (path[len-1] == '\\')) {
 
261
                path[len-1] = '\0';
 
262
        }
 
263
 
 
264
        while ((p = strchr(path, '\\')) != NULL) {
 
265
                char *name_component;
 
266
                struct registry_key *tmp;
 
267
 
 
268
                if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
 
269
                        err = WERR_NOMEM;
 
270
                        goto error;
 
271
                }
 
272
 
 
273
                err = regkey_open_onelevel(mem_ctx, direct_parent,
 
274
                                           name_component, parent->token,
 
275
                                           KEY_ENUMERATE_SUB_KEYS, &tmp);
 
276
                SAFE_FREE(name_component);
 
277
 
 
278
                if (!W_ERROR_IS_OK(err)) {
 
279
                        goto error;
 
280
                }
 
281
                if (direct_parent != parent) {
 
282
                        TALLOC_FREE(direct_parent);
 
283
                }
 
284
 
 
285
                direct_parent = tmp;
 
286
                path = p+1;
 
287
        }
 
288
 
 
289
        err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
 
290
                                   desired_access, pkey);
 
291
 error:
 
292
        if (direct_parent != parent) {
 
293
                TALLOC_FREE(direct_parent);
 
294
        }
 
295
        SAFE_FREE(to_free);
 
296
        return err;
 
297
}
 
298
 
 
299
WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
 
300
                   uint32 idx, char **name, NTTIME *last_write_time)
 
301
{
 
302
        WERROR err;
 
303
 
 
304
        if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) {
 
305
                return WERR_ACCESS_DENIED;
 
306
        }
 
307
 
 
308
        if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
 
309
                return err;
 
310
        }
 
311
 
 
312
        if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
 
313
                return WERR_NO_MORE_ITEMS;
 
314
        }
 
315
 
 
316
        if (!(*name = talloc_strdup(mem_ctx,
 
317
                        regsubkey_ctr_specific_key(key->subkeys, idx))))
 
318
        {
 
319
                return WERR_NOMEM;
 
320
        }
 
321
 
 
322
        if (last_write_time) {
 
323
                *last_write_time = 0;
 
324
        }
 
325
 
 
326
        return WERR_OK;
 
327
}
 
328
 
 
329
WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
 
330
                     uint32 idx, char **pname, struct registry_value **pval)
 
331
{
 
332
        struct registry_value *val;
 
333
        WERROR err;
 
334
 
 
335
        if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
 
336
                return WERR_ACCESS_DENIED;
 
337
        }
 
338
 
 
339
        if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
 
340
                return err;
 
341
        }
 
342
 
 
343
        if (idx >= key->values->num_values) {
 
344
                return WERR_NO_MORE_ITEMS;
 
345
        }
 
346
 
 
347
        err = registry_pull_value(mem_ctx, &val,
 
348
                                  key->values->values[idx]->type,
 
349
                                  key->values->values[idx]->data_p,
 
350
                                  key->values->values[idx]->size,
 
351
                                  key->values->values[idx]->size);
 
352
        if (!W_ERROR_IS_OK(err)) {
 
353
                return err;
 
354
        }
 
355
 
 
356
        if (pname
 
357
            && !(*pname = talloc_strdup(
 
358
                         mem_ctx, key->values->values[idx]->valuename))) {
 
359
                SAFE_FREE(val);
 
360
                return WERR_NOMEM;
 
361
        }
 
362
 
 
363
        *pval = val;
 
364
        return WERR_OK;
 
365
}
 
366
 
 
367
WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
 
368
                      const char *name, struct registry_value **pval)
 
369
{
 
370
        WERROR err;
 
371
        uint32 i;
 
372
 
 
373
        if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
 
374
                return WERR_ACCESS_DENIED;
 
375
        }
 
376
 
 
377
        if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
 
378
                return err;
 
379
        }
 
380
 
 
381
        for (i=0; i<key->values->num_values; i++) {
 
382
                if (strequal(key->values->values[i]->valuename, name)) {
 
383
                        return reg_enumvalue(mem_ctx, key, i, NULL, pval);
 
384
                }
 
385
        }
 
386
 
 
387
        return WERR_BADFILE;
 
388
}
 
389
 
 
390
WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
 
391
                        uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
 
392
                        uint32_t *num_values, uint32_t *max_valnamelen, 
 
393
                        uint32_t *max_valbufsize, uint32_t *secdescsize,
 
394
                        NTTIME *last_changed_time)
 
395
{
 
396
        uint32 i, max_size;
 
397
        size_t max_len;
 
398
        TALLOC_CTX *mem_ctx;
 
399
        WERROR err;
 
400
        struct security_descriptor *secdesc;
 
401
 
 
402
        if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
 
403
                return WERR_ACCESS_DENIED;
 
404
        }
 
405
 
 
406
        if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
 
407
            !W_ERROR_IS_OK(fill_value_cache(key))) {
 
408
                return WERR_BADFILE;
 
409
        }
 
410
 
 
411
        max_len = 0;
 
412
        for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
 
413
                max_len = MAX(max_len,
 
414
                        strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
 
415
        }
 
416
 
 
417
        *num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
 
418
        *max_subkeylen = max_len;
 
419
        *max_subkeysize = 0;    /* Class length? */
 
420
 
 
421
        max_len = 0;
 
422
        max_size = 0;
 
423
        for (i=0; i<key->values->num_values; i++) {
 
424
                max_len = MAX(max_len,
 
425
                              strlen(key->values->values[i]->valuename));
 
426
                max_size = MAX(max_size, key->values->values[i]->size);
 
427
        }
 
428
 
 
429
        *num_values = key->values->num_values;
 
430
        *max_valnamelen = max_len;
 
431
        *max_valbufsize = max_size;
 
432
 
 
433
        if (!(mem_ctx = talloc_new(key))) {
 
434
                return WERR_NOMEM;
 
435
        }
 
436
 
 
437
        err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
 
438
        if (!W_ERROR_IS_OK(err)) {
 
439
                TALLOC_FREE(mem_ctx);
 
440
                return err;
 
441
        }
 
442
 
 
443
        *secdescsize = ndr_size_security_descriptor(secdesc, NULL, 0);
 
444
        TALLOC_FREE(mem_ctx);
 
445
 
 
446
        *last_changed_time = 0;
 
447
 
 
448
        return WERR_OK;
 
449
}
 
450
 
 
451
WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 
452
                     const char *subkeypath, uint32 desired_access,
 
453
                     struct registry_key **pkey,
 
454
                     enum winreg_CreateAction *paction)
 
455
{
 
456
        struct registry_key *key = parent;
 
457
        struct registry_key *create_parent;
 
458
        TALLOC_CTX *mem_ctx;
 
459
        char *path, *end;
 
460
        WERROR err;
 
461
 
 
462
        /*
 
463
         * We must refuse to handle subkey-paths containing
 
464
         * a '/' character because at a lower level, after
 
465
         * normalization, '/' is treated as a key separator
 
466
         * just like '\\'.
 
467
         */
 
468
        if (strchr(subkeypath, '/') != NULL) {
 
469
                return WERR_INVALID_PARAM;
 
470
        }
 
471
 
 
472
        if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
 
473
 
 
474
        if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
 
475
                err = WERR_NOMEM;
 
476
                goto done;
 
477
        }
 
478
 
 
479
        while ((end = strchr(path, '\\')) != NULL) {
 
480
                struct registry_key *tmp;
 
481
                enum winreg_CreateAction action;
 
482
 
 
483
                *end = '\0';
 
484
 
 
485
                err = reg_createkey(mem_ctx, key, path,
 
486
                                    KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
 
487
                if (!W_ERROR_IS_OK(err)) {
 
488
                        goto done;
 
489
                }
 
490
 
 
491
                if (key != parent) {
 
492
                        TALLOC_FREE(key);
 
493
                }
 
494
 
 
495
                key = tmp;
 
496
                path = end+1;
 
497
        }
 
498
 
 
499
        /*
 
500
         * At this point, "path" contains the one-element subkey of "key". We
 
501
         * can try to open it.
 
502
         */
 
503
 
 
504
        err = reg_openkey(ctx, key, path, desired_access, pkey);
 
505
        if (W_ERROR_IS_OK(err)) {
 
506
                if (paction != NULL) {
 
507
                        *paction = REG_OPENED_EXISTING_KEY;
 
508
                }
 
509
                goto done;
 
510
        }
 
511
 
 
512
        if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
 
513
                /*
 
514
                 * Something but "notfound" has happened, so bail out
 
515
                 */
 
516
                goto done;
 
517
        }
 
518
 
 
519
        /*
 
520
         * We have to make a copy of the current key, as we opened it only
 
521
         * with ENUM_SUBKEY access.
 
522
         */
 
523
 
 
524
        err = reg_openkey(mem_ctx, key, "", KEY_CREATE_SUB_KEY,
 
525
                          &create_parent);
 
526
        if (!W_ERROR_IS_OK(err)) {
 
527
                goto done;
 
528
        }
 
529
 
 
530
        /*
 
531
         * Actually create the subkey
 
532
         */
 
533
 
 
534
        err = fill_subkey_cache(create_parent);
 
535
        if (!W_ERROR_IS_OK(err)) goto done;
 
536
 
 
537
        err = create_reg_subkey(key->key, path);
 
538
        W_ERROR_NOT_OK_GOTO_DONE(err);
 
539
 
 
540
        /*
 
541
         * Now open the newly created key
 
542
         */
 
543
 
 
544
        err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
 
545
        if (W_ERROR_IS_OK(err) && (paction != NULL)) {
 
546
                *paction = REG_CREATED_NEW_KEY;
 
547
        }
 
548
 
 
549
 done:
 
550
        TALLOC_FREE(mem_ctx);
 
551
        return err;
 
552
}
 
553
 
 
554
WERROR reg_deletekey(struct registry_key *parent, const char *path)
 
555
{
 
556
        WERROR err;
 
557
        char *name, *end;
 
558
        struct registry_key *tmp_key, *key;
 
559
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
560
 
 
561
        name = talloc_strdup(mem_ctx, path);
 
562
        if (name == NULL) {
 
563
                err = WERR_NOMEM;
 
564
                goto done;
 
565
        }
 
566
 
 
567
        /* check if the key has subkeys */
 
568
        err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
 
569
        W_ERROR_NOT_OK_GOTO_DONE(err);
 
570
 
 
571
        err = fill_subkey_cache(key);
 
572
        W_ERROR_NOT_OK_GOTO_DONE(err);
 
573
 
 
574
        if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
 
575
                err = WERR_ACCESS_DENIED;
 
576
                goto done;
 
577
        }
 
578
 
 
579
        /* no subkeys - proceed with delete */
 
580
        end = strrchr(name, '\\');
 
581
        if (end != NULL) {
 
582
                *end = '\0';
 
583
 
 
584
                err = reg_openkey(mem_ctx, parent, name,
 
585
                                  KEY_CREATE_SUB_KEY, &tmp_key);
 
586
                W_ERROR_NOT_OK_GOTO_DONE(err);
 
587
 
 
588
                parent = tmp_key;
 
589
                name = end+1;
 
590
        }
 
591
 
 
592
        if (name[0] == '\0') {
 
593
                err = WERR_INVALID_PARAM;
 
594
                goto done;
 
595
        }
 
596
 
 
597
        err = delete_reg_subkey(parent->key, name);
 
598
 
 
599
done:
 
600
        TALLOC_FREE(mem_ctx);
 
601
        return err;
 
602
}
 
603
 
 
604
WERROR reg_setvalue(struct registry_key *key, const char *name,
 
605
                    const struct registry_value *val)
 
606
{
 
607
        WERROR err;
 
608
        DATA_BLOB value_data;
 
609
        int res;
 
610
 
 
611
        if (!(key->key->access_granted & KEY_SET_VALUE)) {
 
612
                return WERR_ACCESS_DENIED;
 
613
        }
 
614
 
 
615
        if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
 
616
                return err;
 
617
        }
 
618
 
 
619
        err = registry_push_value(key, val, &value_data);
 
620
        if (!W_ERROR_IS_OK(err)) {
 
621
                return err;
 
622
        }
 
623
 
 
624
        res = regval_ctr_addvalue(key->values, name, val->type,
 
625
                                  (char *)value_data.data, value_data.length);
 
626
        TALLOC_FREE(value_data.data);
 
627
 
 
628
        if (res == 0) {
 
629
                TALLOC_FREE(key->values);
 
630
                return WERR_NOMEM;
 
631
        }
 
632
 
 
633
        if (!store_reg_values(key->key, key->values)) {
 
634
                TALLOC_FREE(key->values);
 
635
                return WERR_REG_IO_FAILURE;
 
636
        }
 
637
 
 
638
        return WERR_OK;
 
639
}
 
640
 
 
641
static WERROR reg_value_exists(struct registry_key *key, const char *name)
 
642
{
 
643
        int i;
 
644
 
 
645
        for (i=0; i<key->values->num_values; i++) {
 
646
                if (strequal(key->values->values[i]->valuename, name)) {
 
647
                        return WERR_OK;
 
648
                }
 
649
        }
 
650
 
 
651
        return WERR_BADFILE;
 
652
}
 
653
 
 
654
WERROR reg_deletevalue(struct registry_key *key, const char *name)
 
655
{
 
656
        WERROR err;
 
657
 
 
658
        if (!(key->key->access_granted & KEY_SET_VALUE)) {
 
659
                return WERR_ACCESS_DENIED;
 
660
        }
 
661
 
 
662
        if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
 
663
                return err;
 
664
        }
 
665
 
 
666
        err = reg_value_exists(key, name);
 
667
        if (!W_ERROR_IS_OK(err)) {
 
668
                return err;
 
669
        }
 
670
 
 
671
        regval_ctr_delvalue(key->values, name);
 
672
 
 
673
        if (!store_reg_values(key->key, key->values)) {
 
674
                TALLOC_FREE(key->values);
 
675
                return WERR_REG_IO_FAILURE;
 
676
        }
 
677
 
 
678
        return WERR_OK;
 
679
}
 
680
 
 
681
WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
 
682
                          struct security_descriptor **psecdesc)
 
683
{
 
684
        return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
 
685
}
 
686
 
 
687
WERROR reg_setkeysecurity(struct registry_key *key,
 
688
                          struct security_descriptor *psecdesc)
 
689
{
 
690
        return regkey_set_secdesc(key->key, psecdesc);
 
691
}
 
692
 
 
693
WERROR reg_getversion(uint32_t *version)
 
694
{
 
695
        if (version == NULL) {
 
696
                return WERR_INVALID_PARAM;
 
697
        }
 
698
 
 
699
        *version = 0x00000005; /* Windows 2000 registry API version */
 
700
        return WERR_OK;
 
701
}
 
702
 
 
703
/*******************************************************************
 
704
 Note: topkeypat is the *full* path that this *key will be
 
705
 loaded into (including the name of the key)
 
706
 ********************************************************************/
 
707
 
 
708
static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
 
709
                            REGF_NK_REC *key)
 
710
{
 
711
        REGF_NK_REC *subkey;
 
712
        REGISTRY_KEY registry_key;
 
713
        REGVAL_CTR *values;
 
714
        struct regsubkey_ctr *subkeys;
 
715
        int i;
 
716
        char *path = NULL;
 
717
        WERROR result = WERR_OK;
 
718
 
 
719
        /* initialize the REGISTRY_KEY structure */
 
720
 
 
721
        registry_key.ops = reghook_cache_find(topkeypath);
 
722
        if (!registry_key.ops) {
 
723
                DEBUG(0, ("reg_load_tree: Failed to assign  REGISTRY_OPS "
 
724
                          "to [%s]\n", topkeypath));
 
725
                return WERR_BADFILE;
 
726
        }
 
727
 
 
728
        registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
 
729
        if (!registry_key.name) {
 
730
                DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
 
731
                return WERR_NOMEM;
 
732
        }
 
733
 
 
734
        /* now start parsing the values and subkeys */
 
735
 
 
736
        result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
 
737
        W_ERROR_NOT_OK_RETURN(result);
 
738
 
 
739
        values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
 
740
        if (values == NULL) {
 
741
                return WERR_NOMEM;
 
742
        }
 
743
 
 
744
        /* copy values into the REGVAL_CTR */
 
745
 
 
746
        for (i=0; i<key->num_values; i++) {
 
747
                regval_ctr_addvalue(values, key->values[i].valuename,
 
748
                                    key->values[i].type,
 
749
                                    (char*)key->values[i].data,
 
750
                                    (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
 
751
        }
 
752
 
 
753
        /* copy subkeys into the struct regsubkey_ctr */
 
754
 
 
755
        key->subkey_index = 0;
 
756
        while ((subkey = regfio_fetch_subkey( regfile, key ))) {
 
757
                result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
 
758
                if (!W_ERROR_IS_OK(result)) {
 
759
                        TALLOC_FREE(subkeys);
 
760
                        return result;
 
761
                }
 
762
        }
 
763
 
 
764
        /* write this key and values out */
 
765
 
 
766
        if (!store_reg_values(&registry_key, values)
 
767
            || !store_reg_keys(&registry_key, subkeys))
 
768
        {
 
769
                DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
 
770
                result = WERR_REG_IO_FAILURE;
 
771
        }
 
772
 
 
773
        TALLOC_FREE(subkeys);
 
774
 
 
775
        if (!W_ERROR_IS_OK(result)) {
 
776
                return result;
 
777
        }
 
778
 
 
779
        /* now continue to load each subkey registry tree */
 
780
 
 
781
        key->subkey_index = 0;
 
782
        while ((subkey = regfio_fetch_subkey(regfile, key))) {
 
783
                path = talloc_asprintf(regfile->mem_ctx,
 
784
                                       "%s\\%s",
 
785
                                       topkeypath,
 
786
                                       subkey->keyname);
 
787
                if (path == NULL) {
 
788
                        return WERR_NOMEM;
 
789
                }
 
790
                result = reg_load_tree(regfile, path, subkey);
 
791
                if (!W_ERROR_IS_OK(result)) {
 
792
                        break;
 
793
                }
 
794
        }
 
795
 
 
796
        return result;
 
797
}
 
798
 
 
799
/*******************************************************************
 
800
 ********************************************************************/
 
801
 
 
802
static WERROR restore_registry_key(REGISTRY_KEY *krecord, const char *fname)
 
803
{
 
804
        REGF_FILE *regfile;
 
805
        REGF_NK_REC *rootkey;
 
806
        WERROR result;
 
807
 
 
808
        /* open the registry file....fail if the file already exists */
 
809
 
 
810
        regfile = regfio_open(fname, (O_RDONLY), 0);
 
811
        if (regfile == NULL) {
 
812
                DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
 
813
                          fname, strerror(errno)));
 
814
                return ntstatus_to_werror(map_nt_error_from_unix(errno));
 
815
        }
 
816
 
 
817
        /* get the rootkey from the regf file and then load the tree
 
818
           via recursive calls */
 
819
 
 
820
        if (!(rootkey = regfio_rootkey(regfile))) {
 
821
                regfio_close(regfile);
 
822
                return WERR_REG_FILE_INVALID;
 
823
        }
 
824
 
 
825
        result = reg_load_tree(regfile, krecord->name, rootkey);
 
826
 
 
827
        /* cleanup */
 
828
 
 
829
        regfio_close(regfile);
 
830
 
 
831
        return result;
 
832
}
 
833
 
 
834
WERROR reg_restorekey(struct registry_key *key, const char *fname)
 
835
{
 
836
        return restore_registry_key(key->key, fname);
 
837
}
 
838
 
 
839
/********************************************************************
 
840
********************************************************************/
 
841
 
 
842
static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
 
843
                             REGF_NK_REC *parent)
 
844
{
 
845
        REGF_NK_REC *key;
 
846
        REGVAL_CTR *values;
 
847
        struct regsubkey_ctr *subkeys;
 
848
        int i, num_subkeys;
 
849
        char *key_tmp = NULL;
 
850
        char *keyname, *parentpath;
 
851
        char *subkeypath = NULL;
 
852
        char *subkeyname;
 
853
        REGISTRY_KEY registry_key;
 
854
        WERROR result = WERR_OK;
 
855
        SEC_DESC *sec_desc = NULL;
 
856
 
 
857
        if (!regfile) {
 
858
                return WERR_GENERAL_FAILURE;
 
859
        }
 
860
 
 
861
        if (!keypath) {
 
862
                return WERR_OBJECT_PATH_INVALID;
 
863
        }
 
864
 
 
865
        /* split up the registry key path */
 
866
 
 
867
        key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
 
868
        if (!key_tmp) {
 
869
                return WERR_NOMEM;
 
870
        }
 
871
        if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
 
872
                return WERR_OBJECT_PATH_INVALID;
 
873
        }
 
874
 
 
875
        if (!keyname) {
 
876
                keyname = parentpath;
 
877
        }
 
878
 
 
879
        /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
 
880
 
 
881
        ZERO_STRUCT(registry_key);
 
882
 
 
883
        registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
 
884
        if (registry_key.name == NULL) {
 
885
                return WERR_NOMEM;
 
886
        }
 
887
 
 
888
        registry_key.ops = reghook_cache_find(registry_key.name);
 
889
        if (registry_key.ops == NULL) {
 
890
                return WERR_BADFILE;
 
891
        }
 
892
 
 
893
        /* lookup the values and subkeys */
 
894
 
 
895
        result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
 
896
        W_ERROR_NOT_OK_RETURN(result);
 
897
 
 
898
        values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
 
899
        if (values == NULL) {
 
900
                return WERR_NOMEM;
 
901
        }
 
902
 
 
903
        fetch_reg_keys(&registry_key, subkeys);
 
904
        fetch_reg_values(&registry_key, values);
 
905
 
 
906
        result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
 
907
        if (!W_ERROR_IS_OK(result)) {
 
908
                goto done;
 
909
        }
 
910
 
 
911
        /* write out this key */
 
912
 
 
913
        key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
 
914
                               parent);
 
915
        if (key == NULL) {
 
916
                result = WERR_CAN_NOT_COMPLETE;
 
917
                goto done;
 
918
        }
 
919
 
 
920
        /* write each one of the subkeys out */
 
921
 
 
922
        num_subkeys = regsubkey_ctr_numkeys(subkeys);
 
923
        for (i=0; i<num_subkeys; i++) {
 
924
                subkeyname = regsubkey_ctr_specific_key(subkeys, i);
 
925
                subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
 
926
                                             keypath, subkeyname);
 
927
                if (subkeypath == NULL) {
 
928
                        result = WERR_NOMEM;
 
929
                        goto done;
 
930
                }
 
931
                result = reg_write_tree(regfile, subkeypath, key);
 
932
                if (!W_ERROR_IS_OK(result))
 
933
                        goto done;
 
934
        }
 
935
 
 
936
        DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
 
937
 
 
938
done:
 
939
        TALLOC_FREE(subkeys);
 
940
        TALLOC_FREE(registry_key.name);
 
941
 
 
942
        return result;
 
943
}
 
944
 
 
945
static WERROR backup_registry_key(REGISTRY_KEY *krecord, const char *fname)
 
946
{
 
947
        REGF_FILE *regfile;
 
948
        WERROR result;
 
949
 
 
950
        /* open the registry file....fail if the file already exists */
 
951
 
 
952
        regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
 
953
                              (S_IREAD|S_IWRITE));
 
954
        if (regfile == NULL) {
 
955
                DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
 
956
                         fname, strerror(errno) ));
 
957
                return ntstatus_to_werror(map_nt_error_from_unix(errno));
 
958
        }
 
959
 
 
960
        /* write the registry tree to the file  */
 
961
 
 
962
        result = reg_write_tree(regfile, krecord->name, NULL);
 
963
 
 
964
        /* cleanup */
 
965
 
 
966
        regfio_close(regfile);
 
967
 
 
968
        return result;
 
969
}
 
970
 
 
971
WERROR reg_savekey(struct registry_key *key, const char *fname)
 
972
{
 
973
        return backup_registry_key(key->key, fname);
 
974
}
 
975
 
 
976
/**********************************************************************
 
977
 * Higher level utility functions
 
978
 **********************************************************************/
 
979
 
 
980
WERROR reg_deleteallvalues(struct registry_key *key)
 
981
{
 
982
        WERROR err;
 
983
        int i;
 
984
 
 
985
        if (!(key->key->access_granted & KEY_SET_VALUE)) {
 
986
                return WERR_ACCESS_DENIED;
 
987
        }
 
988
 
 
989
        if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
 
990
                return err;
 
991
        }
 
992
 
 
993
        for (i=0; i<key->values->num_values; i++) {
 
994
                regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
 
995
        }
 
996
 
 
997
        if (!store_reg_values(key->key, key->values)) {
 
998
                TALLOC_FREE(key->values);
 
999
                return WERR_REG_IO_FAILURE;
 
1000
        }
 
1001
 
 
1002
        return WERR_OK;
 
1003
}
 
1004
 
 
1005
/*
 
1006
 * Utility function to open a complete registry path including the hive prefix.
 
1007
 */
 
1008
 
 
1009
WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
 
1010
                     uint32 desired_access, const struct nt_user_token *token,
 
1011
                     struct registry_key **pkey)
 
1012
{
 
1013
        struct registry_key *hive, *key;
 
1014
        char *path, *p;
 
1015
        WERROR err;
 
1016
 
 
1017
        if (!(path = SMB_STRDUP(orig_path))) {
 
1018
                return WERR_NOMEM;
 
1019
        }
 
1020
 
 
1021
        p = strchr(path, '\\');
 
1022
 
 
1023
        if ((p == NULL) || (p[1] == '\0')) {
 
1024
                /*
 
1025
                 * No key behind the hive, just return the hive
 
1026
                 */
 
1027
 
 
1028
                err = reg_openhive(mem_ctx, path, desired_access, token,
 
1029
                                   &hive);
 
1030
                if (!W_ERROR_IS_OK(err)) {
 
1031
                        SAFE_FREE(path);
 
1032
                        return err;
 
1033
                }
 
1034
                SAFE_FREE(path);
 
1035
                *pkey = hive;
 
1036
                return WERR_OK;
 
1037
        }
 
1038
 
 
1039
        *p = '\0';
 
1040
 
 
1041
        err = reg_openhive(mem_ctx, path, KEY_ENUMERATE_SUB_KEYS, token,
 
1042
                           &hive);
 
1043
        if (!W_ERROR_IS_OK(err)) {
 
1044
                SAFE_FREE(path);
 
1045
                return err;
 
1046
        }
 
1047
 
 
1048
        err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
 
1049
 
 
1050
        TALLOC_FREE(hive);
 
1051
        SAFE_FREE(path);
 
1052
 
 
1053
        if (!W_ERROR_IS_OK(err)) {
 
1054
                return err;
 
1055
        }
 
1056
 
 
1057
        *pkey = key;
 
1058
        return WERR_OK;
 
1059
}
 
1060
 
 
1061
/*
 
1062
 * Utility function to delete a registry key with all its subkeys.
 
1063
 * Note that reg_deletekey returns ACCESS_DENIED when called on a
 
1064
 * key that has subkeys.
 
1065
 */
 
1066
static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
 
1067
                                               struct registry_key *parent,
 
1068
                                               const char *path,
 
1069
                                               bool del_key)
 
1070
{
 
1071
        TALLOC_CTX *mem_ctx = NULL;
 
1072
        WERROR werr = WERR_OK;
 
1073
        struct registry_key *key;
 
1074
        char *subkey_name = NULL;
 
1075
        uint32 i;
 
1076
 
 
1077
        mem_ctx = talloc_new(ctx);
 
1078
        if (mem_ctx == NULL) {
 
1079
                werr = WERR_NOMEM;
 
1080
                goto done;
 
1081
        }
 
1082
 
 
1083
        /* recurse through subkeys first */
 
1084
        werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
 
1085
        if (!W_ERROR_IS_OK(werr)) {
 
1086
                goto done;
 
1087
        }
 
1088
 
 
1089
        werr = fill_subkey_cache(key);
 
1090
        W_ERROR_NOT_OK_GOTO_DONE(werr);
 
1091
 
 
1092
        /*
 
1093
         * loop from top to bottom for perfomance:
 
1094
         * this way, we need to rehash the regsubkey containers less
 
1095
         */
 
1096
        for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
 
1097
                subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
 
1098
                werr = reg_deletekey_recursive_internal(mem_ctx, key,
 
1099
                                        subkey_name,
 
1100
                                        true);
 
1101
                W_ERROR_NOT_OK_GOTO_DONE(werr);
 
1102
        }
 
1103
 
 
1104
        if (del_key) {
 
1105
                /* now delete the actual key */
 
1106
                werr = reg_deletekey(parent, path);
 
1107
        }
 
1108
 
 
1109
done:
 
1110
        TALLOC_FREE(mem_ctx);
 
1111
        return werr;
 
1112
}
 
1113
 
 
1114
static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx,
 
1115
                                            struct registry_key *parent,
 
1116
                                            const char *path,
 
1117
                                            bool del_key)
 
1118
{
 
1119
        WERROR werr;
 
1120
 
 
1121
        werr = regdb_transaction_start();
 
1122
        if (!W_ERROR_IS_OK(werr)) {
 
1123
                DEBUG(0, ("reg_deletekey_recursive_trans: "
 
1124
                          "error starting transaction: %s\n",
 
1125
                          win_errstr(werr)));
 
1126
                return werr;
 
1127
        }
 
1128
 
 
1129
        werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key);
 
1130
 
 
1131
        if (!W_ERROR_IS_OK(werr)) {
 
1132
                DEBUG(1, (__location__ " failed to delete key '%s' from key "
 
1133
                          "'%s': %s\n", path, parent->key->name,
 
1134
                          win_errstr(werr)));
 
1135
                werr = regdb_transaction_cancel();
 
1136
                if (!W_ERROR_IS_OK(werr)) {
 
1137
                        DEBUG(0, ("reg_deletekey_recursive_trans: "
 
1138
                                  "error cancelling transaction: %s\n",
 
1139
                                  win_errstr(werr)));
 
1140
                }
 
1141
        } else {
 
1142
                werr = regdb_transaction_commit();
 
1143
                if (!W_ERROR_IS_OK(werr)) {
 
1144
                        DEBUG(0, ("reg_deletekey_recursive_trans: "
 
1145
                                  "error committing transaction: %s\n",
 
1146
                                  win_errstr(werr)));
 
1147
                }
 
1148
        }
 
1149
 
 
1150
        return werr;
 
1151
}
 
1152
 
 
1153
WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
 
1154
                               struct registry_key *parent,
 
1155
                               const char *path)
 
1156
{
 
1157
        return reg_deletekey_recursive_trans(ctx, parent, path, true);
 
1158
}
 
1159
 
 
1160
WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
 
1161
                                   struct registry_key *parent,
 
1162
                                   const char *path)
 
1163
{
 
1164
        return reg_deletekey_recursive_trans(ctx, parent, path, false);
 
1165
}
 
1166
 
 
1167
#if 0
 
1168
/* these two functions are unused. */
 
1169
 
 
1170
/**
 
1171
 * Utility function to create a registry key without opening the hive
 
1172
 * before. Assumes the hive already exists.
 
1173
 */
 
1174
 
 
1175
WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
 
1176
                       uint32 desired_access,
 
1177
                       const struct nt_user_token *token,
 
1178
                       enum winreg_CreateAction *paction,
 
1179
                       struct registry_key **pkey)
 
1180
{
 
1181
        struct registry_key *hive;
 
1182
        char *path, *p;
 
1183
        WERROR err;
 
1184
 
 
1185
        if (!(path = SMB_STRDUP(orig_path))) {
 
1186
                return WERR_NOMEM;
 
1187
        }
 
1188
 
 
1189
        p = strchr(path, '\\');
 
1190
 
 
1191
        if ((p == NULL) || (p[1] == '\0')) {
 
1192
                /*
 
1193
                 * No key behind the hive, just return the hive
 
1194
                 */
 
1195
 
 
1196
                err = reg_openhive(mem_ctx, path, desired_access, token,
 
1197
                                   &hive);
 
1198
                if (!W_ERROR_IS_OK(err)) {
 
1199
                        SAFE_FREE(path);
 
1200
                        return err;
 
1201
                }
 
1202
                SAFE_FREE(path);
 
1203
                *pkey = hive;
 
1204
                *paction = REG_OPENED_EXISTING_KEY;
 
1205
                return WERR_OK;
 
1206
        }
 
1207
 
 
1208
        *p = '\0';
 
1209
 
 
1210
        err = reg_openhive(mem_ctx, path,
 
1211
                           (strchr(p+1, '\\') != NULL) ?
 
1212
                           KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
 
1213
                           token, &hive);
 
1214
        if (!W_ERROR_IS_OK(err)) {
 
1215
                SAFE_FREE(path);
 
1216
                return err;
 
1217
        }
 
1218
 
 
1219
        err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
 
1220
        SAFE_FREE(path);
 
1221
        TALLOC_FREE(hive);
 
1222
        return err;
 
1223
}
 
1224
 
 
1225
/*
 
1226
 * Utility function to create a registry key without opening the hive
 
1227
 * before. Will not delete a hive.
 
1228
 */
 
1229
 
 
1230
WERROR reg_delete_path(const struct nt_user_token *token,
 
1231
                       const char *orig_path)
 
1232
{
 
1233
        struct registry_key *hive;
 
1234
        char *path, *p;
 
1235
        WERROR err;
 
1236
 
 
1237
        if (!(path = SMB_STRDUP(orig_path))) {
 
1238
                return WERR_NOMEM;
 
1239
        }
 
1240
 
 
1241
        p = strchr(path, '\\');
 
1242
 
 
1243
        if ((p == NULL) || (p[1] == '\0')) {
 
1244
                SAFE_FREE(path);
 
1245
                return WERR_INVALID_PARAM;
 
1246
        }
 
1247
 
 
1248
        *p = '\0';
 
1249
 
 
1250
        err = reg_openhive(NULL, path,
 
1251
                           (strchr(p+1, '\\') != NULL) ?
 
1252
                           KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
 
1253
                           token, &hive);
 
1254
        if (!W_ERROR_IS_OK(err)) {
 
1255
                SAFE_FREE(path);
 
1256
                return err;
 
1257
        }
 
1258
 
 
1259
        err = reg_deletekey(hive, p+1);
 
1260
        SAFE_FREE(path);
 
1261
        TALLOC_FREE(hive);
 
1262
        return err;
 
1263
}
 
1264
#endif /* #if 0 */