r825: - Introduce support for multiple roots (or 'hives')
authorJelmer Vernooij <jelmer@samba.org>
Sat, 22 May 2004 18:49:25 +0000 (18:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:53:53 +0000 (12:53 -0500)
- Clean up rpc backend (possible now that multiple hives are supported)

12 files changed:
source/lib/registry/common/reg_interface.c
source/lib/registry/common/reg_objects.c
source/lib/registry/common/registry.h
source/lib/registry/reg_backend_dir/reg_backend_dir.c
source/lib/registry/reg_backend_nt4/reg_backend_nt4.c
source/lib/registry/reg_backend_rpc/reg_backend_rpc.c
source/lib/registry/reg_backend_w95/reg_backend_w95.c
source/lib/registry/tools/gregedit.c
source/lib/registry/tools/regdiff.c
source/lib/registry/tools/regpatch.c
source/lib/registry/tools/regshell.c
source/lib/registry/tools/regtree.c

index 4d1726c542a47f309d892d42370570ae39530617..3e5a545f9a93c6f6d66cbe6774187c3504e28254 100644 (file)
@@ -117,6 +117,25 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia
        return werr;
 }
 
+WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result)
+{
+       REG_KEY *hive;
+       WERROR error;
+       int i, hivelength;
+
+       if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
+       else hivelength = strlen(name);
+
+       for(i = 0; W_ERROR_IS_OK(error); i++) {
+               error = reg_get_hive(handle, i, &hive);
+               if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
+                       return reg_open_key(hive, name, result);
+               }
+       }
+
+       return error;
+}
+
 /* 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 
@@ -166,7 +185,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
                return WERR_NOT_SUPPORTED;
        }
 
-       error = parent->handle->functions->open_key(parent->handle, fullname, result);
+       error = parent->handle->functions->open_key(parent->handle, parent->hive, fullname, result);
 
        if(!W_ERROR_IS_OK(error)) {
                talloc_destroy(mem_ctx);
@@ -175,6 +194,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
                
        (*result)->handle = parent->handle;
        (*result)->path = fullname;
+       (*result)->hive = parent->hive;
        talloc_steal(mem_ctx, (*result)->mem_ctx, fullname);
 
        talloc_destroy(mem_ctx);
@@ -285,6 +305,7 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey)
 
        (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
        (*subkey)->handle = key->handle;
+       (*subkey)->hive = key->hive;
 
 
        return WERR_OK;;
@@ -315,6 +336,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk
 
        (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
        (*subkey)->handle = key->handle;
+       (*subkey)->hive = key->hive;
 
        return WERR_OK; 
 }
@@ -427,6 +449,25 @@ WERROR reg_val_del(REG_VAL *val)
        return WERR_OK;
 }
 
+WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name)
+{
+       REG_KEY *hive;
+       WERROR error;
+       int i, hivelength;
+
+       if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
+       else hivelength = strlen(name);
+
+       for(i = 0; W_ERROR_IS_OK(error); i++) {
+               error = reg_get_hive(handle, i, &hive);
+               if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
+                       return reg_key_add_name_recursive(hive, name);
+               }
+       }
+
+       return error;
+}
+
 WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path)
 {
        REG_KEY *cur, *prevcur = parent;
@@ -516,21 +557,26 @@ void reg_free(REG_HANDLE *h)
        h->functions->close_registry(h);
 }
 
-WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key) 
+WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key) 
 {
        WERROR ret;
-       if(h->functions->open_root_key) {
-               ret = h->functions->open_root_key(h, key);
+       
+       if(h->functions->get_hive) {
+               ret = h->functions->get_hive(h, hivenum, key);
        } else if(h->functions->open_key) {
-               ret = h->functions->open_key(h, "\\", key);
+               if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key);
+               else ret = WERR_NO_MORE_ITEMS;
        } else {
-               DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name));
+               DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name));
                ret = WERR_NOT_SUPPORTED;
        }
 
        if(W_ERROR_IS_OK(ret)) {
                (*key)->handle = h;
-               (*key)->path = talloc_strdup((*key)->mem_ctx, "\\");
+               if(!(*key)->path) {
+                       (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name);
+               }
+               (*key)->hive = hivenum;
        }
 
        return ret;
@@ -565,7 +611,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent)
        REG_KEY *root;
        WERROR error;
 
-       error = reg_get_root(key->handle, &root);
+       error = reg_get_hive(key->handle, key->hive, &root);
        if(!W_ERROR_IS_OK(error)) return error;
 
        parent_name = strdup(reg_key_get_path(key));
index 787ec5212772bfb3a25e6b144c1e6446be780fd2..7a92f413ff4c811a4b2fc1e60783263b1db58eda 100644 (file)
@@ -139,6 +139,12 @@ char *reg_val_get_path(REG_VAL *v)
 }
 
 const char *reg_key_get_path(REG_KEY *k)
+{
+       SMB_REG_ASSERT(k);
+       return strchr(k->path, '\\')?strchr(k->path, '\\')+1:k->path;
+}
+
+const char *reg_key_get_path_abs(REG_KEY *k)
 {
        SMB_REG_ASSERT(k);
        return k->path;
@@ -168,6 +174,7 @@ REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data)
        r = talloc(mem_ctx, sizeof(REG_KEY));
        ZERO_STRUCTP(r);
        r->handle = k->handle;
+       r->hive = k->hive;
        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);
index 208bcae1e1bffd3274c66d37b368e75e0aaab5a6..d4e8cccade5e828ea24d07289939c44473c7b813 100644 (file)
@@ -40,6 +40,7 @@ struct reg_key_s {
   int cache_values_count;
   REG_KEY **cache_subkeys; 
   int cache_subkeys_count;
+  int hive;
   TALLOC_CTX *mem_ctx;
   int ref;
 };
@@ -61,10 +62,14 @@ struct reg_val_s {
 typedef void (*key_notification_function) (void);
 typedef void (*value_notification_function) (void);
 
-
 /* 
  * Container for function pointers to enumeration routines
  * for virtual registry view 
+ *
+ * Backends can provide :
+ *  - just one hive (example: nt4, w95)
+ *  - several hives (example: rpc)
+ * 
  */ 
  
 struct registry_ops {
@@ -73,17 +78,23 @@ struct registry_ops {
        WERROR (*sync_key)(REG_KEY *, const char *location);
        WERROR (*close_registry) (REG_HANDLE *);
 
+       /* Implement this one */
+       WERROR (*get_hive) (REG_HANDLE *, int , REG_KEY **);
+
+       /* Or this one */
+       WERROR (*open_key) (REG_HANDLE *, int hive, const char *name, REG_KEY **);
+
        /* Either implement these */
-       WERROR (*open_root_key) (REG_HANDLE *, REG_KEY **);
        WERROR (*num_subkeys) (REG_KEY *, int *count);
        WERROR (*num_values) (REG_KEY *, int *count);
        WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **);
+       /* Can not contain more then one level */
        WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **);
        WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **);
