X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba.git;a=blobdiff_plain;f=source3%2Fregistry%2Freg_backend_db.c;h=b9ff5dc7fc63b8374ebad7591117de34880edd8e;hp=419bfd00f5ad7ee87e50f7a41a77374cc4fc70b6;hb=2c11b73391551723e4ada8664b1ba77873420217;hpb=14f593aa0f43127ab78aec848b0fe5933c0c28c9 diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 419bfd00f5a..b9ff5dc7fc6 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -2,6 +2,7 @@ * Unix SMB/CIFS implementation. * Virtual Windows Registry Layer * Copyright (C) Gerald Carter 2002-2005 + * Copyright (C) Michael Adam 2007-2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,8 +30,8 @@ static int regdb_refcount; static bool regdb_key_exists(struct db_context *db, const char *key); static bool regdb_key_is_base_key(const char *key); -static int regdb_fetch_keys_internal(struct db_context *db, const char *key, - struct regsubkey_ctr *ctr); +static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr); static bool regdb_store_keys_internal(struct db_context *db, const char *key, struct regsubkey_ctr *ctr); static int regdb_fetch_values_internal(struct db_context *db, const char* key, @@ -182,7 +183,13 @@ static WERROR init_registry_key_internal(struct db_context *db, goto fail; } - regdb_fetch_keys_internal(db, base, subkeys); + werr = regdb_fetch_keys_internal(db, base, subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto fail; + } + if (*subkeyname) { werr = regsubkey_ctr_addkey(subkeys, subkeyname); if (!W_ERROR_IS_OK(werr)) { @@ -243,7 +250,7 @@ WERROR init_registry_key(const char *add_path) static void regdb_ctr_add_value(struct regval_ctr *ctr, struct builtin_regkey_value *value) { - UNISTR2 data; + DATA_BLOB data; switch(value->type) { case REG_DWORD: @@ -253,10 +260,10 @@ static void regdb_ctr_add_value(struct regval_ctr *ctr, break; case REG_SZ: - init_unistr2(&data, value->data.string, UNI_STR_TERMINATE); + push_reg_sz(talloc_tos(), &data, value->data.string); regval_ctr_addvalue(ctr, value->valuename, REG_SZ, - (char*)data.buffer, - data.uni_str_len*sizeof(uint16)); + (char*)data.data, + data.length); break; default: @@ -623,14 +630,21 @@ static WERROR regdb_store_keys_internal2(struct db_context *db, WERROR werr; if (!key) { - return WERR_INVALID_PARAM; + werr = WERR_INVALID_PARAM; + goto done; } keyname = talloc_strdup(ctx, key); if (!keyname) { - return WERR_NOMEM; + werr = WERR_NOMEM; + goto done; } + keyname = normalize_reg_path(ctx, keyname); + if (!keyname) { + werr = WERR_NOMEM; + goto done; + } /* allocate some initial memory */ @@ -718,74 +732,37 @@ done: do not currently exist ***********************************************************************/ -static bool regdb_store_keys_internal(struct db_context *db, const char *key, - struct regsubkey_ctr *ctr) +struct regdb_store_keys_context { + const char *key; + struct regsubkey_ctr *ctr; +}; + +static NTSTATUS regdb_store_keys_action(struct db_context *db, + void *private_data) { - int num_subkeys, old_num_subkeys, i; + struct regdb_store_keys_context *store_ctx; + WERROR werr; + int num_subkeys, i; char *path = NULL; struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL; char *oldkeyname = NULL; - TALLOC_CTX *ctx = talloc_stackframe(); - WERROR werr; - - if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) { - goto fail; - } - - /* - * fetch a list of the old subkeys so we can determine if anything has - * changed - */ - - werr = regsubkey_ctr_init(ctx, &old_subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - return false; - } - - regdb_fetch_keys_internal(db, key, old_subkeys); - - num_subkeys = regsubkey_ctr_numkeys(ctr); - old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); - if ((num_subkeys && old_num_subkeys) && - (num_subkeys == old_num_subkeys)) { - - for (i = 0; i < num_subkeys; i++) { - if (strcmp(regsubkey_ctr_specific_key(ctr, i), - regsubkey_ctr_specific_key(old_subkeys, i)) - != 0) - { - break; - } - } - if (i == num_subkeys) { - /* - * Nothing changed, no point to even start a tdb - * transaction - */ - TALLOC_FREE(old_subkeys); - return true; - } - } - - TALLOC_FREE(old_subkeys); + TALLOC_CTX *mem_ctx = talloc_stackframe(); - if (db->transaction_start(db) != 0) { - DEBUG(0, ("regdb_store_keys: transaction_start failed\n")); - goto fail; - } + store_ctx = (struct regdb_store_keys_context *)private_data; /* * Re-fetch the old keys inside the transaction */ - werr = regsubkey_ctr_init(ctx, &old_subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; - } + werr = regsubkey_ctr_init(mem_ctx, &old_subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - regdb_fetch_keys_internal(db, key, old_subkeys); + werr = regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto done; + } /* * Make the store operation as safe as possible without transactions: @@ -814,21 +791,22 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key, for (i=0; ictr, oldkeyname)) { /* * It's still around, don't delete */ - continue; } - path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname); + path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key, + oldkeyname); if (!path) { - goto cancel; + werr = WERR_NOMEM; + goto done; } werr = regdb_delete_key_lists(db, path); - W_ERROR_NOT_OK_GOTO(werr, cancel); + W_ERROR_NOT_OK_GOTO_DONE(werr); TALLOC_FREE(path); } @@ -837,56 +815,51 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key, /* (2) store the subkey list for the parent */ - werr = regdb_store_keys_internal2(db, key, ctr); + werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store new subkey list " - "for parent [%s]: %s\n", key, win_errstr(werr))); - goto cancel; + "for parent [%s]: %s\n", store_ctx->key, + win_errstr(werr))); + goto done; } /* (3) now create records for any subkeys that don't already exist */ - num_subkeys = regsubkey_ctr_numkeys(ctr); + num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr); if (num_subkeys == 0) { - werr = regsubkey_ctr_init(ctx, &subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; - } + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - werr = regdb_store_keys_internal2(db, key, subkeys); + werr = regdb_store_keys_internal2(db, store_ctx->key, subkeys); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store " - "new record for key [%s]: %s\n", key, - win_errstr(werr))); - goto cancel; + "new record for key [%s]: %s\n", + store_ctx->key, win_errstr(werr))); + goto done; } TALLOC_FREE(subkeys); - } for (i=0; ikey, + regsubkey_ctr_specific_key(store_ctx->ctr, i)); if (!path) { - goto cancel; - } - werr = regsubkey_ctr_init(ctx, &subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; + werr = WERR_NOMEM; + goto done; } + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - if (regdb_fetch_keys_internal(db, path, subkeys) == -1) { + werr = regdb_fetch_keys_internal(db, path, subkeys); + if (!W_ERROR_IS_OK(werr)) { /* create a record with 0 subkeys */ werr = regdb_store_keys_internal2(db, path, subkeys); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store " "new record for key [%s]: %s\n", path, win_errstr(werr))); - goto cancel; + goto done; } } @@ -894,23 +867,84 @@ static bool regdb_store_keys_internal(struct db_context *db, const char *key, TALLOC_FREE(path); } - if (db->transaction_commit(db) != 0) { - DEBUG(0, ("regdb_store_keys: Could not commit transaction\n")); - goto fail; + werr = WERR_OK; + +done: + talloc_free(mem_ctx); + return werror_to_ntstatus(werr); +} + +static bool regdb_store_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr) +{ + int num_subkeys, old_num_subkeys, i; + struct regsubkey_ctr *old_subkeys = NULL; + TALLOC_CTX *ctx = talloc_stackframe(); + WERROR werr; + bool ret = false; + struct regdb_store_keys_context store_ctx; + + if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) { + goto done; } - TALLOC_FREE(ctx); - return true; + /* + * fetch a list of the old subkeys so we can determine if anything has + * changed + */ -cancel: - if (db->transaction_cancel(db) != 0) { - smb_panic("regdb_store_keys: transaction_cancel failed\n"); + werr = regsubkey_ctr_init(ctx, &old_subkeys); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,("regdb_store_keys: talloc() failure!\n")); + goto done; } -fail: + werr = regdb_fetch_keys_internal(db, key, old_subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto done; + } + + num_subkeys = regsubkey_ctr_numkeys(ctr); + old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); + if ((num_subkeys && old_num_subkeys) && + (num_subkeys == old_num_subkeys)) { + + for (i = 0; i < num_subkeys; i++) { + if (strcmp(regsubkey_ctr_specific_key(ctr, i), + regsubkey_ctr_specific_key(old_subkeys, i)) + != 0) + { + break; + } + } + if (i == num_subkeys) { + /* + * Nothing changed, no point to even start a tdb + * transaction + */ + + ret = true; + goto done; + } + } + + TALLOC_FREE(old_subkeys); + + store_ctx.key = key; + store_ctx.ctr = ctr; + + werr = ntstatus_to_werror(dbwrap_trans_do(db, + regdb_store_keys_action, + &store_ctx)); + + ret = W_ERROR_IS_OK(werr); + +done: TALLOC_FREE(ctx); - return false; + return ret; } bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) @@ -918,11 +952,52 @@ bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) return regdb_store_keys_internal(regdb, key, ctr); } +/** + * create a subkey of a given key + */ + +struct regdb_create_subkey_context { + const char *key; + const char *subkey; +}; + +static NTSTATUS regdb_create_subkey_action(struct db_context *db, + void *private_data) +{ + WERROR werr; + struct regdb_create_subkey_context *create_ctx; + struct regsubkey_ctr *subkeys; + TALLOC_CTX *mem_ctx = talloc_stackframe(); + + create_ctx = (struct regdb_create_subkey_context *)private_data; + + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_fetch_keys_internal(db, create_ctx->key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regsubkey_ctr_addkey(subkeys, create_ctx->subkey); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_store_keys_internal2(db, create_ctx->key, subkeys); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, (__location__ " failed to store new subkey list for " + "parent key %s: %s\n", create_ctx->key, + win_errstr(werr))); + } + +done: + talloc_free(mem_ctx); + return werror_to_ntstatus(werr); +} + static WERROR regdb_create_subkey(const char *key, const char *subkey) { WERROR werr; struct regsubkey_ctr *subkeys; TALLOC_CTX *mem_ctx = talloc_stackframe(); + struct regdb_create_subkey_context create_ctx; if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) { werr = WERR_NOT_FOUND; @@ -932,10 +1007,8 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey) werr = regsubkey_ctr_init(mem_ctx, &subkeys); W_ERROR_NOT_OK_GOTO_DONE(werr); - if (regdb_fetch_keys_internal(regdb, key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto done; - } + werr = regdb_fetch_keys_internal(regdb, key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); if (regsubkey_ctr_key_exists(subkeys, subkey)) { werr = WERR_OK; @@ -944,51 +1017,67 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey) talloc_free(subkeys); - if (regdb->transaction_start(regdb) != 0) { - werr = WERR_REG_IO_FAILURE; - goto done; - } + create_ctx.key = key; + create_ctx.subkey = subkey; - werr = regsubkey_ctr_init(mem_ctx, &subkeys); - W_ERROR_NOT_OK_GOTO(werr, cancel); + werr = ntstatus_to_werror(dbwrap_trans_do(regdb, + regdb_create_subkey_action, + &create_ctx)); - if (regdb_fetch_keys_internal(regdb, key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto cancel; - } +done: + talloc_free(mem_ctx); + return werr; +} - werr = regsubkey_ctr_addkey(subkeys, subkey); - W_ERROR_NOT_OK_GOTO(werr, cancel); +/** + * create a subkey of a given key + */ - werr = regdb_store_keys_internal2(regdb, key, subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " failed to store new subkey list for " - "parent key %s: %s\n", key, win_errstr(werr))); - goto cancel; - } +struct regdb_delete_subkey_context { + const char *key; + const char *subkey; + const char *path; +}; - if (regdb->transaction_commit(regdb) != 0) { - werr = WERR_REG_IO_FAILURE; - DEBUG(0, (__location__ " failed to commit transaction\n")); - } +static NTSTATUS regdb_delete_subkey_action(struct db_context *db, + void *private_data) +{ + WERROR werr; + struct regdb_delete_subkey_context *delete_ctx; + struct regsubkey_ctr *subkeys; + TALLOC_CTX *mem_ctx = talloc_stackframe(); - goto done; + delete_ctx = (struct regdb_delete_subkey_context *)private_data; + + werr = regdb_delete_key_lists(db, delete_ctx->path); + W_ERROR_NOT_OK_GOTO_DONE(werr); -cancel: - if (regdb->transaction_cancel(regdb) != 0) { - smb_panic("regdb_create_subkey: transaction_cancel failed\n"); + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_fetch_keys_internal(db, delete_ctx->key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regsubkey_ctr_delkey(subkeys, delete_ctx->subkey); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_store_keys_internal2(db, delete_ctx->key, subkeys); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, (__location__ " failed to store new subkey_list for " + "parent key %s: %s\n", delete_ctx->key, + win_errstr(werr))); } done: talloc_free(mem_ctx); - return werr; + return werror_to_ntstatus(werr); } static WERROR regdb_delete_subkey(const char *key, const char *subkey) { WERROR werr; - struct regsubkey_ctr *subkeys; char *path; + struct regdb_delete_subkey_context delete_ctx; TALLOC_CTX *mem_ctx = talloc_stackframe(); if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) { @@ -1007,43 +1096,13 @@ static WERROR regdb_delete_subkey(const char *key, const char *subkey) goto done; } - if (regdb->transaction_start(regdb) != 0) { - werr = WERR_REG_IO_FAILURE; - goto done; - } - - werr = regdb_delete_key_lists(regdb, path); - W_ERROR_NOT_OK_GOTO(werr, cancel); - - werr = regsubkey_ctr_init(mem_ctx, &subkeys); - W_ERROR_NOT_OK_GOTO(werr, cancel); - - if (regdb_fetch_keys_internal(regdb, key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto cancel; - } + delete_ctx.key = key; + delete_ctx.subkey = subkey; + delete_ctx.path = path; - werr = regsubkey_ctr_delkey(subkeys, subkey); - W_ERROR_NOT_OK_GOTO(werr, cancel); - - werr = regdb_store_keys_internal2(regdb, key, subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " failed to store new subkey_list for " - "parent key %s: %s\n", key, win_errstr(werr))); - goto cancel; - } - - if (regdb->transaction_commit(regdb) != 0) { - DEBUG(0, (__location__ " failed to commit transaction\n")); - werr = WERR_REG_IO_FAILURE; - } - - goto done; - -cancel: - if (regdb->transaction_cancel(regdb) != 0) { - smb_panic("regdb_delete_subkey: transaction_cancel failed\n"); - } + werr = ntstatus_to_werror(dbwrap_trans_do(regdb, + regdb_delete_subkey_action, + &delete_ctx)); done: talloc_free(mem_ctx); @@ -1127,39 +1186,58 @@ static int cmp_keynames(const void *p1, const void *p2) return StrCaseCmp(*((char **)p1), *((char **)p2)); } -static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) +struct create_sorted_subkeys_context { + const char *key; + const char *sorted_keyname; +}; + +static NTSTATUS create_sorted_subkeys_action(struct db_context *db, + void *private_data) { char **sorted_subkeys; struct regsubkey_ctr *ctr; - bool result = false; NTSTATUS status; char *buf; char *p; - int i, res; + int i; size_t len; int num_subkeys; - WERROR werr; + struct create_sorted_subkeys_context *sorted_ctx; - if (regdb->transaction_start(regdb) != 0) { - DEBUG(0, ("create_sorted_subkeys: transaction_start " - "failed\n")); - return false; - } + sorted_ctx = (struct create_sorted_subkeys_context *)private_data; - werr = regsubkey_ctr_init(talloc_tos(), &ctr); - if (!W_ERROR_IS_OK(werr)) { - goto fail; + /* + * In this function, we only treat failing of the actual write to + * the db as a real error. All preliminary errors, at a stage when + * nothing has been written to the DB yet are treated as success + * to be committed (as an empty transaction). + * + * The reason is that this (disposable) call might be nested in other + * transactions. Doing a cancel here would destroy the possibility of + * a transaction_commit for transactions that we might be wrapped in. + */ + + status = werror_to_ntstatus(regsubkey_ctr_init(talloc_tos(), &ctr)); + if (!NT_STATUS_IS_OK(status)) { + /* don't treat this as an error */ + status = NT_STATUS_OK; + goto done; } - res = regdb_fetch_keys_internal(regdb, key, ctr); - if (res == -1) { - goto fail; + status = werror_to_ntstatus(regdb_fetch_keys_internal(db, + sorted_ctx->key, + ctr)); + if (!NT_STATUS_IS_OK(status)) { + /* don't treat this as an error */ + status = NT_STATUS_OK; + goto done; } num_subkeys = regsubkey_ctr_numkeys(ctr); sorted_subkeys = talloc_array(ctr, char *, num_subkeys); if (sorted_subkeys == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } len = 4 + 4*num_subkeys; @@ -1168,7 +1246,8 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys, regsubkey_ctr_specific_key(ctr, i)); if (sorted_subkeys[i] == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } len += strlen(sorted_subkeys[i])+1; } @@ -1177,7 +1256,8 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) buf = talloc_array(ctr, char, len); if (buf == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } p = buf + 4 + 4*num_subkeys; @@ -1191,38 +1271,28 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) } status = dbwrap_store_bystring( - regdb, sorted_keyname, make_tdb_data((uint8_t *)buf, len), + db, sorted_ctx->sorted_keyname, make_tdb_data((uint8_t *)buf, + len), TDB_REPLACE); - if (!NT_STATUS_IS_OK(status)) { - /* - * Don't use a "goto fail;" here, this would commit the broken - * transaction. See below for an explanation. - */ - if (regdb->transaction_cancel(regdb) == -1) { - smb_panic("create_sorted_subkeys: transaction_cancel " - "failed\n"); - } - TALLOC_FREE(ctr); - return false; - } - result = true; - fail: - /* - * We only get here via the "goto fail" when we did not write anything - * yet. Using transaction_commit even in a failure case is necessary - * because this (disposable) call might be nested in other - * transactions. Doing a cancel here would destroy the possibility of - * a transaction_commit for transactions that we might be wrapped in. - */ - if (regdb->transaction_commit(regdb) == -1) { - DEBUG(0, ("create_sorted_subkeys: transaction_commit " - "failed\n")); - result = false; - } +done: + talloc_free(ctr); + return status; +} - TALLOC_FREE(ctr); - return result; +static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) +{ + NTSTATUS status; + struct create_sorted_subkeys_context sorted_ctx; + + sorted_ctx.key = key; + sorted_ctx.sorted_keyname = sorted_keyname; + + status = dbwrap_trans_do(regdb, + create_sorted_subkeys_action, + &sorted_ctx); + + return NT_STATUS_IS_OK(status); } struct scan_subkey_state { @@ -1368,36 +1438,36 @@ done: released by the caller. ***********************************************************************/ -static int regdb_fetch_keys_internal(struct db_context *db, const char *key, - struct regsubkey_ctr *ctr) +static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr) { WERROR werr; - uint32 num_items; + uint32_t num_items; uint8 *buf; uint32 buflen, len; int i; fstring subkeyname; - int ret = -1; TALLOC_CTX *frame = talloc_stackframe(); TDB_DATA value; DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); + frame = talloc_stackframe(); + if (!regdb_key_exists(db, key)) { + DEBUG(10, ("key [%s] not found\n", key)); + werr = WERR_NOT_FOUND; goto done; } werr = regsubkey_ctr_set_seqnum(ctr, db->get_seqnum(db)); - if (!W_ERROR_IS_OK(werr)) { - goto done; - } + W_ERROR_NOT_OK_GOTO_DONE(werr); value = regdb_fetch_key_internal(db, frame, key); if (value.dptr == NULL) { DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n", key)); - ret = 0; goto done; } @@ -1405,27 +1475,37 @@ static int regdb_fetch_keys_internal(struct db_context *db, const char *key, buflen = value.dsize; len = tdb_unpack( buf, buflen, "d", &num_items); + werr = regsubkey_ctr_reinit(ctr); + W_ERROR_NOT_OK_GOTO_DONE(werr); + for (i=0; i