summaryrefslogtreecommitdiff
path: root/source3/registry/reg_objects.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/registry/reg_objects.c')
-rw-r--r--source3/registry/reg_objects.c175
1 files changed, 148 insertions, 27 deletions
diff --git a/source3/registry/reg_objects.c b/source3/registry/reg_objects.c
index 47122ccad2..b975ced324 100644
--- a/source3/registry/reg_objects.c
+++ b/source3/registry/reg_objects.c
@@ -24,25 +24,135 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_REGISTRY
+struct regsubkey_ctr {
+ uint32_t num_subkeys;
+ char **subkeys;
+ struct db_context *subkeys_hash;
+ int seqnum;
+};
+
/**********************************************************************
- Note that the REGSUB_CTR and REGVAL_CTR objects *must* be talloc()'d
- since the methods use the object pointer as the talloc context for
- internal private data.
+ Note that the struct regsubkey_ctr and REGVAL_CTR objects *must* be
+ talloc()'d since the methods use the object pointer as the talloc
+ context for internal private data.
- There is no longer a regXXX_ctr_intit() and regXXX_ctr_destroy()
+ There is no longer a regval_ctr_intit() and regval_ctr_destroy()
pair of functions. Simply TALLOC_ZERO_P() and TALLOC_FREE() the
object.
**********************************************************************/
+WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr)
+{
+ if (ctr == NULL) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *ctr = talloc_zero(mem_ctx, struct regsubkey_ctr);
+ if (*ctr == NULL) {
+ return WERR_NOMEM;
+ }
+
+ (*ctr)->subkeys_hash = db_open_rbt(*ctr);
+ if ((*ctr)->subkeys_hash == NULL) {
+ talloc_free(*ctr);
+ return WERR_NOMEM;
+ }
+
+ return WERR_OK;
+}
+
+WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum)
+{
+ if (ctr == NULL) {
+ return WERR_INVALID_PARAM;
+ }
+
+ ctr->seqnum = seqnum;
+
+ return WERR_OK;
+}
+
+int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr)
+{
+ if (ctr == NULL) {
+ return -1;
+ }
+
+ return ctr->seqnum;
+}
+
+static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr,
+ const char *keyname,
+ uint32 idx)
+{
+ WERROR werr;
+
+ werr = ntstatus_to_werror(dbwrap_store_bystring(ctr->subkeys_hash,
+ keyname,
+ make_tdb_data((uint8 *)&idx,
+ sizeof(idx)),
+ TDB_REPLACE));
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, ("error hashing new key '%s' in container: %s\n",
+ keyname, win_errstr(werr)));
+ }
+
+ return werr;
+}
+
+static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr,
+ const char *keyname)
+{
+ WERROR werr;
+
+ werr = ntstatus_to_werror(dbwrap_delete_bystring(ctr->subkeys_hash,
+ keyname));
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, ("error unhashing key '%s' in container: %s\n",
+ keyname, win_errstr(werr)));
+ }
+
+ return werr;
+}
+
+static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr,
+ const char *keyname,
+ uint32 *idx)
+{
+ TDB_DATA data;
+
+ if ((ctr == NULL) || (keyname == NULL)) {
+ return WERR_INVALID_PARAM;
+ }
+
+ data = dbwrap_fetch_bystring(ctr->subkeys_hash, ctr, keyname);
+ if (data.dptr == NULL) {
+ return WERR_NOT_FOUND;
+ }
+
+ if (data.dsize != sizeof(*idx)) {
+ talloc_free(data.dptr);
+ return WERR_INVALID_DATATYPE;
+ }
+
+ if (idx != NULL) {
+ *idx = *(uint32 *)data.dptr;
+ }
+
+ talloc_free(data.dptr);
+ return WERR_OK;
+}
+
/***********************************************************************
Add a new key to the array
**********************************************************************/
-WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
+WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname )
{
char **newkeys;
+ WERROR werr;
if ( !keyname ) {
return WERR_OK;
@@ -68,6 +178,10 @@ WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
*/
return WERR_NOMEM;
}
+
+ werr = regsubkey_ctr_hash_keyname(ctr, keyname, ctr->num_subkeys);
+ W_ERROR_NOT_OK_RETURN(werr);
+
ctr->num_subkeys++;
return WERR_OK;
@@ -77,57 +191,64 @@ WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
Delete a key from the array
**********************************************************************/
-int regsubkey_ctr_delkey( REGSUBKEY_CTR *ctr, const char *keyname )
+WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname )
{
- int i;
+ WERROR werr;
+ uint32 idx, j;
- if ( !keyname )
- return ctr->num_subkeys;
+ if (keyname == NULL) {
+ return WERR_INVALID_PARAM;
+ }
/* make sure the keyname is actually already there */
- for ( i=0; i<ctr->num_subkeys; i++ ) {
- if ( strequal( ctr->subkeys[i], keyname ) )
- break;
- }
+ werr = regsubkey_ctr_index_for_keyname(ctr, keyname, &idx);
+ W_ERROR_NOT_OK_RETURN(werr);
- if ( i == ctr->num_subkeys )
- return ctr->num_subkeys;
+ werr = regsubkey_ctr_unhash_keyname(ctr, keyname);
+ W_ERROR_NOT_OK_RETURN(werr);
/* update if we have any keys left */
ctr->num_subkeys--;
- if ( i < ctr->num_subkeys )
- memmove(&ctr->subkeys[i], &ctr->subkeys[i+1],
- sizeof(char*) * (ctr->num_subkeys-i));
+ if (idx < ctr->num_subkeys) {
+ memmove(&ctr->subkeys[idx], &ctr->subkeys[idx+1],
+ sizeof(char *) * (ctr->num_subkeys - idx));
+
+ /* we have to re-hash rest of the array... :-( */
+ for (j = idx; j < ctr->num_subkeys; j++) {
+ werr = regsubkey_ctr_hash_keyname(ctr, ctr->subkeys[j], j);
+ W_ERROR_NOT_OK_RETURN(werr);
+ }
+ }
- return ctr->num_subkeys;
+ return WERR_OK;
}
/***********************************************************************
Check for the existance of a key
**********************************************************************/
-bool regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname )
+bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname )
{
- int i;
+ WERROR werr;
if (!ctr->subkeys) {
return False;
}
- for ( i=0; i<ctr->num_subkeys; i++ ) {
- if ( strequal( ctr->subkeys[i],keyname ) )
- return True;
+ werr = regsubkey_ctr_index_for_keyname(ctr, keyname, NULL);
+ if (!W_ERROR_IS_OK(werr)) {
+ return false;
}
- return False;
+ return true;
}
/***********************************************************************
How many keys does the container hold ?
**********************************************************************/
-int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
+int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr )
{
return ctr->num_subkeys;
}
@@ -136,7 +257,7 @@ int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
Retreive a specific key string
**********************************************************************/
-char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index )
+char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32_t key_index )
{
if ( ! (key_index < ctr->num_subkeys) )
return NULL;