+       /* Can not contain more then one level */
        WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **);
 
        /* Or these */
-       WERROR (*open_key) (REG_HANDLE *, const char *name, REG_KEY **);
        WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***);
        WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***);
 
@@ -111,15 +122,8 @@ struct registry_ops {
        void (*free_val_backend_data) (REG_VAL *);
 };
 
-typedef struct reg_sub_tree_s {
-       char *path;
-       REG_HANDLE *handle;
-       struct reg_sub_tree_s *prev, *next;
-} REG_SUBTREE;
-
 struct reg_handle_s {
        struct registry_ops *functions;
-       REG_SUBTREE *subtrees;
        char *location;
        char *credentials;
        void *backend_data;
index 517324fdd225ee3596db085141157b4d3fa8f1d5..cb61864d0c8f13fd8e1598e626e34a9b6890b3d6 100644 (file)
@@ -38,16 +38,22 @@ static WERROR reg_dir_del_key(REG_KEY *k)
        return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE;
 }
 
-static WERROR reg_dir_open_key(REG_HANDLE *h, const char *name, REG_KEY **subkey)
+static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **subkey)
 {
        DIR *d;
        char *fullpath;
        REG_KEY *ret;
-       TALLOC_CTX *mem_ctx = talloc_init("tmp");
+       TALLOC_CTX *mem_ctx;
+       
+       if(hive != 0) return WERR_NO_MORE_ITEMS;
+       
        if(!name) {
                DEBUG(0, ("NULL pointer passed as directory name!"));
                return WERR_INVALID_PARAM;
        }
+
+       
+       mem_ctx = talloc_init("tmp");
        fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name);
        fullpath = reg_path_win2unix(fullpath);
        
