regedit: Print value summary, fix heap corruption and path printing.
[Samba.git] / source3 / utils / regedit_valuelist.c
blob4fc0ae8fd77a839908e35d70fdc54dde70a709da
1 /*
2 * Samba Unix/Linux SMB client library
3 * Registry Editor
4 * Copyright (C) Christopher Davis 2012
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "regedit_valuelist.h"
21 #include "lib/registry/registry.h"
23 static void value_list_free_items(ITEM **items)
25 size_t i;
26 ITEM *item;
27 struct value_item *vitem;
29 if (items == NULL) {
30 return;
33 for (i = 0; items[i] != NULL; ++i) {
34 item = items[i];
35 vitem = item_userptr(item);
36 SMB_ASSERT(vitem != NULL);
37 free_item(item);
40 talloc_free(items);
43 static int value_list_free(struct value_list *vl)
45 if (vl->menu) {
46 unpost_menu(vl->menu);
47 free_menu(vl->menu);
49 if (vl->empty && vl->empty[0]) {
50 free_item(vl->empty[0]);
52 value_list_free_items(vl->items);
54 return 0;
57 struct value_list *value_list_new(TALLOC_CTX *ctx, WINDOW *orig, int nlines,
58 int ncols, int begin_y, int begin_x)
60 static const char *empty = "(no values)";
61 static const char *empty_desc = "";
62 struct value_list *vl;
64 vl = talloc_zero(ctx, struct value_list);
65 if (vl == NULL) {
66 return NULL;
69 talloc_set_destructor(vl, value_list_free);
71 vl->empty = talloc_zero_array(vl, ITEM *, 2);
72 if (vl->empty == NULL) {
73 goto fail;
75 vl->empty[0] = new_item(empty, empty_desc);
76 if (vl->empty[0] == NULL) {
77 goto fail;
80 vl->window = orig;
81 vl->sub_window = derwin(orig, nlines, ncols, begin_y, begin_x);
83 vl->menu = new_menu(vl->empty);
84 if (vl->menu == NULL) {
85 goto fail;
88 set_menu_format(vl->menu, nlines, 1);
89 set_menu_win(vl->menu, vl->window);
90 set_menu_sub(vl->menu, vl->sub_window);
91 menu_opts_on(vl->menu, O_SHOWDESC);
92 set_menu_mark(vl->menu, "* ");
94 return vl;
96 fail:
97 talloc_free(vl);
99 return NULL;
102 static uint32_t get_num_values(TALLOC_CTX *ctx, const struct registry_key *key)
104 const char *classname;
105 uint32_t num_subkeys;
106 uint32_t num_values;
107 NTTIME last_change_time;
108 uint32_t max_subkeynamelen;
109 uint32_t max_valnamelen;
110 uint32_t max_valbufsize;
111 WERROR rv;
113 rv = reg_key_get_info(ctx, key, &classname, &num_subkeys,
114 &num_values, &last_change_time,
115 &max_subkeynamelen, &max_valnamelen,
116 &max_valbufsize);
118 if (W_ERROR_IS_OK(rv)) {
119 return num_values;
122 return 0;
125 void value_list_show(struct value_list *vl)
127 post_menu(vl->menu);
128 wrefresh(vl->window);
131 static WERROR append_data_summary(struct value_item *vitem)
133 char *tmp;
135 /* This is adapted from print_registry_value() in net_registry_util.c */
137 switch(vitem->type) {
138 case REG_DWORD: {
139 uint32_t v = 0;
140 if (vitem->data.length >= 4) {
141 v = IVAL(vitem->data.data, 0);
143 tmp = talloc_asprintf_append(vitem->value_desc, "(0x%x)", v);
144 break;
146 case REG_SZ:
147 case REG_EXPAND_SZ: {
148 const char *s;
150 if (!pull_reg_sz(vitem, &vitem->data, &s)) {
151 break;
153 tmp = talloc_asprintf_append(vitem->value_desc, "(\"%s\")", s);
154 break;
156 case REG_MULTI_SZ: {
157 size_t i;
158 const char **a;
160 if (!pull_reg_multi_sz(vitem, &vitem->data, &a)) {
161 break;
163 tmp = vitem->value_desc;
164 for (i = 0; a[i] != NULL; ++i) {
165 tmp = talloc_asprintf_append(tmp, "\"%s\" ", a[i]);
166 if (tmp == NULL) {
167 return WERR_NOMEM;
170 break;
172 case REG_BINARY:
173 tmp = talloc_asprintf_append(vitem->value_desc, "(%d bytes)",
174 (int)vitem->data.length);
175 break;
176 default:
177 tmp = talloc_asprintf_append(vitem->value_desc,
178 "(<unprintable>)");
179 break;
182 if (tmp == NULL) {
183 return WERR_NOMEM;
186 vitem->value_desc = tmp;
188 return WERR_OK;
191 WERROR value_list_load(struct value_list *vl, struct registry_key *key)
193 uint32_t n_values;
194 uint32_t idx;
195 struct value_item *vitem;
196 ITEM **new_items;
197 WERROR rv;
199 unpost_menu(vl->menu);
201 n_values = get_num_values(vl, key);
202 if (n_values == 0) {
203 set_menu_items(vl->menu, vl->empty);
204 return WERR_OK;
207 new_items = talloc_zero_array(vl, ITEM *, n_values + 1);
208 if (new_items == NULL) {
209 return WERR_NOMEM;
212 for (idx = 0; idx < n_values; ++idx) {
213 vitem = talloc_zero(new_items, struct value_item);
214 if (vitem == NULL) {
215 return WERR_NOMEM;
218 rv = reg_key_get_value_by_index(vitem, key, idx,
219 &vitem->value_name,
220 &vitem->type,
221 &vitem->data);
223 if (!W_ERROR_IS_OK(rv)) {
224 talloc_free(vitem);
225 return rv;
228 vitem->value_desc = talloc_asprintf(vitem, "%-8s",
229 str_regtype(vitem->type));
230 if (vitem->value_desc == NULL) {
231 talloc_free(vitem);
232 return rv;
235 rv = append_data_summary(vitem);
236 if (!W_ERROR_IS_OK(rv)) {
237 talloc_free(vitem);
238 return rv;
241 new_items[idx] = new_item(vitem->value_name,
242 vitem->value_desc);
243 set_item_userptr(new_items[idx], vitem);
246 set_menu_items(vl->menu, new_items);
247 value_list_free_items(vl->items);
248 vl->items = new_items;
250 return WERR_OK;