r12528: Add seperate proto headers for ntvfs, tdr, smb_server and nbt_server.
[samba.git] / source4 / lib / registry / common / reg_interface.c
index 5e6b4fbac882c906fa15128170312aae33fc9db7..00fa42d34277366df98af09da69c8950d9a809d3 100644 (file)
 */
 
 #include "includes.h"
-#include "lib/registry/common/registry.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_REGISTRY
+#include "dlinklist.h"
+#include "lib/registry/registry.h"
+#include "smb_build.h"
 
 /* List of available backends */
 static struct reg_init_function_entry *backends = NULL;
@@ -30,516 +29,507 @@ static struct reg_init_function_entry *backends = NULL;
 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
 
 /* Register new backend */
-NTSTATUS registry_register(void *_function)  
+_PUBLIC_ NTSTATUS registry_register(const void *_hive_ops)  
 {
-       struct registry_ops *functions = _function;
+       const struct hive_operations *hive_ops = _hive_ops;
        struct reg_init_function_entry *entry = backends;
 
-       if (!functions || !functions->name) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
+       DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
 
        /* Check for duplicates */
-       if (reg_find_backend_entry(functions->name)) {
-               DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
+       if (reg_find_backend_entry(hive_ops->name)) {
+               DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       entry = malloc(sizeof(struct reg_init_function_entry));
-       entry->functions = functions;
+       entry = talloc(talloc_autofree_context(), struct reg_init_function_entry);
+       entry->hive_functions = hive_ops;
 
        DLIST_ADD(backends, entry);
-       DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
+       DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
        return NT_STATUS_OK;
 }
 
 /* Find a backend in the list of available backends */
 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
 {
-       struct reg_init_function_entry *entry = backends;
+       struct reg_init_function_entry *entry;
+
+       entry = backends;
 
        while(entry) {
-               if (strcmp(entry->functions->name, name)==0) return entry;
+               if (strcmp(entry->hive_functions->name, name) == 0) return entry;
                entry = entry->next;
        }
 
        return NULL;
 }
 
-/* Open a registry file/host/etc */
-WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h)
+_PUBLIC_ NTSTATUS registry_init(void)
 {
-       struct reg_init_function_entry *entry;
-       static BOOL reg_first_init = True;
-       TALLOC_CTX *mem_ctx;
-       REG_HANDLE *ret;
-       NTSTATUS status;
-       WERROR werr;
+       init_module_fn static_init[] = STATIC_REGISTRY_MODULES;
+       init_module_fn *shared_init = load_samba_modules(NULL, "registry");
+
+       run_init_functions(static_init);
+       run_init_functions(shared_init);
+
+       talloc_free(shared_init);
+       
+       return NT_STATUS_OK;
+}
+
+/* Check whether a certain backend is present */
+BOOL reg_has_backend(const char *backend)
+{
+       return reg_find_backend_entry(backend) != NULL?True:False;
+}
+
+static struct {
+       uint32_t handle;
+       const char *name;
+} predef_names[] = 
+{
+       {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
+       {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
+       {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
+       {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
+       {HKEY_USERS, "HKEY_USERS" },
+       {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
+       {HKEY_DYN_DATA, "HKEY_DYN_DATA" },
+       {HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
+       {HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
+       { 0, NULL }
+};
+
+_PUBLIC_ int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys)
+{
+       int i;
+       *predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(predef_names));
+       *hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(predef_names));
+
+       for (i = 0; predef_names[i].name; i++) {
+               (*predefs)[i] = talloc_strdup(mem_ctx, predef_names[i].name);
+               (*hkeys)[i] = predef_names[i].handle;
+       }
+
+       return i;
+}
+
+const char *reg_get_predef_name(uint32_t hkey)
+{
+       int i;
+       for (i = 0; predef_names[i].name; i++) {
+               if (predef_names[i].handle == hkey) return predef_names[i].name;
+       }
+
+       return NULL;
+}
+
+WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
+{
+       int i;
+       
+       for (i = 0; predef_names[i].name; i++) {
+               if (!strcasecmp(predef_names[i].name, name)) return reg_get_predefined_key(ctx, predef_names[i].handle, key);
+       }
+
+       DEBUG(1, ("No predefined key with name '%s'\n", name));
+       
+       return WERR_BADFILE;
+}
 
-       if(reg_first_init) {
-               status = register_subsystem("registry", registry_register);
-               if (!NT_STATUS_IS_OK(status)) 
-                       return WERR_GENERAL_FAILURE;
+WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
+{
+       WERROR ret = ctx->get_predefined_key(ctx, hkey, key);
 
-               static_init_reg;
-               reg_first_init = False;
+       if (W_ERROR_IS_OK(ret)) {
+               (*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey));
+               (*key)->path = ""; 
        }
 
+       return ret;
+}
+
+/* Open a registry file/host/etc */
+_PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root)
+{
+       struct registry_hive *rethive;
+       struct registry_key *retkey = NULL;
+       struct reg_init_function_entry *entry;
+       WERROR werr;
+
        entry = reg_find_backend_entry(backend);
        
        if (!entry) {
                DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
                return WERR_GENERAL_FAILURE;
        }
-       
-       mem_ctx = talloc_init(backend);
-       ret = talloc(mem_ctx, sizeof(REG_HANDLE));
-       ZERO_STRUCTP(ret);      
-       ret->location = location?talloc_strdup(mem_ctx, location):NULL;
-       ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL;
-       ret->functions = entry->functions;
-       ret->backend_data = NULL;
-       ret->mem_ctx = mem_ctx;
-       *h = ret;
-
-       if(!entry->functions->open_registry) {
-               return WERR_OK;
+
+       if(!entry->hive_functions || !entry->hive_functions->open_hive) {
+               return WERR_NOT_SUPPORTED;
        }
        
-       werr = entry->functions->open_registry(ret, location, credentials);
+       rethive = talloc(parent_ctx, struct registry_hive);
+       rethive->location = location?talloc_strdup(rethive, location):NULL;
+       rethive->functions = entry->hive_functions;
+       rethive->backend_data = NULL;
 
-       if(W_ERROR_IS_OK(werr)) 
-               return WERR_OK;
+       werr = entry->hive_functions->open_hive(rethive, &retkey);
+
+       if(!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
+       if(!retkey) {
+               DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
+               return WERR_GENERAL_FAILURE;
+       }
+
+       rethive->root = retkey;
 
-       talloc_destroy(mem_ctx);
-       return werr;
+       retkey->hive = rethive;
+       retkey->name = NULL;
+       retkey->path = talloc_strdup(retkey, "");
+       
+       *root = retkey;
+
+       return WERR_OK;
 }
 
 /* Open a key 
  * First tries to use the open_key function from the backend
  * then falls back to get_subkey_by_name and later get_subkey_by_index 
  */
-WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
+_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
 {
-       char *fullname;
-       WERROR status;
-       REG_KEY *ret = NULL;
-       TALLOC_CTX *mem_ctx;
+       WERROR error;
 
        if(!parent) {
-               DEBUG(0, ("Invalid parent key specified"));
+               DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
                return WERR_INVALID_PARAM;
        }
 
-       if(!parent->handle->functions->open_key && 
-          (parent->handle->functions->get_subkey_by_name || 
-          parent->handle->functions->get_subkey_by_index)) {
+       if(!parent->hive->functions->open_key && 
+          (parent->hive->functions->get_subkey_by_name || 
+          parent->hive->functions->get_subkey_by_index)) {
                char *orig = strdup(name), 
                         *curbegin = orig, 
                         *curend = strchr(orig, '\\');
-               REG_KEY *curkey = parent;
+               struct registry_key *curkey = parent;
 
                while(curbegin && *curbegin) {
                        if(curend)*curend = '\0';
-                       status = reg_key_get_subkey_by_name(curkey, curbegin, result);
-                       if(!NT_STATUS_IS_OK(status)) {
+                       error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
+                       if(!W_ERROR_IS_OK(error)) {
                                SAFE_FREE(orig);
-                               return status;
+                               return error;
                        }
                        if(!curend) break;
                        curbegin = curend + 1;
                        curend = strchr(curbegin, '\\');
                }
                SAFE_FREE(orig);
-               
+
                *result = curkey;
+               
                return WERR_OK;
        }
 
-       mem_ctx = talloc_init("mem_ctx");
-
-       fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name);
-\
-
-       if(!parent->handle->functions->open_key) {
+       if(!parent->hive->functions->open_key) {
                DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
                return WERR_NOT_SUPPORTED;
        }
 
-       status = parent->handle->functions->open_key(parent->handle, fullname, result);
+       error = parent->hive->functions->open_key(mem_ctx, parent, name, result);
 
-       if(!NT_STATUS_IS_OK(status)) {
-               talloc_destroy(mem_ctx);
-               return status;
-       }
+       if(!W_ERROR_IS_OK(error)) return error;
                
-       ret->handle = parent->handle;
-       ret->path = fullname;
-       talloc_steal(mem_ctx, ret->mem_ctx, fullname);
-
-       talloc_destroy(mem_ctx);
-
-       *result = ret;
+       (*result)->hive = parent->hive;
+       (*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
+       (*result)->hive = parent->hive;
 
        return WERR_OK;
 }
 
-WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
+_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val)
 {
        if(!key) return WERR_INVALID_PARAM;
 
-       if(!key->handle->functions->get_value_by_index) {
-               if(!key->cache_values)
-                       key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
-               
-               if(idx < key->cache_values_count && idx >= 0) {
-                       *val = reg_val_dup(key->cache_values[idx]);
-               } else {
-                       return WERR_NO_MORE_ITEMS;
-               }
-       } else {
-               WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
+       if(key->hive->functions->get_value_by_index) {
+               WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
                if(!W_ERROR_IS_OK(status)) 
                        return status;
+       } else {
+               return WERR_NOT_SUPPORTED;
        }
        
-       (*val)->parent = key;
-       (*val)->handle = key->handle;
        return WERR_OK;
 }
 
-WERROR reg_key_num_subkeys(REG_KEY *key, int *count)
+WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count)
 {
        if(!key) return WERR_INVALID_PARAM;
        
-       if(!key->handle->functions->num_subkeys) {
-               if(!key->cache_subkeys) 
-                       key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
+       if(key->hive->functions->num_subkeys) {
+               return key->hive->functions->num_subkeys(key, count);
+       }
 
-               *count = key->cache_subkeys_count;
-               return WERR_OK;
+       if(key->hive->functions->get_subkey_by_index) {
+               int i;
+               WERROR error;
+               struct registry_key *dest = NULL;
+               TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
+               
+               for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
+               talloc_free(mem_ctx);
+
+               *count = i;
+               if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
+               return error;
        }
 
-       return key->handle->functions->num_subkeys(key, count);
+       return WERR_NOT_SUPPORTED;
 }
 
-WERROR reg_key_num_values(REG_KEY *key, int *count)
+WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count)
 {
        
        if(!key) return WERR_INVALID_PARAM;
-       
-       if(!key->handle->functions->num_values) {
-               if(!key->handle->functions->fetch_values) {
-                       DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name));
-                       return WERR_NOT_SUPPORTED;
-               }
+
+       if (key->hive->functions->num_values) {
+               return key->hive->functions->num_values(key, count);
+       }
+
+       if(key->hive->functions->get_value_by_index) {
+               int i;
+               WERROR error;
+               struct registry_value *dest;
+               TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
                
-               if(!key->cache_values) 
-                       key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
+               for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
+               talloc_free(mem_ctx);
 
-               *count = key->cache_values_count;
-               return WERR_OK;
+               *count = i;
+               if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
+               return error;
        }
 
-       
-       return key->handle->functions->num_values(key, count);
+       return WERR_NOT_SUPPORTED;
 }
 
-WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey)
+WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey)
 {
        if(!key) return WERR_INVALID_PARAM;
 
-       if(!key->handle->functions->get_subkey_by_index) {
-               if(!key->cache_subkeys) 
-                       key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
-
-               if(idx < key->cache_subkeys_count) {
-                       *subkey = reg_key_dup(key->cache_subkeys[idx]);
-               } else {
-                       return WERR_NO_MORE_ITEMS;
-               }
-       } else {
-               WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey);
+       if(key->hive->functions->get_subkey_by_index) {
+               WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
                if(!NT_STATUS_IS_OK(status)) return status;
+       } else {
+               return WERR_NOT_SUPPORTED;
        }
 
-       (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
-       (*subkey)->handle = key->handle;
-
+       if(key->hive->root == key) 
+               (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
+       else 
+               (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
 
+       (*subkey)->hive = key->hive;
        return WERR_OK;;
 }
 
-WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey)
+WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey)
 {
        int i;
-       REG_KEY *ret = NULL;
        WERROR error = WERR_OK;
 
        if(!key) return WERR_INVALID_PARAM;
 
-       if(key->handle->functions->get_subkey_by_name) {
-               error = key->handle->functions->get_subkey_by_name(key,name,subkey);
-       } else {
+       if(key->hive->functions->get_subkey_by_name) {
+               error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
+       } else if(key->hive->functions->open_key) {
+               error = key->hive->functions->open_key(mem_ctx, key, name, subkey);
+       } else if(key->hive->functions->get_subkey_by_index) {
                for(i = 0; W_ERROR_IS_OK(error); i++) {
-                       error = reg_key_get_subkey_by_index(key, i, subkey);
-                       if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
+                       error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
+                       if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) {
                                break;
                        }
-                       reg_key_free(*subkey);
                }
 
+               if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
+                       error = WERR_DEST_NOT_FOUND;
+       } else {
+               return WERR_NOT_SUPPORTED;
        }
 
-       if(!W_ERROR_IS_OK(error) && W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
-               return error;
+       if(!W_ERROR_IS_OK(error)) return error;
 
-       ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
-       ret->handle = key->handle;
+       (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
+       (*subkey)->hive = key->hive;
 
-       *subkey = ret;
-               
        return WERR_OK; 
 }
 
-WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val)
+WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val)
 {
-       int i, max;
-       REG_VAL *ret = NULL;
+       int i;
        WERROR error = WERR_OK;
 
        if(!key) return WERR_INVALID_PARAM;
 
-       if(key->handle->functions->get_value_by_name) {
-               error = key->handle->functions->get_value_by_name(key,name, val);
+       if(key->hive->functions->get_value_by_name) {
+               error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
        } else {
                for(i = 0; W_ERROR_IS_OK(error); i++) {
-                       error = reg_key_get_value_by_index(key, i, val);
-                       if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
+                       error = reg_key_get_value_by_index(mem_ctx, key, i, val);
+                       if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) {
                                break;
                        }
-                       reg_val_free(*val);
                }
        }
 
-       if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
-               return error;
-       
-       (*val)->parent = key;
-       (*val)->handle = key->handle;
-       
-       return WERR_OK;
+       if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
+               return WERR_DEST_NOT_FOUND;
+
+       return error;
 }
 
-WERROR reg_key_del(REG_KEY *key)
+WERROR reg_key_del(struct registry_key *parent, const char *name)
 {
        WERROR error;
-       if(!key) return WERR_INVALID_PARAM;
+       if(!parent) return WERR_INVALID_PARAM;
        
        
-       if(!key->handle->functions->del_key)
+       if(!parent->hive->functions->del_key)
                return WERR_NOT_SUPPORTED;
        
-       error = key->handle->functions->del_key(key);
+       error = parent->hive->functions->del_key(parent, name);
        if(!W_ERROR_IS_OK(error)) return error;
 
-       /* Invalidate cache */
-       key->cache_subkeys = NULL;
-       key->cache_subkeys_count = 0;
        return WERR_OK;
 }
 
-WERROR reg_sync(REG_KEY *h, const char *location)
-{
-       if(!h->handle->functions->sync_key)
-               return WERR_OK;
-
-       return h->handle->functions->sync_key(h, location);
-}
-
-WERROR reg_key_del_recursive(REG_KEY *key)
+WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey)
 {
-       BOOL succeed = True;
-       WERROR error = WERR_OK;
-       int i;
+       WERROR error;
        
-       /* Delete all values for specified key */
-       for(i = 0; W_ERROR_IS_OK(error); i++) {
-               REG_VAL *val;
-               error = reg_key_get_value_by_index(key, i, &val);
-               if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
-                       return error;
-
-               if(W_ERROR_IS_OK(error)) {
-                       error = reg_val_del(val);
-                       if(!W_ERROR_IS_OK(error)) return error;
-               }
+       if (!parent) return WERR_INVALID_PARAM;
+       
+       if (!parent->hive->functions->add_key) {
+               DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
+               return WERR_NOT_SUPPORTED;
        }
 
-       error = WERR_OK;
-
-       /* Delete all keys below this one */
-       for(i = 0; W_ERROR_IS_OK(error); i++) {
-               REG_KEY *subkey;
+       error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
 
-               error = reg_key_get_subkey_by_index(key, i, &subkey);
-               if(!W_ERROR_IS_OK(error)) return error;
+       if(!W_ERROR_IS_OK(error)) return error;
 
-               error = reg_key_del_recursive(subkey);
-               if(!W_ERROR_IS_OK(error)) return error;
+       if (!*newkey) {
+               DEBUG(0, ("Backend returned WERR_OK, but didn't specify key!\n"));
+               return WERR_GENERAL_FAILURE;
        }
+       
+       (*newkey)->hive = parent->hive;
 
-       return reg_key_del(key);
+       return WERR_OK;
 }
 
-WERROR reg_val_del(REG_VAL *val)
+_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data)
 {
-       WERROR error;
-       if (!val) return WERR_INVALID_PARAM;
+       /* A 'real' set function has preference */
+       if (key->hive->functions->set_value) 
+               return key->hive->functions->set_value(key, value, type, data);
 
-       if (!val->handle->functions->del_value) {
-               DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name));
-               return WERR_NOT_SUPPORTED;
-       }
-       
-       error = val->handle->functions->del_value(val);
+       DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
+       return WERR_NOT_SUPPORTED;
+}
 
-       if(!W_ERROR_IS_OK(error)) return error;
 
-       val->parent->cache_values = NULL;
-       val->parent->cache_values_count = 0;
+WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc)
+{
+       /* A 'real' set function has preference */
+       if (key->hive->functions->key_get_sec_desc) 
+               return key->hive->functions->key_get_sec_desc(ctx, key, secdesc);
 
-       return WERR_OK;
+       DEBUG(1, ("Backend '%s' doesn't support method get_sec_desc\n", key->hive->functions->name));
+       return WERR_NOT_SUPPORTED;
 }
 
-WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path)
+_PUBLIC_ WERROR reg_del_value(const struct registry_key *key, const char *valname)
 {
-       REG_KEY *cur, *prevcur = parent;
-       WERROR error;
-       char *begin = (char *)path, *end;
+       WERROR ret = WERR_OK;
+       if(!key->hive->functions->del_value)
+               return WERR_NOT_SUPPORTED;
 
-       while(1) { 
-               end = strchr(begin, '\\');
-               if(end) *end = '\0';
-               
-               error = reg_key_get_subkey_by_name(prevcur, begin, &cur);
+       ret = key->hive->functions->del_value(key, valname);
 
-               /* Key is not there, add it */
-               if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
-                       error = reg_key_add_name(prevcur, begin, 0, NULL, &cur);
-                       if(!W_ERROR_IS_OK(error)) return error;
-               }
+       if(!W_ERROR_IS_OK(ret)) return ret;
 
-               if(!W_ERROR_IS_OK(error)) {
-                       if(end) *end = '\\';
-                       return error;
-               }
-               
-               if(!end) break;
-               *end = '\\';
-               begin = end+1;
-               prevcur = cur;
-       }
-       return WERR_OK;
+       return ret;
 }
 
-WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **newkey)
+WERROR reg_key_flush(const struct registry_key *key)
 {
-       WERROR error;
-       
-       if (!parent) return WERR_INVALID_PARAM;
+       if (!key) {
+               return WERR_INVALID_PARAM;
+       }
        
-       if (!parent->handle->functions->add_key) {
-               DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name));
-               return WERR_NOT_SUPPORTED;
+       if (key->hive->functions->flush_key) {
+               return key->hive->functions->flush_key(key);
        }