index cb3c284811c9a7ff3c7df213d3545934921f5d47..255389624e04c9800ff0db9f332f498e591dc33e 100644 (file)
@@ -1663,8 +1663,9 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char
        return WERR_OK;
 }
 
-static WERROR nt_get_root_key(REG_HANDLE *h, REG_KEY **key) 
+static WERROR nt_get_root_key(REG_HANDLE *h, int hive, REG_KEY **key) 
 { 
+       if(hive != 0) return WERR_NO_MORE_ITEMS;
        return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key);
 }
 
@@ -1737,7 +1738,7 @@ static struct registry_ops reg_backend_nt4 = {
        .name = "nt4",
        .open_registry = nt_open_registry,
        .close_registry = nt_close_registry,
-       .open_root_key = nt_get_root_key,
+       .get_hive = nt_get_root_key,
        .num_subkeys = nt_num_subkeys,
        .num_values = nt_num_values,
        .get_subkey_by_index = nt_key_by_index,
index 74b25884d6e877c9b8ddd474b480836f09a0d0fc..d863568c17510d6b58d77eb2a8063ec01e100f6c 100644 (file)
@@ -22,9 +22,6 @@
 
 /**
  * This is the RPC backend for the registry library.
- *
- * This backend is a little special. The root key is 'virtual'. All 
- * of its subkeys are the hives available on the remote server.
  */
 
 static void init_winreg_String(struct winreg_String *name, const char *s)
@@ -40,11 +37,11 @@ static void init_winreg_String(struct winreg_String *name, const char *s)
 }
 
 
-#define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \
+#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \
 { \
        struct winreg_Open ## u r; \
        struct winreg_OpenUnknown unknown; \
-       struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
+       NTSTATUS status; \
        \
        unknown.unknown0 = 0x84e0; \
        unknown.unknown1 = 0x0000; \
@@ -52,12 +49,13 @@ static void init_winreg_String(struct winreg_String *name, const char *s)
        r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
        r.out.handle = hnd;\
        \
-       if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\
+       status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \
+       if (NT_STATUS_IS_ERR(status)) {\
                DEBUG(0,("Error executing open\n"));\
-               return NULL;\
+               return ntstatus_to_werror(status);\
        }\
 \
-       return hnd;\
+       return r.out.result;\
 }
 
 openhive(HKLM)
@@ -66,11 +64,6 @@ openhive(HKPD)
 openhive(HKU)
 openhive(HKCR)
 
