s4:samr: allow builtin groups for samr_OpenGroup.
[Samba.git] / source3 / utils / regedit_valuelist.c
blobb135159ed9289d2690b3166627390c1e82f5f3a4
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 if (vl->panel) {
53 del_panel(vl->panel);
55 if (vl->window) {
56 delwin(vl->window);
58 value_list_free_items(vl->items);
60 return 0;
63 struct value_list *value_list_new(TALLOC_CTX *ctx, int nlines, int ncols,
64 int begin_y, int begin_x)
66 static const char *empty = "(no values)";
67 static const char *empty_desc = "";
68 struct value_list *vl;
70 vl = talloc_zero(ctx, struct value_list);
71 if (vl == NULL) {
72 return NULL;
75 talloc_set_destructor(vl, value_list_free);
77 vl->empty = talloc_zero_array(vl, ITEM *, 2);
78 if (vl->empty == NULL) {
79 goto fail;
81 vl->empty[0] = new_item(empty, empty_desc);
82 if (vl->empty[0] == NULL) {
83 goto fail;
86 vl->window = newwin(nlines, ncols, begin_y, begin_x);
87 if (vl->window == NULL) {
88 goto fail;
90 vl->panel = new_panel(vl->window);
91 if (vl->panel == NULL) {
92 goto fail;
95 vl->menu = new_menu(vl->empty);
96 if (vl->menu == NULL) {
97 goto fail;
100 set_menu_format(vl->menu, nlines, 1);
101 set_menu_win(vl->menu, vl->window);
103 menu_opts_on(vl->menu, O_SHOWDESC);
104 set_menu_mark(vl->menu, "* ");
106 return vl;
108 fail:
109 talloc_free(vl);
111 return NULL;
114 void value_list_resize(struct value_list *vl, int nlines, int ncols,
115 int begin_y, int begin_x)
117 WINDOW *nwin;
119 unpost_menu(vl->menu);
120 nwin = newwin(nlines, ncols, begin_y, begin_x);
121 replace_panel(vl->panel, nwin);
122 delwin(vl->window);
123 vl->window = nwin;
124 set_menu_format(vl->menu, nlines, 1);
125 set_menu_win(vl->menu, vl->window);
126 post_menu(vl->menu);
129 static uint32_t get_num_values(TALLOC_CTX *ctx, const struct registry_key *key)
131 const char *classname;
132 uint32_t num_subkeys;
133 uint32_t num_values;
134 NTTIME last_change_time;
135 uint32_t max_subkeynamelen;
136 uint32_t max_valnamelen;
137 uint32_t max_valbufsize;
138 WERROR rv;
140 rv = reg_key_get_info(ctx, key, &classname, &num_subkeys,
141 &num_values, &last_change_time,
142 &max_subkeynamelen, &max_valnamelen,
143 &max_valbufsize);
145 if (W_ERROR_IS_OK(rv)) {
146 return num_values;
149 return 0;
152 void value_list_show(struct value_list *vl)
154 post_menu(vl->menu);
157 static bool string_is_printable(const char *s)
159 const char *p;
161 for (p = s; *p; ++p) {
162 if (!isprint(*p)) {
163 return false;
167 return true;
170 static WERROR append_data_summary(struct value_item *vitem)
172 char *tmp = NULL;
174 /* This is adapted from print_registry_value() in net_registry_util.c */
176 switch(vitem->type) {
177 case REG_DWORD: {
178 uint32_t v = 0;
179 if (vitem->data.length >= 4) {
180 v = IVAL(vitem->data.data, 0);
182 tmp = talloc_asprintf_append(vitem->value_desc, "(0x%x)", v);
183 break;
185 case REG_SZ:
186 case REG_EXPAND_SZ: {
187 const char *s;
189 if (!pull_reg_sz(vitem, &vitem->data, &s)) {
190 break;
192 vitem->unprintable = !string_is_printable(s);
193 if (vitem->unprintable) {
194 tmp = talloc_asprintf_append(vitem->value_desc,
195 "(unprintable)");
196 } else {
197 tmp = talloc_asprintf_append(vitem->value_desc,
198 "(\"%s\")", s);
200 break;
202 case REG_MULTI_SZ: {
203 size_t i;
204 const char **a;
206 if (!pull_reg_multi_sz(vitem, &vitem->data, &a)) {
207 break;
209 tmp = vitem->value_desc;
210 for (i = 0; a[i] != NULL; ++i) {
211 if (!string_is_printable(a[i])) {
212 tmp = talloc_asprintf_append(tmp,
213 "(unprintable)");
214 vitem->unprintable = true;
215 } else {
216 tmp = talloc_asprintf_append(tmp, "\"%s\" ",
217 a[i]);
219 if (tmp == NULL) {
220 return WERR_NOMEM;
223 break;
225 case REG_BINARY:
226 tmp = talloc_asprintf_append(vitem->value_desc, "(%d bytes)",
227 (int)vitem->data.length);
228 break;
229 default:
230 tmp = talloc_asprintf_append(vitem->value_desc,
231 "(<unprintable>)");
232 break;
235 if (tmp == NULL) {
236 return WERR_NOMEM;
239 vitem->value_desc = tmp;
241 return WERR_OK;
244 WERROR value_list_load(struct value_list *vl, struct registry_key *key)
246 uint32_t n_values;
247 uint32_t idx;
248 struct value_item *vitem;
249 ITEM **new_items;
250 WERROR rv;
251 static const char *empty_name = "(empty)";
252 const char *name;
254 unpost_menu(vl->menu);
256 n_values = get_num_values(vl, key);
257 if (n_values == 0) {
258 set_menu_items(vl->menu, vl->empty);
259 return WERR_OK;
262 new_items = talloc_zero_array(vl, ITEM *, n_values + 1);
263 if (new_items == NULL) {
264 return WERR_NOMEM;
267 for (idx = 0; idx < n_values; ++idx) {
268 vitem = talloc_zero(new_items, struct value_item);
269 if (vitem == NULL) {
270 return WERR_NOMEM;
273 rv = reg_key_get_value_by_index(vitem, key, idx,
274 &vitem->value_name,
275 &vitem->type,
276 &vitem->data);
278 if (!W_ERROR_IS_OK(rv)) {
279 talloc_free(vitem);
280 return rv;
283 vitem->value_desc = talloc_asprintf(vitem, "%-14s",
284 str_regtype(vitem->type));
285 if (vitem->value_desc == NULL) {
286 talloc_free(vitem);
287 return rv;
290 rv = append_data_summary(vitem);
291 if (!W_ERROR_IS_OK(rv)) {
292 talloc_free(vitem);
293 return rv;
296 /* ncurses won't accept empty strings in menu items */
297 name = vitem->value_name;
298 if (name[0] == '\0') {
299 name = empty_name;
301 new_items[idx] = new_item(name, vitem->value_desc);
302 if (new_items[idx] == NULL) {
303 talloc_free(vitem);
304 return WERR_NOMEM;
307 set_item_userptr(new_items[idx], vitem);
310 set_menu_items(vl->menu, new_items);
311 value_list_free_items(vl->items);
312 vl->items = new_items;
314 return WERR_OK;