-
-       error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey);
-
-       if(!W_ERROR_IS_OK(error)) return error;
        
-       (*newkey)->handle = parent->handle;
-       (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name);
-
-       parent->cache_subkeys = NULL;
-       parent->cache_subkeys_count = 0;
+       /* No need for flushing, apparently */
        return WERR_OK;
 }
 
-WERROR reg_val_update(REG_VAL *val, int type, void *data, int len)
+WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize)
 {
+       int i = 0; 
+       struct registry_key *subkey;
        WERROR error;
-       
-       /* A 'real' update function has preference */
-       if (val->handle->functions->update_value) 
-               return val->handle->functions->update_value(val, type, data, len);
-
-       /* Otherwise, just remove and add again */
-       if (val->handle->functions->add_value && 
-               val->handle->functions->del_value) {
-               REG_VAL *new;
-               if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) 
-                       return error;
-               
-               error = val->handle->functions->add_value(val->parent, val->name, type, data, len);
-               if(!W_ERROR_IS_OK(error)) return error;
-               memcpy(val, new, sizeof(REG_VAL));
-               val->parent->cache_values = NULL;
-               val->parent->cache_values_count = 0;
-               return WERR_OK;
-       }
-               
-       DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name));
-       return WERR_NOT_SUPPORTED;
-}
+       TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
 