-struct rpc_data {
-       struct dcerpc_pipe *pipe;
-       struct policy_handle *hives[10];
-};
-
 struct rpc_key_data {
        struct policy_handle pol;
        int num_subkeys;
@@ -81,7 +74,7 @@ struct rpc_key_data {
 
 struct {
        const char *name;
-       struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
+       WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h);
 } known_hives[] = {
 { "HKEY_LOCAL_MACHINE", open_HKLM },
 { "HKEY_CURRENT_USER", open_HKCU },
@@ -95,7 +88,6 @@ static WERROR rpc_query_key(REG_KEY *k);
 
 static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
 {
-       struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
        char *binding = strdup(location);
        NTSTATUS status;
        char *user, *pass;
@@ -106,40 +98,42 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char
        pass = strchr(user, '%');
        *pass = '\0'; pass++;
 
-       ZERO_STRUCTP(mydata);
-       
-       status = dcerpc_pipe_connect(&mydata->pipe, binding, 
+       status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding, 
                     DCERPC_WINREG_UUID,
                     DCERPC_WINREG_VERSION,
                      lp_workgroup(),
                      user, pass);
-
-       h->backend_data = mydata;
        
        return ntstatus_to_werror(status);
 }
 
-static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
+static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k)
 {
-       /* There's not really a 'root' key here */
-       *k = reg_key_new_abs("\\", h, h->backend_data);
-       return WERR_OK;
+       struct rpc_key_data *mykeydata;
+       WERROR error;
+       if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
+       *k = reg_key_new_abs(known_hives[n].name, h, NULL);
+       (*k)->backend_data = mykeydata = talloc_p((*k)->mem_ctx, struct rpc_key_data);
+       mykeydata->num_values = -1;
+       mykeydata->num_subkeys = -1;
+       error = known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &mykeydata->pol);
+       return error;
 }
 
 static WERROR rpc_close_registry(REG_HANDLE *h)
 {
-       dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
+       dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data);
        return WERR_OK;
 }
 
 static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
 {
-       struct policy_handle *hive = NULL;
     struct winreg_OpenKey r;
        int i;
        struct rpc_data *mydata = k->handle->backend_data;
+       WERROR error;
+       REG_KEY *hivekey;
        struct rpc_key_data *mykeydata;
-       char *realkeyname, *hivename;
 
        if(k->backend_data) { 
                *data = k->backend_data; 
@@ -151,57 +145,55 @@ static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
        mykeydata->num_values = -1;
        mykeydata->num_subkeys = -1;
 
-       /* First, ensure the handle to the hive is opened */
-       realkeyname = strchr(k->path+1, '\\');
-       if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1);
-       else hivename = strdup(k->path+1);
-
-       for(i = 0; known_hives[i].name; i++) {
-               if(!strcmp(hivename, known_hives[i].name)) {
-               if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, k->handle);
-                       hive = mydata->hives[i];
-                       break;
-               }
-       }
-       
-       if(!hive) {
-               DEBUG(0, ("No such hive: %s\n", hivename));
-               return WERR_FOOBAR;
-       }
-
-       if(realkeyname && realkeyname[0] == '\\')realkeyname++;
-
-       if(!realkeyname || !(*realkeyname)) { 
-               mykeydata->pol = *hive;
-               return WERR_OK;
-       }
-
        /* Then, open the handle using the hive */
 
        memset(&r, 0, sizeof(struct winreg_OpenKey));
-    r.in.handle = hive;
-    init_winreg_String(&r.in.keyname, realkeyname);
+       error = rpc_get_hive(k->handle, k->hive, &hivekey);
+       if(!W_ERROR_IS_OK(error))return error;
+    r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
+    init_winreg_String(&r.in.keyname, reg_key_get_path(k));
     r.in.unknown = 0x00000000;
     r.in.access_mask = 0x02000000;
     r.out.handle = &mykeydata->pol;
 
-    dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
+    dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
 
        return r.out.result;
 }
 
