Example #1
0
void value_list_resize(struct value_list *vl, int nlines, int ncols,
		       int begin_y, int begin_x)
{
	WINDOW *nwin, *nsub;

	nwin = newwin(nlines, ncols, begin_y, begin_x);
	if (nwin == NULL) {
		return;
	}
	nsub = subwin(nwin, nlines - 2, ncols - 2, begin_y + 1, begin_x + 1);
	if (nsub == NULL) {
		delwin(nwin);
		return;
	}
	replace_panel(vl->panel, nwin);
	delwin(vl->sub);
	delwin(vl->window);
	vl->window = nwin;
	vl->sub = nsub;
	box(vl->window, 0, 0);
	mvwprintw(vl->window, 0, HEADING_X, "Value");
	multilist_set_window(vl->list, vl->sub);
	value_list_show(vl);
}
Example #2
0
static void handle_value_input(struct regedit *regedit, int c)
{
	struct value_item *vitem;
	bool binmode = false;

	switch (c) {
	case KEY_DOWN:
		menu_driver(regedit->vl->menu, REQ_DOWN_ITEM);
		break;
	case KEY_UP:
		menu_driver(regedit->vl->menu, REQ_UP_ITEM);
		break;
	case 'b':
	case 'B':
		binmode = true;
		/* Falthrough... */
	case '\n':
	case KEY_ENTER:
		vitem = item_userptr(current_item(regedit->vl->menu));
		if (vitem) {
			struct tree_node *node;
			node = item_userptr(current_item(regedit->keys->menu));
			dialog_edit_value(regedit, node->key, vitem->type,
					  vitem, binmode);
			value_list_load(regedit->vl, node->key);
		}
		break;
	case 'n':
	case 'N': {
		int new_type;
		int sel;

		sel = dialog_select_type(regedit, &new_type);
		if (sel == DIALOG_OK) {
			struct tree_node *node;
			node = item_userptr(current_item(regedit->keys->menu));
			dialog_edit_value(regedit, node->key, new_type, NULL,
					  false);
			value_list_load(regedit->vl, node->key);
		}
		break;
	}
	case 'd':
	case 'D':
		vitem = item_userptr(current_item(regedit->vl->menu));
		if (vitem) {
			int sel;

			sel = dialog_notice(regedit, DIA_CONFIRM,
					    "Delete Value",
					     "Really delete value \"%s\"?",
					     vitem->value_name);
			if (sel == DIALOG_OK) {
				ITEM *it = current_item(regedit->keys->menu);
				struct tree_node *node = item_userptr(it);
				reg_del_value(regedit, node->key,
					      vitem->value_name);
				value_list_load(regedit->vl, node->key);
			}
		}
		break;
	}

	value_list_show(regedit->vl);
}
Example #3
0
static void display_window(TALLOC_CTX *mem_ctx, struct registry_context *ctx)
{
	struct regedit *regedit;
	struct tree_node *root;
	bool colors;
	int key;

	initscr();

	cbreak();
	noecho();

	colors = has_colors();
	if (colors) {
		start_color();
		use_default_colors();
	}

	regedit = talloc_zero(mem_ctx, struct regedit);
	SMB_ASSERT(regedit != NULL);
	regedit_main = regedit;

	regedit->main_window = stdscr;
	keypad(regedit->main_window, TRUE);

	mvwprintw(regedit->main_window, 0, 0, "Path: ");
	regedit->path_label = newpad(1, PATH_WIDTH_MAX);
	SMB_ASSERT(regedit->path_label);
	wprintw(regedit->path_label, "/");
	show_path(regedit_main);

	root = load_hives(regedit, ctx);
	SMB_ASSERT(root != NULL);

	regedit->keys = tree_view_new(regedit, root, KEY_HEIGHT, KEY_WIDTH,
				      KEY_START_Y, KEY_START_X);
	SMB_ASSERT(regedit->keys != NULL);

	regedit->vl = value_list_new(regedit, VAL_HEIGHT, VAL_WIDTH,
				     VAL_START_Y, VAL_START_X);
	SMB_ASSERT(regedit->vl != NULL);

	regedit->tree_input = true;
	print_heading(regedit);

	tree_view_show(regedit->keys);
	menu_driver(regedit->keys->menu, REQ_FIRST_ITEM);
	load_values(regedit);
	value_list_show(regedit->vl);

	update_panels();
	doupdate();

	do {
		key = regedit_getch();

		handle_main_input(regedit, key);
		update_panels();
		doupdate();
	} while (key != 'q' || key == 'Q');

	endwin();
}
Example #4
0
static void handle_tree_input(struct regedit *regedit, int c)
{
	struct tree_node *node;

	switch (c) {
	case KEY_DOWN:
		menu_driver(regedit->keys->menu, REQ_DOWN_ITEM);
		load_values(regedit);
		break;
	case KEY_UP:
		menu_driver(regedit->keys->menu, REQ_UP_ITEM);
		load_values(regedit);
		break;
	case '\n':
	case KEY_ENTER:
	case KEY_RIGHT:
		node = item_userptr(current_item(regedit->keys->menu));
		if (node && tree_node_has_children(node)) {
			tree_node_load_children(node);
			print_path(regedit, node->child_head);
			tree_view_update(regedit->keys, node->child_head);
			value_list_load(regedit->vl, node->child_head->key);
		}
		break;
	case KEY_LEFT:
		node = item_userptr(current_item(regedit->keys->menu));
		if (node && node->parent) {
			print_path(regedit, node->parent);
			node = tree_node_first(node->parent);
			tree_view_update(regedit->keys, node);
			value_list_load(regedit->vl, node->key);
		}
		break;
	case 'n':
	case 'N':
		node = item_userptr(current_item(regedit->keys->menu));
		add_reg_key(regedit, node, false);
		break;
	case 's':
	case 'S':
		node = item_userptr(current_item(regedit->keys->menu));
		add_reg_key(regedit, node, true);
		break;
	case 'd':
	case 'D': {
		int sel;

		node = item_userptr(current_item(regedit->keys->menu));
		if (!node->parent) {
			break;
		}
		sel = dialog_notice(regedit, DIA_CONFIRM,
				    "Delete Key",
				     "Really delete key \"%s\"?",
				     node->name);
		if (sel == DIALOG_OK) {
			WERROR rv;
			struct tree_node *pop;
			struct tree_node *parent = node->parent;

			rv = reg_key_del(node, parent->key, node->name);
			if (W_ERROR_IS_OK(rv)) {
				tree_view_clear(regedit->keys);
				pop = tree_node_pop(&node);
				tree_node_free_recursive(pop);
				node = parent->child_head;
				if (node == NULL) {
					node = tree_node_first(parent);
					print_path(regedit, node);
				}
				tree_view_update(regedit->keys, node);
				value_list_load(regedit->vl, node->key);
			} else {
				dialog_notice(regedit, DIA_ALERT, "Delete Key",
					      "Failed to delete key.");
			}
		}
		break;
	}
	}

	tree_view_show(regedit->keys);
	value_list_show(regedit->vl);
}
static void handle_main_input(struct regedit *regedit, int c)
{
	switch (c) {
	case 18: { /* CTRL-R */
		struct tree_node *root, *node;
		const char **path;

		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);

		tree_view_set_root(regedit->keys, root);
		tree_view_set_path(regedit->keys, path);
		node = tree_view_get_current_node(regedit->keys);
		value_list_load(regedit->vl, node->key);
		tree_view_show(regedit->keys);
		value_list_show(regedit->vl);
		print_path(regedit, node);
		talloc_free(discard_const(path));
		break;
	}
	case 'f':
	case 'F':
	case '/': {
		int rv;
		struct regedit_search_opts *opts;
		struct tree_node *node;

		opts = &regedit->active_search;
		rv = dialog_search_input(regedit, opts);
		if (rv == DIALOG_OK) {
			SMB_ASSERT(opts->query != NULL);
			opts->match = find_substring_nocase;
			node = regedit->keys->root->child_head;
			if (opts->search_case) {
				opts->match = find_substring;
			}
			if (!opts->search_recursive) {
				node = tree_view_get_current_node(regedit->keys);
				node = tree_node_first(node);
			}
			regedit_search(regedit, node, NULL, SEARCH_NEXT);
		}
		break;
	}
	case 'x':
		regedit_search_repeat(regedit, SEARCH_NEXT);
		break;
	case 'X':
		regedit_search_repeat(regedit, SEARCH_PREV);
		break;
	case '\t':
		regedit->tree_input = !regedit->tree_input;
		print_heading(regedit);
		break;
	default:
		if (regedit->tree_input) {
			handle_tree_input(regedit, c);
		} else {
			handle_value_input(regedit, c);
		}
	}
}
static void handle_value_input(struct regedit *regedit, int c)
{
	struct value_item *vitem;
	bool binmode = false;
	WERROR err;
	int sel;

	switch (c) {
	case KEY_DOWN:
		value_list_driver(regedit->vl, ML_CURSOR_DOWN);
		break;
	case KEY_UP:
		value_list_driver(regedit->vl, ML_CURSOR_UP);
		break;
	case KEY_NPAGE:
		value_list_driver(regedit->vl, ML_CURSOR_PGDN);
		break;
	case KEY_PPAGE:
		value_list_driver(regedit->vl, ML_CURSOR_PGUP);
		break;
	case KEY_HOME:
		value_list_driver(regedit->vl, ML_CURSOR_HOME);
		break;
	case KEY_END:
		value_list_driver(regedit->vl, ML_CURSOR_END);
		break;
	case 'b':
	case 'B':
		binmode = true;
		/* Falthrough... */
	case '\n':
	case KEY_ENTER:
		vitem = value_list_get_current_item(regedit->vl);
		if (vitem) {
			struct tree_node *node;
			const char *name = NULL;
			node = tree_view_get_current_node(regedit->keys);
			sel = dialog_edit_value(regedit, node->key, vitem->type,
					        vitem, binmode, &err, &name);
			if (!W_ERROR_IS_OK(err)) {
				const char *msg = get_friendly_werror_msg(err);
				dialog_notice(regedit, DIA_ALERT, "Error",
					      "Error editing value:\n%s", msg);
			} else if (sel == DIALOG_OK) {
				tree_node_reopen_key(regedit->registry_context,
						     node);
				value_list_load(regedit->vl, node->key);
				value_list_set_current_item_by_name(regedit->vl,
								    name);
				talloc_free(discard_const(name));
			}
		}
		break;
	case 'n':
	case 'N': {
		int new_type;

		sel = dialog_select_type(regedit, &new_type);
		if (sel == DIALOG_OK) {
			struct tree_node *node;
			const char *name = NULL;
			node = tree_view_get_current_node(regedit->keys);
			sel = dialog_edit_value(regedit, node->key, new_type,
						NULL, false, &err, &name);
			if (!W_ERROR_IS_OK(err)) {
				const char *msg = get_friendly_werror_msg(err);
				dialog_notice(regedit, DIA_ALERT, "Error",
					      "Error creating value:\n%s", msg);
			} else if (sel == DIALOG_OK) {
				tree_node_reopen_key(regedit->registry_context,
						     node);
				value_list_load(regedit->vl, node->key);
				value_list_set_current_item_by_name(regedit->vl,
								    name);
				talloc_free(discard_const(name));
			}
		}
		break;
	}
	case 'd':
	case 'D':
		vitem = value_list_get_current_item(regedit->vl);
		if (vitem) {
			sel = dialog_notice(regedit, DIA_CONFIRM,
					    "Delete Value",
					     "Really delete value \"%s\"?",
					     vitem->value_name);
			if (sel == DIALOG_OK) {
				struct tree_node *node;
				node = tree_view_get_current_node(regedit->keys);
				reg_del_value(regedit, node->key,
					      vitem->value_name);
				tree_node_reopen_key(regedit->registry_context,
						     node);
				value_list_load(regedit->vl, node->key);
			}
		}
		break;
	}

	value_list_show(regedit->vl);
}
static void handle_tree_input(struct regedit *regedit, int c)
{
	struct tree_node *node;

	switch (c) {
	case KEY_DOWN:
		tree_view_driver(regedit->keys, ML_CURSOR_DOWN);
		load_values(regedit);
		break;
	case KEY_UP:
		tree_view_driver(regedit->keys, ML_CURSOR_UP);
		load_values(regedit);
		break;
	case KEY_NPAGE:
		tree_view_driver(regedit->keys, ML_CURSOR_PGDN);
		load_values(regedit);
		break;
	case KEY_PPAGE:
		tree_view_driver(regedit->keys, ML_CURSOR_PGUP);
		load_values(regedit);
		break;
	case KEY_HOME:
		tree_view_driver(regedit->keys, ML_CURSOR_HOME);
		load_values(regedit);
		break;
	case KEY_END:
		tree_view_driver(regedit->keys, ML_CURSOR_END);
		load_values(regedit);
		break;
	case '\n':
	case KEY_ENTER:
	case KEY_RIGHT:
		node = tree_view_get_current_node(regedit->keys);
		if (node && tree_node_has_children(node)) {
			WERROR rv;

			rv = tree_node_load_children(node);
			if (W_ERROR_IS_OK(rv)) {
				print_path(regedit, node->child_head);
				tree_view_update(regedit->keys, node->child_head);
				value_list_load(regedit->vl, node->child_head->key);
			} else {
				const char *msg = get_friendly_werror_msg(rv);
				dialog_notice(regedit, DIA_ALERT, "Loading Subkeys",
					      "Failed to load subkeys: %s", msg);
			}
		}
		break;
	case KEY_LEFT:
		node = tree_view_get_current_node(regedit->keys);
		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));
			tree_view_set_current_node(regedit->keys, node);
			value_list_load(regedit->vl, node->key);
		}
		break;
	case 'n':
	case 'N':
		node = tree_view_get_current_node(regedit->keys);
		add_reg_key(regedit, node, false);
		break;
	case 's':
	case 'S':
		node = tree_view_get_current_node(regedit->keys);
		add_reg_key(regedit, node, true);
		break;
	case 'd':
	case 'D': {
		int sel;

		node = tree_view_get_current_node(regedit->keys);
		if (tree_node_is_top_level(node)) {
			break;
		}
		sel = dialog_notice(regedit, DIA_CONFIRM,
				    "Delete Key",
				     "Really delete key \"%s\"?",
				     node->name);
		if (sel == DIALOG_OK) {
			WERROR rv;
			struct tree_node *pop;
			struct tree_node *parent = node->parent;

			rv = reg_key_del(node, parent->key, node->name);
			if (W_ERROR_IS_OK(rv)) {
				tree_node_reopen_key(regedit->registry_context,
						     parent);
				tree_view_clear(regedit->keys);
				pop = tree_node_pop(&node);
				talloc_free(pop);
				node = parent->child_head;
				if (node == NULL) {
					node = tree_node_first(parent);
					print_path(regedit, node);
				}
				tree_view_update(regedit->keys, node);
				value_list_load(regedit->vl, node->key);
			} else {
				const char *msg = get_friendly_werror_msg(rv);
				dialog_notice(regedit, DIA_ALERT, "Delete Key",
					      "Failed to delete key: %s", msg);
			}
		}
		break;
	}
	}

	tree_view_show(regedit->keys);
	value_list_show(regedit->vl);
}
static WERROR regedit_search(struct regedit *regedit, struct tree_node *node,
			     struct value_item *vitem, unsigned flags)
{
	struct regedit_search_opts *opts;
	struct tree_node *found;
	struct value_item *found_value;
	bool search_key, need_sync;
	char *save_value_name;
	WERROR rv;
	bool (*iterate)(struct tree_node **, bool, WERROR *);
	struct value_item *(*find_item)(struct value_list *,
				        struct value_item *,
				        const char *,
				        regedit_search_match_fn_t);