-void reg_free(REG_HANDLE *h)
-{
-       if(!h->functions->close_registry) return;
+       *max_subkeylen = *max_subkeysize = 0;
 
-       h->functions->close_registry(h);
-}
+       do {
+               error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
 
-WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key) 
-{
-       WERROR ret;
-       if(h->functions->open_root_key) {
-               ret = h->functions->open_root_key(h, key);
-       } else if(h->functions->open_key) {
-               ret = h->functions->open_key(h, "\\", key);
-       } else {
-               DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name));
-               ret = WERR_NOT_SUPPORTED;
-       }
+               if (W_ERROR_IS_OK(error)) {
+                       *max_subkeysize = MAX(*max_subkeysize, 0xFF);
+                       *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
+               }
 
-       if(W_ERROR_IS_OK(ret)) {
-               (*key)->handle = h;
-               (*key)->path = talloc_strdup((*key)->mem_ctx, "\\");
-       }
+               i++;
+       } while (W_ERROR_IS_OK(error));
 
-       return ret;
+       talloc_free(mem_ctx);
+
+       return WERR_OK;
 }
 
-WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen)
+WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize)
 {
-       WERROR ret = WERR_OK;
-       if(!key->handle->functions->add_value)
-               return WERR_NOT_SUPPORTED;
+       int i = 0; 
+       struct registry_value *value;
+       WERROR error;
+       TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
 
-       ret = key->handle->functions->add_value(key, name, type, value, vallen);
+       *max_valnamelen = *max_valbufsize = 0;
 
-       if(!W_ERROR_IS_OK(ret)) return ret;
+       do {
+               error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
 
-       /* Invalidate the cache */
-       key->cache_values = NULL;
-       key->cache_values_count = 0;
-       return ret;
-}
+               if (W_ERROR_IS_OK(error)) {
+                       if (value->name) {
+                               *max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
+                       }
+                       *max_valbufsize = MAX(*max_valbufsize, value->data.length);
+               }
 
-WERROR reg_save(REG_HANDLE *h, const char *location)
-{
-       /* FIXME */     
-       return WERR_NOT_SUPPORTED;
+               i++;
+       } while (W_ERROR_IS_OK(error));
+
+       talloc_free(mem_ctx);
+
+       return WERR_OK;
 }