-static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
+static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key)
 {
        struct rpc_key_data *mykeydata;
+    struct winreg_OpenKey r;
+       REG_KEY *hivekey;
+       WERROR error;
+       
        *key = reg_key_new_abs(name, h, NULL);
-       return rpc_key_put_rpc_data(*key, &mykeydata);
+
+       (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data);
+       mykeydata->num_values = -1;
+       mykeydata->num_subkeys = -1;
+
+       /* Then, open the handle using the hive */
+
+       memset(&r, 0, sizeof(struct winreg_OpenKey));
+       error = rpc_get_hive(h, hive, &hivekey);
+       if(!W_ERROR_IS_OK(error))return error;
+    r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
+    init_winreg_String(&r.in.keyname, name);
+    r.in.unknown = 0x00000000;
+    r.in.access_mask = 0x02000000;
+    r.out.handle = &mykeydata->pol;
+
+    dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r);
+
+       return r.out.result;
 }
 
 static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)  
 {
        struct winreg_EnumValue r;
        struct winreg_Uint8buf vb;
-       struct rpc_data *mydata = parent->handle->backend_data;
        struct winreg_EnumValueName vn;
        NTSTATUS status;
        struct rpc_key_data *mykeydata;
@@ -211,11 +203,6 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
        error = rpc_key_put_rpc_data(parent, &mykeydata);
        if(!W_ERROR_IS_OK(error)) return error;
 
-       /* Root is a special case */
-       if(parent->backend_data == parent->handle->backend_data) {
-               return WERR_NO_MORE_ITEMS;
-       }
-
        if(mykeydata->num_values == -1) {
                error = rpc_query_key(parent);
                if(!W_ERROR_IS_OK(error)) return error;
@@ -244,7 +231,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
        vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
        r.in.value = r.out.value = &vb;
 
-       status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
+       status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
        if(NT_STATUS_IS_ERR(status)) {
                DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
        }
@@ -273,13 +260,6 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
        WERROR error;
        NTSTATUS status;
 
-       /* 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, NULL);
-               return rpc_key_put_rpc_data(*subkey, &mykeydata);
-       }
-
        error = rpc_key_put_rpc_data(parent, &mykeydata);
        if(!W_ERROR_IS_OK(error)) return error;
 
@@ -295,7 +275,7 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
        r.in.enum_index = n;
        r.in.unknown = r.out.unknown = 0x0414;
        r.in.key_name_len = r.out.key_name_len = 0;
-       status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
+       status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
        if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
                *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL);
        }
@@ -306,7 +286,9 @@ 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)
 {
        struct rpc_key_data *mykeydata;
-       WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
+       WERROR error;
+
+       error = rpc_key_put_rpc_data(parent, &mykeydata);
        if(!W_ERROR_IS_OK(error)) return error;
 
        /* FIXME */
@@ -318,16 +300,15 @@ static WERROR rpc_query_key(REG_KEY *k)
     NTSTATUS status;
        WERROR error;
     struct winreg_QueryInfoKey r;
-    struct rpc_data *mydata = k->handle->backend_data;
     struct rpc_key_data *mykeydata;
 
-    init_winreg_String(&r.in.class, NULL);
-
        error = rpc_key_put_rpc_data(k, &mykeydata);
        if(!W_ERROR_IS_OK(error)) return error;
+
+    init_winreg_String(&r.in.class, NULL);
     r.in.handle = &mykeydata->pol;
        
-    status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
+    status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
 
     if (!NT_STATUS_IS_OK(status)) {
         printf("QueryInfoKey failed - %s\n", nt_errstr(status));
@@ -347,22 +328,21 @@ static WERROR rpc_query_key(REG_KEY *k)
 static WERROR rpc_del_key(REG_KEY *k)
 {
        NTSTATUS status;
-       struct rpc_data *mydata = k->handle->backend_data;
-       struct rpc_key_data *mykeydata;
+       struct rpc_key_data *mykeydata = k->backend_data;
        struct winreg_DeleteKey r;
        REG_KEY *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;
-
+       
     r.in.handle = &mykeydata->pol;
     init_winreg_String(&r.in.key, k->name);
  
-    status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
+    status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
 
        return r.out.result;
 }
@@ -373,15 +353,9 @@ static void rpc_close_key(REG_KEY *k)
 }
 
 static WERROR rpc_num_values(REG_KEY *key, int *count) {
-       struct rpc_key_data *mykeydata;
+       struct rpc_key_data *mykeydata = key->backend_data;
        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;
 
@@ -395,20 +369,12 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) {
 }
 
 static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
-       struct rpc_key_data *mykeydata;
+       struct rpc_key_data *mykeydata = key->backend_data;
        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) {
                error = rpc_query_key(key);
                if(!W_ERROR_IS_OK(error)) return error;
@@ -422,7 +388,7 @@ static struct registry_ops reg_backend_rpc = {
        .name = "rpc",
        .open_registry = rpc_open_registry,
        .close_registry = rpc_close_registry,
-       .open_root_key = rpc_open_root,
+       .get_hive = rpc_get_hive,
        .open_key = rpc_open_key,
        .get_subkey_by_index = rpc_get_subkey_by_index,
        .get_value_by_index = rpc_get_value_by_index,
index c5d2e24103a404fa5bfcae1b25b79d89edee1793..b014f4da663037e0883774b88605eaa8bc72483a 100644 (file)
@@ -179,12 +179,14 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr)
        }
 }
 
