r187: RPC registry backend fixes
authorJelmer Vernooij <jelmer@samba.org>
Mon, 12 Apr 2004 20:07:50 +0000 (20:07 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:51:15 +0000 (12:51 -0500)
(This used to be commit f832d6776cb10f5c7d7ed83e6f66e4d28a461916)

source4/lib/registry/common/reg_interface.c
source4/lib/registry/common/reg_objects.c
source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
source4/lib/registry/tools/regtree.c

index 5753de1bcae591986210dfc434742a2b27e29486..fdbb7345d2b05448c3b0dd3ecd71dbfafc243d53 100644 (file)
@@ -187,7 +187,12 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
 {
        if(!key) return WERR_INVALID_PARAM;
 
-       if(!key->handle->functions->get_value_by_index) {
+       if(key->handle->functions->get_value_by_index) {
+               WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
+               if(!W_ERROR_IS_OK(status)) 
+                       return status;
+
+       } else if(key->handle->functions->fetch_values) {
                if(!key->cache_values)
                        key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
                
@@ -197,9 +202,7 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
                        return WERR_NO_MORE_ITEMS;
                }
        } else {
-               WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
-               if(!W_ERROR_IS_OK(status)) 
-                       return status;
+               return WERR_NOT_SUPPORTED;
        }
        
        (*val)->parent = key;
index 3f721c107eef27950a4a5b94f572fb779c905443..787ec5212772bfb3a25e6b144c1e6446be780fd2 100644 (file)
@@ -163,11 +163,14 @@ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data)
 REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data)
 {
        REG_KEY *r;
+       const char *parent_path = k?reg_key_get_path(k):"";
        TALLOC_CTX *mem_ctx = talloc_init(name);
        r = talloc(mem_ctx, sizeof(REG_KEY));
        ZERO_STRUCTP(r);
        r->handle = k->handle;
        r->name = talloc_strdup(mem_ctx, name);
+       
+       r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name);
        r->backend_data = data;
        r->mem_ctx = mem_ctx;
        r->ref = 1;
index f17bdbb3f5ee90b8a2d68e9038cffabf01f873ac..f5a7127ed656bcc710b515bd069f6b137bfdbc89 100644 (file)
@@ -71,6 +71,12 @@ struct rpc_data {
        struct policy_handle *hives[10];
 };
 
+struct rpc_key_data {
+       struct policy_handle pol;
+       int num_subkeys;
+       int num_values;
+};
+
 struct {
        const char *name;
        struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
@@ -119,21 +125,30 @@ static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
 static WERROR rpc_close_registry(REG_HANDLE *h)
 {
        dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
-       free(h->backend_data);
        return WERR_OK;
 }
 
-static WERROR rpc_key_put_policy_handle(REG_KEY *k)
+static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
 {
-       struct policy_handle *key_handle, *hive = NULL;
+       struct policy_handle *hive = NULL;
     struct winreg_OpenKey r;
        int i;
        struct rpc_data *mydata = k->handle->backend_data;
+       struct rpc_key_data *mykeydata;
        char *realkeyname, *hivename;
-       if(k->backend_data) return WERR_OK;
+
+       if(k->backend_data) { 
+               *data = k->backend_data; 
+               return WERR_OK;
+       }
+
+       k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
+       *data = mykeydata;
+       mykeydata->num_values = -1;
+       mykeydata->num_subkeys = -1;
 
        /* First, ensure the handle to the hive is opened */
-       realkeyname = strchr(k->path, '\\');
+       realkeyname = strchr(k->path+1, '\\');
        if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1);
        else hivename = strdup(k->path+1);
 
@@ -150,15 +165,13 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k)
                return WERR_FOOBAR;
        }
 
-       if(realkeyname[0] == '\\')realkeyname++;
+       if(realkeyname && realkeyname[0] == '\\')realkeyname++;
 
        if(!realkeyname || !(*realkeyname)) { 
-               k->backend_data = hive;
+               mykeydata->pol = *hive;
                return WERR_OK;
        }
 
-       key_handle = talloc(k->mem_ctx, sizeof(struct policy_handle));
-
        /* Then, open the handle using the hive */
 
        memset(&r, 0, sizeof(struct winreg_OpenKey));
@@ -166,20 +179,19 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k)
     init_winreg_String(&r.in.keyname, realkeyname);
     r.in.unknown = 0x00000000;
     r.in.access_mask = 0x02000000;
-    r.out.handle = key_handle;
+    r.out.handle = &mykeydata->pol;
 
     dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
 
-       if(W_ERROR_IS_OK(r.out.result)) k->backend_data = key_handle;
-                                                                                                                               
        return r.out.result;
 }
 
 static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
 {
        WERROR error;
+       struct rpc_key_data *mykeydata;
        *key = reg_key_new_abs(name, h, NULL);
-       return rpc_key_put_policy_handle(*key);
+       return rpc_key_put_rpc_data(*key, &mykeydata);
 }
 
 static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) 
@@ -189,6 +201,8 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
        struct winreg_String classname;
        struct winreg_Time tm;
        struct rpc_data *mydata = parent->handle->backend_data;
+       struct rpc_key_data *mykeydata = parent->backend_data;
+       WERROR error;
        int i;
        NTSTATUS status;
        TALLOC_CTX *mem_ctx;