	opts = &regedit->active_search;

	if (!opts->query || !opts->match) {
		return WERR_OK;
	}

	SMB_ASSERT(opts->search_key || opts->search_value);

	rv = WERR_OK;
	found = NULL;
	found_value = NULL;
	save_value_name = NULL;
	search_key = opts->search_key;
	need_sync = false;
	iterate = tree_node_next;
	find_item = value_list_find_next_item;

	if (flags & SEARCH_PREV) {
		iterate = tree_node_prev;
		find_item = value_list_find_prev_item;
	}

	if (opts->search_value) {
		struct value_item *it;

		it = value_list_get_current_item(regedit->vl);
		if (it) {
			save_value_name = talloc_strdup(regedit,
							it->value_name);
			if (save_value_name == NULL) {
				return WERR_NOMEM;
			}
		}

		if (vitem) {
			search_key = false;
		}
	}

	if (!vitem && (flags & SEARCH_REPEAT)) {
		if (opts->search_value) {
			search_key = false;
		} else if (!iterate(&node, opts->search_recursive, &rv)) {
			beep();
			return rv;
		}
	}

	do {
		if (search_key) {
			SMB_ASSERT(opts->search_key == true);
			if (opts->match(node->name, opts->query)) {
				found = node;
			} else if (opts->search_value) {
				search_key = false;
			}
		}
		if (!search_key) {
			SMB_ASSERT(opts->search_value == true);
			if (!vitem) {
				rv = value_list_load_quick(regedit->vl,
							   node->key);
				if (!W_ERROR_IS_OK(rv)) {
					goto out;
				}
				need_sync = true;
			}
			found_value = find_item(regedit->vl, vitem, opts->query,
						opts->match);
			if (found_value) {
				found = node;
			} else {
				vitem = NULL;
				search_key = opts->search_key;
			}
		}
	} while (!found && iterate(&node, opts->search_recursive, &rv));

	if (!W_ERROR_IS_OK(rv)) {
		goto out;
	}

	if (found) {
		/* Put the cursor on the node that was found */
		if (!tree_view_is_node_visible(regedit->keys, found)) {
			tree_view_update(regedit->keys,
					 tree_node_first(found));
			print_path(regedit, found);
		}
		tree_view_set_current_node(regedit->keys, found);
		if (found_value) {
			if (need_sync) {
				value_list_sync(regedit->vl);
			}
			value_list_set_current_item(regedit->vl, found_value);
			regedit->tree_input = false;
		} else {
			load_values(regedit);
			regedit->tree_input = true;
		}
		tree_view_show(regedit->keys);
		value_list_show(regedit->vl);
		print_heading(regedit);
	} else {
		if (need_sync) {
			load_values(regedit);
			value_list_set_current_item_by_name(regedit->vl,
							    save_value_name);
		}
		beep();
	}

out:
	talloc_free(save_value_name);

	return rv;
}