-static WERROR w95_open_root (REG_HANDLE *h, REG_KEY **key)
+static WERROR w95_open_root (REG_HANDLE *h, int hive, REG_KEY **key)
 {
        CREG *creg = h->backend_data;
+
+       if(hive != 0) return WERR_NO_MORE_ITEMS;
        
        /* First element in rgkn should be root key */
-       *key = reg_key_new_abs("\\", h, LOCN_RGKN(creg, sizeof(RGKN_HDR)));
+       *key = reg_key_new_abs("", h, LOCN_RGKN(creg, sizeof(RGKN_HDR)));
        
        return WERR_OK;
 }
@@ -356,7 +358,7 @@ static struct registry_ops reg_backend_w95 = {
        .name = "w95",
        .open_registry = w95_open_reg,
        .close_registry = w95_close_reg,
-       .open_root_key = w95_open_root,
+       .get_hive = w95_open_root,
        .fetch_values = w95_fetch_values,
        .get_subkey_by_index = w95_get_subkey_by_index,
 };
index 7b06b2266f9629194d5fe91ca1e9e5902f4179f3..e8800c6ee981e15bc2378570d2cf2a5be0172ff3 100644 (file)
@@ -1,6 +1,6 @@
 /* 
    Unix SMB/CIFS implementation.
-   Gtk registry frontend
+   GTK+ registry frontend
    
    Copyright (C) Jelmer Vernooij 2004
 
@@ -115,20 +115,25 @@ static void registry_load_root()
 {
        REG_KEY *root;
        GtkTreeIter iter, tmpiter;
-       WERROR error;
+       WERROR error = WERR_OK;
+       int i = 0;
        if(!registry) return;
 
-       error = reg_get_root(registry, &root);
-       if(!W_ERROR_IS_OK(error)) {
-               gtk_show_werror(error);
-               return;
-       }
-
        gtk_tree_store_clear(store_keys);
 
-       /* Add the root */
-       gtk_tree_store_append(store_keys, &iter, NULL);
-       gtk_tree_store_set (store_keys,
+       while(1) {
+               error = reg_get_hive(registry, i, &root);
+               if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
+                       return;
+               }
+               if(!W_ERROR_IS_OK(error)) {
+                       gtk_show_werror(error);
+                       return;
+               }
+
+               /* Add the root */
+               gtk_tree_store_append(store_keys, &iter, NULL);
+               gtk_tree_store_set (store_keys,
                                            &iter, 
                                                0,
                                                reg_key_name(root),
@@ -136,7 +141,9 @@ static void registry_load_root()
                                                root,
                                                -1);
 
-       gtk_tree_store_append(store_keys, &tmpiter, &iter);
+               gtk_tree_store_append(store_keys, &tmpiter, &iter);
+               i++;
+       }
 
        gtk_widget_set_sensitive( save, True );
        gtk_widget_set_sensitive( save_as, True );
index d9419208cd4f01d834ef2f5c44c736f3f835c872..7520e653bb6515c45631a0d3ed9a5368010b4dae 100644 (file)
@@ -100,10 +100,11 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
        const char *credentials1= NULL, *credentials2 = NULL;
        char *outputfile = NULL;
        FILE *fd = stdout;
-       REG_HANDLE *h2;
+       REG_HANDLE *h1, *h2;
        REG_KEY *root1 = NULL, *root2;
        int from_null = 0;
-       WERROR error;
+       int i;
+       WERROR error, error2;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
                {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL},
@@ -130,7 +131,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
        setup_logging(argv[0], True);
 
        if(!from_null) {
-               REG_HANDLE *h1;
                const char *location1;
                location1 = poptGetArg(pc);
                if(!location1) {
@@ -145,8 +145,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
                        fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1);
                        return 1;
                }
-
-               if(!W_ERROR_IS_OK(reg_get_root(h1, &root1))) return 1;
        }
 
        location2 = poptGetArg(pc);
@@ -163,12 +161,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
                return 1;
        }
        
