static struct db_context *regdb = NULL;
static int regdb_refcount;
-static bool regdb_key_exists(const char *key);
+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 bool regdb_store_keys_internal(struct db_context *db, const char *key,
+ struct regsubkey_ctr *ctr);
/* List the deepest path into the registry. All part components will be created.*/
goto fail;
}
- regdb_fetch_keys(base, subkeys);
+ regdb_fetch_keys_internal(regdb, base, subkeys);
if (*subkeyname) {
werr = regsubkey_ctr_addkey(subkeys, subkeyname);
if (!W_ERROR_IS_OK(werr)) {
goto fail;
}
}
- if (!regdb_store_keys( base, subkeys)) {
+ if (!regdb_store_keys_internal(regdb, base, subkeys)) {
werr = WERR_CAN_NOT_COMPLETE;
goto fail;
}
{
WERROR werr;
- if (regdb_key_exists(add_path)) {
+ if (regdb_key_exists(regdb, add_path)) {
return WERR_OK;
}
{
WERROR werr;
TALLOC_CTX *frame = talloc_stackframe();
- REGVAL_CTR *values;
+ struct regval_ctr *values;
int i;
UNISTR2 data;
* If all do already exist, we can save the writes.
*/
for (i=0; builtin_registry_paths[i] != NULL; i++) {
- if (!regdb_key_exists(builtin_registry_paths[i])) {
+ if (!regdb_key_exists(regdb, builtin_registry_paths[i])) {
goto do_init;
}
}
for (i=0; builtin_registry_values[i].path != NULL; i++) {
- values = TALLOC_ZERO_P(frame, REGVAL_CTR);
+ values = TALLOC_ZERO_P(frame, struct regval_ctr);
if (values == NULL) {
werr = WERR_NOMEM;
goto done;
/* loop over all of the predefined paths and add each component */
for (i=0; builtin_registry_paths[i] != NULL; i++) {
- if (regdb_key_exists(builtin_registry_paths[i])) {
+ if (regdb_key_exists(regdb, builtin_registry_paths[i])) {
continue;
}
werr = init_registry_key_internal(builtin_registry_paths[i]);
for (i=0; builtin_registry_values[i].path != NULL; i++) {
- values = TALLOC_ZERO_P(frame, REGVAL_CTR);
+ values = TALLOC_ZERO_P(frame, struct regval_ctr);
if (values == NULL) {
werr = WERR_NOMEM;
goto fail;
return regdb->get_seqnum(regdb);
}
+
+static WERROR regdb_delete_key_with_prefix(struct db_context *db,
+ const char *keyname,
+ const char *prefix)
+{
+ char *path;
+ WERROR werr = WERR_NOMEM;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+ if (keyname == NULL) {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ if (prefix == NULL) {
+ path = discard_const_p(char, keyname);
+ } else {
+ path = talloc_asprintf(mem_ctx, "%s/%s", prefix, keyname);
+ if (path == NULL) {
+ goto done;
+ }
+ }
+
+ path = normalize_reg_path(mem_ctx, path);
+ if (path == NULL) {
+ goto done;
+ }
+
+ werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path));
+
+ /* treat "not" found" as ok */
+ if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
+ werr = WERR_OK;
+ }
+
+done:
+ talloc_free(mem_ctx);
+ return werr;
+}
+
+
+static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
+{
+ return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
+}
+
+static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
+{
+ return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
+}
+
+static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
+{
+ return regdb_delete_key_with_prefix(db, keyname, NULL);
+}
+
+static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
+{
+ WERROR werr;
+
+ werr = regdb_delete_values(db, keyname);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+ REG_VALUE_PREFIX, keyname, win_errstr(werr)));
+ goto done;
+ }
+
+ werr = regdb_delete_secdesc(db, keyname);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+ REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
+ goto done;
+ }
+
+ werr = regdb_delete_subkeylist(db, keyname);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, (__location__ " Deleting %s failed: %s\n",
+ keyname, win_errstr(werr)));
+ goto done;
+ }
+
+done:
+ return werr;
+}
+
/***********************************************************************
Add subkey strings to the registry tdb under a defined key
fmt is the same format as tdb_pack except this function only supports
fstrings
***********************************************************************/
-static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr)
+static bool regdb_store_keys_internal2(struct db_context *db,
+ const char *key,
+ struct regsubkey_ctr *ctr)
{
TDB_DATA dbuf;
uint8 *buffer = NULL;
dbuf.dptr = buffer;
dbuf.dsize = len;
- status = dbwrap_store_bystring(regdb, keyname, dbuf, TDB_REPLACE);
+ status = dbwrap_store_bystring(db, keyname, dbuf, TDB_REPLACE);
if (!NT_STATUS_IS_OK(status)) {
ret = false;
goto done;
keyname = talloc_asprintf(ctx, "%s/%s", REG_SORTED_SUBKEYS_PREFIX,
keyname);
if (keyname != NULL) {
- dbwrap_delete_bystring(regdb, keyname);
+ dbwrap_delete_bystring(db, keyname);
}
done:
do not currently exist
***********************************************************************/
-bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
+static bool regdb_store_keys_internal(struct db_context *db, const char *key,
+ struct regsubkey_ctr *ctr)
{
int num_subkeys, old_num_subkeys, i;
char *path = NULL;
struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
char *oldkeyname = NULL;
TALLOC_CTX *ctx = talloc_stackframe();
- NTSTATUS status;
WERROR werr;
- if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
+ if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) {
goto fail;
}
return false;
}
- regdb_fetch_keys(key, old_subkeys);
+ regdb_fetch_keys_internal(db, key, old_subkeys);
num_subkeys = regsubkey_ctr_numkeys(ctr);
old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
TALLOC_FREE(old_subkeys);
- if (regdb->transaction_start(regdb) != 0) {
+ if (db->transaction_start(db) != 0) {
DEBUG(0, ("regdb_store_keys: transaction_start failed\n"));
goto fail;
}
goto cancel;
}
- regdb_fetch_keys(key, old_subkeys);
+ regdb_fetch_keys_internal(db, key, old_subkeys);
/*
* Make the store operation as safe as possible without transactions:
continue;
}
- /* (a) Delete the value list for this key */
-
- path = talloc_asprintf(ctx, "%s/%s/%s",
- REG_VALUE_PREFIX,
- key,
- oldkeyname );
- if (!path) {
- goto cancel;
- }
- path = normalize_reg_path(ctx, path);
- if (!path) {
- goto cancel;
- }
- /* Ignore errors here, we might have no values around */
- dbwrap_delete_bystring(regdb, path);
- TALLOC_FREE(path);
-
- /* (b) Delete the secdesc for this key */
-
- path = talloc_asprintf(ctx, "%s/%s/%s",
- REG_SECDESC_PREFIX,
- key,
- oldkeyname );
- if (!path) {
- goto cancel;
- }
- path = normalize_reg_path(ctx, path);
+ path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
if (!path) {
goto cancel;
}
- status = dbwrap_delete_bystring(regdb, path);
- /* Don't fail if there are no values around. */
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
- {
- DEBUG(1, ("Deleting %s failed: %s\n", path,
- nt_errstr(status)));
- goto cancel;
- }
- TALLOC_FREE(path);
- /* (c) Delete the list of subkeys of this key */
+ werr = regdb_delete_key_lists(db, path);
+ W_ERROR_NOT_OK_GOTO(werr, cancel);
- path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
- if (!path) {
- goto cancel;
- }
- path = normalize_reg_path(ctx, path);
- if (!path) {
- goto cancel;
- }
- status = dbwrap_delete_bystring(regdb, path);
- /* Don't fail if the subkey record was not found. */
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
- {
- DEBUG(1, ("Deleting %s failed: %s\n", path,
- nt_errstr(status)));
- goto cancel;
- }
TALLOC_FREE(path);
}
/* (2) store the subkey list for the parent */
- if (!regdb_store_keys_internal(key, ctr) ) {
+ if (!regdb_store_keys_internal2(db, key, ctr)) {
DEBUG(0,("regdb_store_keys: Failed to store new subkey list "
"for parent [%s]\n", key));
goto cancel;
goto cancel;
}
- if (!regdb_store_keys_internal(key, subkeys)) {
+ if (!regdb_store_keys_internal2(db, key, subkeys)) {
DEBUG(0,("regdb_store_keys: Failed to store "
"new record for key [%s]\n", key));
goto cancel;
goto cancel;
}
- if (regdb_fetch_keys( path, subkeys ) == -1) {
+ if (regdb_fetch_keys_internal(db, path, subkeys) == -1) {
/* create a record with 0 subkeys */
- if (!regdb_store_keys_internal(path, subkeys)) {
+ if (!regdb_store_keys_internal2(db, path, subkeys)) {
DEBUG(0,("regdb_store_keys: Failed to store "
"new record for key [%s]\n", path));
goto cancel;
TALLOC_FREE(path);
}
- if (regdb->transaction_commit(regdb) != 0) {
+ if (db->transaction_commit(db) != 0) {
DEBUG(0, ("regdb_store_keys: Could not commit transaction\n"));
goto fail;
}
return true;
cancel:
- if (regdb->transaction_cancel(regdb) != 0) {
+ if (db->transaction_cancel(db) != 0) {
smb_panic("regdb_store_keys: transaction_cancel failed\n");
}
return false;
}
+bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
+{
+ return regdb_store_keys_internal(regdb, key, ctr);
+}
+
+static WERROR regdb_create_subkey(const char *key, const char *subkey)
+{
+ WERROR werr;
+ struct regsubkey_ctr *subkeys;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+ if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) {
+ werr = WERR_NOT_FOUND;
+ goto done;
+ }
+
+ 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;
+ }
+
+ if (regsubkey_ctr_key_exists(subkeys, subkey)) {
+ werr = WERR_OK;
+ goto done;
+ }
+
+ talloc_free(subkeys);
+
+ if (regdb->transaction_start(regdb) != 0) {
+ werr = WERR_REG_IO_FAILURE;
+ goto done;
+ }
+
+ 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;
+ }
+
+ werr = regsubkey_ctr_addkey(subkeys, subkey);
+ W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+ if (!regdb_store_keys_internal2(regdb, key, subkeys)) {
+ DEBUG(0, (__location__ " failed to store new subkey list for "
+ "parent key %s\n", key));
+ werr = WERR_REG_IO_FAILURE;
+ goto cancel;
+ }
+
+ if (regdb->transaction_commit(regdb) != 0) {
+ werr = WERR_REG_IO_FAILURE;
+ DEBUG(0, (__location__ " failed to commit transaction\n"));
+ }
+
+ goto done;
+
+cancel:
+ if (regdb->transaction_cancel(regdb) != 0) {
+ smb_panic("regdb_create_subkey: transaction_cancel failed\n");
+ }
+
+done:
+ talloc_free(mem_ctx);
+ return werr;
+}
+
+static WERROR regdb_delete_subkey(const char *key, const char *subkey)
+{
+ WERROR werr;
+ struct regsubkey_ctr *subkeys;
+ char *path;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+ if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) {
+ werr = WERR_NOT_FOUND;
+ goto done;
+ }
+
+ path = talloc_asprintf(mem_ctx, "%s/%s", key, subkey);
+ if (path == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ if (!regdb_key_exists(regdb, path)) {
+ werr = WERR_OK;
+ 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;
+ }
+
+ werr = regsubkey_ctr_delkey(subkeys, subkey);
+ W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+ if (!regdb_store_keys_internal2(regdb, key, subkeys)) {
+ DEBUG(0, (__location__ " failed to store new subkey_list for "
+ "parent key %s\n", key));
+ werr = WERR_REG_IO_FAILURE;
+ goto cancel;
+ }
+
+ if (regdb->transaction_commit(regdb) != 0) {
+ DEBUG(0, (__location__ " failed to commit transaction\n"));
+ werr = WERR_REG_IO_FAILURE;
+ }
+
+ goto done;
-static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key)
+cancel:
+ if (regdb->transaction_cancel(regdb) != 0) {
+ smb_panic("regdb_delete_subkey: transaction_cancel failed\n");
+ }
+
+done:
+ talloc_free(mem_ctx);
+ return werr;
+}
+
+static TDB_DATA regdb_fetch_key_internal(struct db_context *db,
+ TALLOC_CTX *mem_ctx, const char *key)
{
char *path = NULL;
TDB_DATA data;
return make_tdb_data(NULL, 0);
}
- data = dbwrap_fetch_bystring(regdb, mem_ctx, path);
+ data = dbwrap_fetch_bystring(db, mem_ctx, path);
TALLOC_FREE(path);
return data;
* parent_subkey_scanner. The code uses parse_record() to avoid a memcpy of
* the potentially large subkey record.
*
- * The sorted subkey record is deleted in regdb_store_keys_internal and
+ * The sorted subkey record is deleted in regdb_store_keys_internal2 and
* recreated on demand.
*/
goto fail;
}
- res = regdb_fetch_keys(key, ctr);
+ res = regdb_fetch_keys_internal(regdb, key, ctr);
if (res == -1) {
goto fail;
}
* a transaction_commit for transactions that we might be wrapped in.
*/
if (regdb->transaction_commit(regdb) == -1) {
- DEBUG(0, ("create_sorted_subkeys: transaction_start "
+ DEBUG(0, ("create_sorted_subkeys: transaction_commit "
"failed\n"));
- goto fail;
+ result = false;
}
TALLOC_FREE(ctr);
return 0;
}
-static bool scan_parent_subkeys(const char *parent, const char *name)
+static bool scan_parent_subkeys(struct db_context *db, const char *parent,
+ const char *name)
{
char *path = NULL;
char *key = NULL;
}
state.scanned = false;
- res = regdb->parse_record(regdb, string_term_tdb_data(key),
- parent_subkey_scanner, &state);
+ res = db->parse_record(db, string_term_tdb_data(key),
+ parent_subkey_scanner, &state);
if (state.scanned) {
result = state.found;
if (!create_sorted_subkeys(path, key)) {
goto fail;
}
- res = regdb->parse_record(regdb, string_term_tdb_data(key),
- parent_subkey_scanner, &state);
+ res = db->parse_record(db, string_term_tdb_data(key),
+ parent_subkey_scanner, &state);
if ((res == 0) && (state.scanned)) {
result = state.found;
}
* The exeption of this are keys without a parent key,
* i.e. the "base" keys (HKLM, HKCU, ...).
*/
-static bool regdb_key_exists(const char *key)
+static bool regdb_key_exists(struct db_context *db, const char *key)
{
TALLOC_CTX *mem_ctx = talloc_stackframe();
TDB_DATA value;
p = strrchr(path, '/');
if (p == NULL) {
/* this is a base key */
- value = regdb_fetch_key_internal(mem_ctx, path);
+ value = regdb_fetch_key_internal(db, mem_ctx, path);
ret = (value.dptr != NULL);
} else {
*p = '\0';
- ret = scan_parent_subkeys(path, p+1);
+ ret = scan_parent_subkeys(db, path, p+1);
}
done:
released by the caller.
***********************************************************************/
-int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
+static int regdb_fetch_keys_internal(struct db_context *db, const char *key,
+ struct regsubkey_ctr *ctr)
{
WERROR werr;
uint32 num_items;
DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
- if (!regdb_key_exists(key)) {
+ if (!regdb_key_exists(db, key)) {
goto done;
}
- werr = regsubkey_ctr_set_seqnum(ctr, regdb_get_seqnum());
+ werr = regsubkey_ctr_set_seqnum(ctr, db->get_seqnum(db));
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- value = regdb_fetch_key_internal(frame, key);
+ value = regdb_fetch_key_internal(db, frame, key);
if (value.dptr == NULL) {
DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
return ret;
}
+int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
+{
+ return regdb_fetch_keys_internal(regdb, key, ctr);
+}
+
/****************************************************************************
Unpack a list of registry values frem the TDB
***************************************************************************/
-static int regdb_unpack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
+static int regdb_unpack_values(struct regval_ctr *values, uint8 *buf, int buflen)
{
int len = 0;
uint32 type;
Pack all values in all printer keys
***************************************************************************/
-static int regdb_pack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
+static int regdb_pack_values(struct regval_ctr *values, uint8 *buf, int buflen)
{
int len = 0;
int i;
- REGISTRY_VALUE *val;
+ struct regval_blob *val;
int num_values;
if ( !values )
released by the caller.
***********************************************************************/
-int regdb_fetch_values( const char* key, REGVAL_CTR *values )
+int regdb_fetch_values(const char* key, struct regval_ctr *values)
{
char *keystr = NULL;
TALLOC_CTX *ctx = talloc_stackframe();
DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key));
- if (!regdb_key_exists(key)) {
+ if (!regdb_key_exists(regdb, key)) {
goto done;
}
values->seqnum = regdb_get_seqnum();
- value = regdb_fetch_key_internal(ctx, keystr);
+ value = regdb_fetch_key_internal(regdb, ctx, keystr);
if (!value.dptr) {
/* all keys have zero values by default */
return ret;
}
-bool regdb_store_values( const char *key, REGVAL_CTR *values )
+bool regdb_store_values(const char *key, struct regval_ctr *values)
{
TDB_DATA old_data, data;
char *keystr = NULL;
DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key));
- if (!regdb_key_exists(key)) {
+ if (!regdb_key_exists(regdb, key)) {
goto done;
}
DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
- if (!regdb_key_exists(key)) {
+ if (!regdb_key_exists(regdb, key)) {
err = WERR_BADFILE;
goto done;
}
{
TALLOC_CTX *mem_ctx = talloc_stackframe();
char *tdbkey;
- NTSTATUS status;
WERROR err = WERR_NOMEM;
TDB_DATA tdbdata;
- if (!regdb_key_exists(key)) {
+ if (!regdb_key_exists(regdb, key)) {
err = WERR_BADFILE;
goto done;
}
if (secdesc == NULL) {
/* assuming a delete */
- status = dbwrap_trans_delete_bystring(regdb, tdbkey);
- if (NT_STATUS_IS_OK(status)) {
- err = WERR_OK;
- } else {
- err = ntstatus_to_werror(status);
- }
+ err = ntstatus_to_werror(dbwrap_trans_delete_bystring(regdb,
+ tdbkey));
goto done;
}
err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc,
&tdbdata.dptr,
&tdbdata.dsize));
- if (!W_ERROR_IS_OK(err)) {
- goto done;
- }
+ W_ERROR_NOT_OK_GOTO_DONE(err);
- status = dbwrap_trans_store_bystring(regdb, tdbkey, tdbdata, 0);
- if (!NT_STATUS_IS_OK(status)) {
- err = ntstatus_to_werror(status);
- goto done;
- }
+ err = ntstatus_to_werror(dbwrap_trans_store_bystring(regdb, tdbkey,
+ tdbdata, 0));
done:
TALLOC_FREE(mem_ctx);
return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
}
-bool regdb_values_need_update(REGVAL_CTR *values)
+bool regdb_values_need_update(struct regval_ctr *values)
{
return (regdb_get_seqnum() != values->seqnum);
}
* Table of function pointers for default access
*/
-REGISTRY_OPS regdb_ops = {
+struct registry_ops regdb_ops = {
.fetch_subkeys = regdb_fetch_keys,
.fetch_values = regdb_fetch_values,
.store_subkeys = regdb_store_keys,
.store_values = regdb_store_values,
+ .create_subkey = regdb_create_subkey,
+ .delete_subkey = regdb_delete_subkey,
.get_secdesc = regdb_get_secdesc,
.set_secdesc = regdb_set_secdesc,
.subkeys_need_update = regdb_subkeys_need_update,