diff options
Diffstat (limited to 'source3/registry/reg_objects.c')
-rw-r--r-- | source3/registry/reg_objects.c | 175 |
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; |