-       error = reg_get_root(h2, &root2);
-       if(!W_ERROR_IS_OK(error)) {
-               fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2);
-               return 1;
-       }
-
        poptFreeContext(pc);
 
        if(outputfile) {
@@ -182,7 +174,23 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
        fprintf(fd, "REGEDIT4\n\n");
        fprintf(fd, "; Generated using regdiff\n");
 
-       writediff(root1, root2, fd); 
+       error2 = error = WERR_OK; 
+       
+       for(i = 0; ; i++) {
+               if(backend1) error = reg_get_hive(h1, i, &root1);
+               else root1 = NULL;
+
+               if(!W_ERROR_IS_OK(error)) break;
+       
+               if(backend2) error2 = reg_get_hive(h2, i, &root2);
+               else root2 = NULL;
+               
+               if(!W_ERROR_IS_OK(error2)) break;
+       
+               writediff(root1, root2, fd); 
+
+               if(!root1 && !root2) break;
+       }
 
        fclose(fd);
        
index 64c2637a0cea4970f56693dea98bf40f6070aa8b..77c0f710c1c8428835f0ee198eeb59b323d70363 100644 (file)
@@ -664,7 +664,7 @@ static CMD_FILE *cmd_file_create(const char *file)
 
 char *str_type(unsigned char type);
 
-static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
+static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name)
 {
        CMD *cmd;
        BOOL modified = False;
@@ -680,12 +680,12 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
                 */
                switch (cmd->cmd) {
                case CMD_ADD_KEY: 
-                 error = reg_open_key(root, cmd->key, &tmp);
+                 error = reg_open_key_abs(r, cmd->key, &tmp);
 
                  /* If we found it, apply the other bits, else create such a key */
                  if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
-                         if(W_ERROR_IS_OK(reg_key_add_name_recursive(root, cmd->key))) {
-                                 error = reg_open_key(root, cmd->key, &tmp);
+                         if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) {
+                                 error = reg_open_key_abs(r, cmd->key, &tmp);
                                  if(!W_ERROR_IS_OK(error)) {
                                        DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key));
                                        continue;
@@ -732,7 +732,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
                   * Find the key if it exists, and delete it ...
                   */
 
-                 error = reg_open_key(root, cmd->key, &tmp);
+                 error = reg_open_key_abs(r, cmd->key, &tmp);
                  if(!W_ERROR_IS_OK(error)) {
                          DEBUG(0, ("Unable to open key '%s'\n", cmd->key));
                          continue;
@@ -756,7 +756,6 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
 {
        int opt;
        poptContext pc;
-       REG_KEY *root;
        const char *location;
        const char *credentials = NULL;
        const char *patch;
@@ -793,13 +792,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
        if(!patch) patch = "/dev/stdin";
        poptFreeContext(pc);
 
-       error = reg_get_root(h, &root);
-       if(!W_ERROR_IS_OK(error)) {
-               DEBUG(0, ("Error opening root!\n"));
-               return 1;
-       }
-
-       nt_apply_reg_command_file(root, patch);
+       nt_apply_reg_command_file(h, patch);
 
        reg_free(h);
 
index e8b01081e8117469af38390d5ab3707e927d3bce..26312ad4bc74304c456b49832caa7b81d01a1a26 100644 (file)
@@ -27,6 +27,7 @@
  * rmval/rm - remove value
  * rmkey/rmdir - remove key
  * mkkey/mkdir - make key
+ * ch - change hive
  * help
  * exit
  */
@@ -227,7 +228,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
 
     setup_logging("regtree", True);
 
-       error = reg_get_root(h, &curkey);
+       error = reg_get_hive(h, 0, &curkey);
 
        if(!W_ERROR_IS_OK(error)) return 1;
 
index 477c63af2c1011eab8fcb2447243726309174119..e583194a56108ba0e8735acc0ad0d7fbee524042 100644 (file)
@@ -60,7 +60,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals)
 
  int main(int argc, char **argv)
 {
-       int opt;
+       int opt, i;
        const char *backend = "dir";
        const char *credentials = NULL;
        poptContext pc;
@@ -91,10 +91,14 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals)
        }
        poptFreeContext(pc);
 
-       error = reg_get_root(h, &root);
-       if(!W_ERROR_IS_OK(error)) return 1;
+       error = WERR_OK;
 
-       print_tree(0, root, fullpath, no_values);
+       for(i = 0; W_ERROR_IS_OK(error); i++) {
+               error = reg_get_hive(h, i, &root);
+               if(!W_ERROR_IS_OK(error)) return 1;
+
+               print_tree(0, root, fullpath, no_values);
+       }
        
        return 0;
 }