@@ -196,17 +210,14 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
        /* If parent is the root key, list the hives */
        if(parent->backend_data == mydata) { 
                if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
-
-               *subkey = reg_key_new_rel(known_hives[n].name, parent, known_hives[n].open(mydata->pipe, parent->handle));
-
-               return WERR_OK;
+               *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL);
+               return rpc_key_put_rpc_data(*subkey, &mykeydata);
        }
 
-       if(!parent->backend_data) {
-               rpc_key_put_policy_handle(parent);
-       }
+       error = rpc_key_put_rpc_data(parent, &mykeydata);
+       if(!W_ERROR_IS_OK(error)) return error;
 
-       r.in.handle = parent->backend_data;
+       r.in.handle = &mykeydata->pol;
        keyname.unknown = 0x0000020a;
        init_winreg_String(&keyname.key_name, NULL);
        init_winreg_String(&classname, NULL);
@@ -229,24 +240,56 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
 
 static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key)
 {
-       rpc_key_put_policy_handle(parent);
+       struct rpc_key_data *mykeydata;
+       WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
+       if(!W_ERROR_IS_OK(error)) return error;
+
        /* FIXME */
        return WERR_NOT_SUPPORTED;
 }
 
+static WERROR rpc_query_key(REG_KEY *k)
+{
+    NTSTATUS status;
+    struct winreg_QueryInfoKey r;
+       struct rpc_data *mydata = k->handle->backend_data;
+       struct rpc_key_data *mykeydata;
+       WERROR error = rpc_key_put_rpc_data(k, &mykeydata);
+                                                                                                       
+    r.in.handle = &mykeydata->pol;
+    init_winreg_String(&r.in.class, NULL);
+                                                                                                       
+    status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
+                                                                                                       
+    if (!NT_STATUS_IS_OK(status)) {
+        printf("QueryInfoKey failed - %s\n", nt_errstr(status));
+        return ntstatus_to_werror(status);
+    }
+                                                                                                       
+    if (W_ERROR_IS_OK(r.out.result)) {
+               mykeydata->num_subkeys = r.out.num_subkeys;
+               mykeydata->num_values = r.out.num_values;
+       } 
 
+       return r.out.result;
+}
 
 static WERROR rpc_del_key(REG_KEY *k)
 {
        NTSTATUS status;
        struct rpc_data *mydata = k->handle->backend_data;
+       struct rpc_key_data *mykeydata;
        struct winreg_DeleteKey r;
        REG_KEY *parent;
-       WERROR error = reg_key_get_parent(k, &parent);
+       WERROR error;
+       
+       error = reg_key_get_parent(k, &parent);
+       if(!W_ERROR_IS_OK(error)) return error;
+       
+       error = rpc_key_put_rpc_data(parent, &mykeydata);
        if(!W_ERROR_IS_OK(error)) return error;
-       rpc_key_put_policy_handle(parent);
 
-    r.in.handle = parent->backend_data;
+    r.in.handle = &mykeydata->pol;
     init_winreg_String(&r.in.key, k->name);
  
     status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
@@ -259,6 +302,52 @@ static void rpc_close_key(REG_KEY *k)
        reg_key_free(k);
 }
 
+static WERROR rpc_num_values(REG_KEY *key, int *count) {
+       struct rpc_key_data *mykeydata;
+       WERROR error;
+               
+       /* Root is a special case */
+       if(key->backend_data == key->handle->backend_data) {
+               *count = 0;
+               return WERR_OK;
+       }
+               
+       error = rpc_key_put_rpc_data(key, &mykeydata);
+       if(!W_ERROR_IS_OK(error)) return error;
+
+       if(mykeydata->num_values == -1) {
+               WERROR error = rpc_query_key(key);
+               if(!W_ERROR_IS_OK(error)) return error;
+       }
+                       
+       *count = mykeydata->num_values;
+       return WERR_OK;
+}
+
+static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
+       struct rpc_key_data *mykeydata;
+       WERROR error;
+       
+       /* Root is a special case */
+       if(key->backend_data == key->handle->backend_data) {
+               int i;
+               for(i = 0; known_hives[i].name; i++);
+               *count = i;
+               return WERR_OK;
+       }
+       
+       error = rpc_key_put_rpc_data(key, &mykeydata);
+       if(!W_ERROR_IS_OK(error)) return error;
+
+       if(mykeydata->num_subkeys == -1) {
+               WERROR error = rpc_query_key(key);
+               if(!W_ERROR_IS_OK(error)) return error;
+       }
+                       
+       *count = mykeydata->num_subkeys;
+       return WERR_OK;
+}
+
 static struct registry_ops reg_backend_rpc = {
        .name = "rpc",
        .open_registry = rpc_open_registry,
@@ -269,6 +358,8 @@ static struct registry_ops reg_backend_rpc = {
        .add_key = rpc_add_key,
        .del_key = rpc_del_key,
        .free_key_backend_data = rpc_close_key,
+       .num_subkeys = rpc_num_subkeys,
+       .num_values = rpc_num_values,
 };
 
 NTSTATUS reg_rpc_init(void)
index b8a5f5049683f298e0638aca03bee9df368a4a21..eb32b1e55ea6908f44a8b4991b7154559400b96a 100644 (file)
@@ -38,7 +38,7 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals)
        }
 
        if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
-               DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p)));
+               DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path(p), win_errstr(error)));
        }
 
        if(!novals) {