regedit: make all hives descend from a root node
authorChris Davis <cd.rattan@gmail.com>
Tue, 1 Jul 2014 06:19:53 +0000 (23:19 -0700)
committerMichael Adam <obnox@samba.org>
Wed, 1 Oct 2014 12:32:09 +0000 (14:32 +0200)
This helps simplify cleanup, since each node's talloc context is the
parent node, and freeing the root node will destroy the entire tree
without any extra utility functions.

It also wouldn't be hard to extend this later on to support browsing
multiple registries at the same time.

Signed-off-by: Chris Davis <cd.rattan@gmail.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source3/utils/regedit.c
source3/utils/regedit_treeview.c
source3/utils/regedit_treeview.h

index c0dbf9069ea90678020c56079442ba87660c6f2c..8fca96bd18d4ce7aa113240e9335be431cf2212c 100644 (file)
@@ -86,53 +86,6 @@ static void print_path(struct regedit *regedit, struct tree_node *node)
        show_path(regedit);
 }
 
-/* load all available hives */
-static struct tree_node *load_hives(struct regedit *regedit)
-{
-       const char *hives[] = {
-               "HKEY_CLASSES_ROOT",
-               "HKEY_CURRENT_USER",
-               "HKEY_LOCAL_MACHINE",
-               "HKEY_PERFORMANCE_DATA",
-               "HKEY_USERS",
-               "HKEY_CURRENT_CONFIG",
-               "HKEY_DYN_DATA",
-               "HKEY_PERFORMANCE_TEXT",
-               "HKEY_PERFORMANCE_NLSTEXT",
-               NULL
-       };
-       struct tree_node *root, *prev, *node;
-       struct registry_key *key;
-       WERROR rv;
-       size_t i;
-
-       root = NULL;
-       prev = NULL;
-
-       for (i = 0; hives[i] != NULL; ++i) {
-               rv = reg_get_predefined_key_by_name(regedit->registry_context,
-                                                   hives[i], &key);
-               if (!W_ERROR_IS_OK(rv)) {
-                       continue;
-               }
-
-               node = tree_node_new(regedit, NULL, hives[i], key);
-               if (node == NULL) {
-                       return NULL;
-               }
-
-               if (root == NULL) {
-                       root = node;
-               }
-               if (prev) {
-                       tree_node_append(prev, node);
-               }
-               prev = node;
-       }
-
-       return root;
-}
-
 static void print_help(struct regedit *regedit)
 {
        const char *khelp = "[n] New Key [s] New Subkey [d] Del Key "
@@ -196,7 +149,7 @@ static void add_reg_key(struct regedit *regedit, struct tree_node *node,
        const char *name;
        const char *msg;
 
-       if (!subkey && !node->parent) {
+       if (!subkey && tree_node_is_top_level(node)) {
                return;
        }
 
@@ -387,7 +340,7 @@ static void handle_tree_input(struct regedit *regedit, int c)
                break;
        case KEY_LEFT:
                node = tree_view_get_current_node(regedit->keys);
-               if (node && node->parent) {
+               if (node && !tree_node_is_top_level(node)) {
                        print_path(regedit, node->parent);
                        node = node->parent;
                        tree_view_update(regedit->keys, tree_node_first(node));
@@ -410,7 +363,7 @@ static void handle_tree_input(struct regedit *regedit, int c)
                int sel;
 
                node = tree_view_get_current_node(regedit->keys);
-               if (!node->parent) {
+               if (tree_node_is_top_level(node)) {
                        break;
                }
                sel = dialog_notice(regedit, DIA_CONFIRM,
@@ -537,8 +490,11 @@ static void handle_main_input(struct regedit *regedit, int c)
 
                node = tree_view_get_current_node(regedit->keys);
                path = tree_node_get_path(regedit, node);
+               SMB_ASSERT(path != NULL);
+
+               root = tree_node_new_root(regedit, regedit->registry_context);
+               SMB_ASSERT(root != NULL);
 
-               root = load_hives(regedit);
                tree_view_set_root(regedit->keys, root);
                tree_view_set_path(regedit->keys, path);
                node = tree_view_get_current_node(regedit->keys);
@@ -647,7 +603,7 @@ static void display_window(TALLOC_CTX *mem_ctx, struct registry_context *ctx)
        wprintw(regedit->path_label, "/");
        show_path(regedit_main);
 
-       root = load_hives(regedit);
+       root = tree_node_new_root(regedit, ctx);
        SMB_ASSERT(root != NULL);
 
        regedit->keys = tree_view_new(regedit, root, KEY_HEIGHT, KEY_WIDTH,
index 2f44613e8df9ba3e17738080f0400d123b50df86..dd4b5cb08cbedad750eba84e863ea03d029709f7 100644 (file)
 
 #define HEADING_X 3
 
+static int tree_node_free(struct tree_node *node)
+{
+       DEBUG(9, ("tree_node_free('%s', %p)\n", node->name, node));
+       return 0;
+}
+
 struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
                                const char *name, struct registry_key *key)
 {
@@ -32,6 +38,8 @@ struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
        if (!node) {
                return NULL;
        }
+       talloc_set_destructor(node, tree_node_free);
+       DEBUG(9, ("tree_node_new('%s', %p)\n", name, node));
 
        node->name = talloc_strdup(node, name);
        if (!node->name) {
@@ -39,7 +47,9 @@ struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
                return NULL;
        }
 
-       node->key = talloc_steal(node, key);
+       if (key) {
+               node->key = talloc_steal(node, key);
+       }
 
        if (parent) {
                /* Check if this node is the first descendant of parent. */
@@ -52,6 +62,52 @@ struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
        return node;
 }
 
+/* prepare a root node with all available hives as children */
+struct tree_node *tree_node_new_root(TALLOC_CTX *ctx,
+                                    struct registry_context *regctx)
+{
+       const char *hives[] = {
+               "HKEY_CLASSES_ROOT",
+               "HKEY_CURRENT_USER",
+               "HKEY_LOCAL_MACHINE",
+               "HKEY_PERFORMANCE_DATA",
+               "HKEY_USERS",
+               "HKEY_CURRENT_CONFIG",
+               "HKEY_DYN_DATA",
+               "HKEY_PERFORMANCE_TEXT",
+               "HKEY_PERFORMANCE_NLSTEXT",
+               NULL
+       };
+       struct tree_node *root, *prev, *node;
+       struct registry_key *key;
+       WERROR rv;
+       size_t i;
+
+       root = tree_node_new(ctx, NULL, "ROOT", NULL);
+       if (root == NULL) {
+               return NULL;
+       }
+       prev = NULL;
+
+       for (i = 0; hives[i] != NULL; ++i) {
+               rv = reg_get_predefined_key_by_name(regctx, hives[i], &key);
+               if (!W_ERROR_IS_OK(rv)) {
+                       continue;
+               }
+
+               node = tree_node_new(root, root, hives[i], key);
+               if (node == NULL) {
+                       return NULL;
+               }
+               if (prev) {
+                       tree_node_append(prev, node);
+               }
+               prev = node;
+       }
+
+       return root;
+}
+
 void tree_node_append(struct tree_node *left, struct tree_node *right)
 {
        if (left->next) {
@@ -250,23 +306,6 @@ finish:
        return rv;
 }
 
-void tree_node_free_recursive(struct tree_node *list)
-{
-       struct tree_node *node;
-
-       if (list == NULL) {
-               return;
-       }
-
-       while ((node = tree_node_pop(&list)) != NULL) {
-               if (node->child_head) {
-                       tree_node_free_recursive(node->child_head);
-               }
-               node->child_head = NULL;
-               talloc_free(node);
-       }
-}
-
 void tree_view_clear(struct tree_view *view)
 {
        multilist_set_data(view->list, NULL);
@@ -277,7 +316,7 @@ WERROR tree_view_set_root(struct tree_view *view, struct tree_node *root)
        multilist_set_data(view->list, NULL);
        talloc_free(view->root);
        view->root = root;
-       return tree_view_update(view, root);
+       return tree_view_update(view, root->child_head);
 }
 
 WERROR tree_view_set_path(struct tree_view *view, const char **path)
@@ -285,7 +324,7 @@ WERROR tree_view_set_path(struct tree_view *view, const char **path)
        struct tree_node *top, *node;
        WERROR rv;
 
-       top = view->root;
+       top = view->root->child_head;
        while (*path) {
                for (node = top; node != NULL; node = node->next) {
                        if (strcmp(*path, node->name) == 0) {
@@ -377,7 +416,6 @@ static int tree_view_free(struct tree_view *view)
        if (view->window) {
                delwin(view->window);
        }
-       tree_node_free_recursive(view->root);
 
        return 0;
 }
@@ -479,7 +517,7 @@ struct tree_view *tree_view_new(TALLOC_CTX *ctx, struct tree_node *root,
        if (view->list == NULL) {
                goto fail;
        }
-       tree_view_update(view, root);
+       tree_view_update(view, root->child_head);
 
        return view;
 
@@ -520,7 +558,7 @@ const char **tree_node_get_path(TALLOC_CTX *ctx, struct tree_node *node)
        size_t nitems, index;
        struct tree_node *p;
 
-       for (nitems = 0, p = node; p != NULL; p = p->parent) {
+       for (nitems = 0, p = node; !tree_node_is_root(p); p = p->parent) {
                ++nitems;
        }
 
@@ -529,7 +567,9 @@ const char **tree_node_get_path(TALLOC_CTX *ctx, struct tree_node *node)
                return NULL;
        }
 
-       for (index = nitems - 1, p = node; p != NULL; p = p->parent, --index) {
+       for (index = nitems - 1, p = node;
+            !tree_node_is_root(p);
+            p = p->parent, --index) {
                array[index] = talloc_strdup(array, p->name);
                if (array[index] == NULL) {
                        talloc_free(discard_const(array));
@@ -553,7 +593,7 @@ size_t tree_node_print_path(WINDOW *label, struct tree_node *node)
        werase(label);
        wprintw(label, "/");
 
-       if (node->parent == NULL)
+       if (tree_node_is_top_level(node))
                return 0;
 
        frame = talloc_stackframe();
index 29c5fe2e6552b4f0183e2738e68c4ca48d7823a9..4d1851ab1d8e595cfd66d3498dfeb0878994c482 100644 (file)
@@ -48,8 +48,14 @@ struct tree_view {
        struct multilist *list;
 };
 
+struct registry_context;
+
 struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
                                const char *name, struct registry_key *key);
+struct tree_node *tree_node_new_root(TALLOC_CTX *ctx,
+                                    struct registry_context *regctx);
+#define tree_node_is_root(node) ((node)->key == NULL)
+#define tree_node_is_top_level(node) tree_node_is_root((node)->parent)
 void tree_node_append(struct tree_node *left, struct tree_node *right);
 struct tree_node *tree_node_pop(struct tree_node **plist);
 struct tree_node *tree_node_first(struct tree_node *list);