2 * Samba Unix/Linux SMB client library
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/>.
22 #include "regedit_valuelist.h"
23 #include "regedit_list.h"
24 #include "lib/registry/registry.h"
28 static int value_list_free(struct value_list
*vl
)
43 static const char *vl_get_column_header(const void *data
, unsigned col
)
57 static const void *vl_get_first_row(const void *data
)
59 const struct value_list
*vl
;
62 vl
= talloc_get_type_abort(data
, struct value_list
);
64 return &vl
->values
[0];
71 static const void *vl_get_next_row(const void *data
, const void *row
)
73 const struct value_list
*vl
;
74 const struct value_item
*value
= row
;
76 SMB_ASSERT(data
!= NULL
);
77 SMB_ASSERT(value
!= NULL
);
78 vl
= talloc_get_type_abort(data
, struct value_list
);
79 if (value
== &vl
->values
[vl
->nvalues
- 1]) {
86 static const void *vl_get_prev_row(const void *data
, const void *row
)
88 const struct value_list
*vl
;
89 const struct value_item
*value
= row
;
91 SMB_ASSERT(data
!= NULL
);
92 SMB_ASSERT(value
!= NULL
);
93 vl
= talloc_get_type_abort(data
, struct value_list
);
94 if (value
== &vl
->values
[0]) {
101 static const char *vl_get_item_label(const void *row
, unsigned col
)
103 const struct value_item
*value
= row
;
105 SMB_ASSERT(value
!= NULL
);
106 SMB_ASSERT(value
->value_name
!= NULL
);
109 return value
->value_name
;
111 return str_regtype(value
->type
);
122 static struct multilist_accessors vl_accessors
= {
123 .get_column_header
= vl_get_column_header
,
124 .get_first_row
= vl_get_first_row
,
125 .get_next_row
= vl_get_next_row
,
126 .get_prev_row
= vl_get_prev_row
,
127 .get_item_label
= vl_get_item_label
130 struct value_list
*value_list_new(TALLOC_CTX
*ctx
, int nlines
, int ncols
,
131 int begin_y
, int begin_x
)
133 struct value_list
*vl
;
135 vl
= talloc_zero(ctx
, struct value_list
);
140 talloc_set_destructor(vl
, value_list_free
);
142 vl
->window
= newwin(nlines
, ncols
, begin_y
, begin_x
);
143 if (vl
->window
== NULL
) {
146 vl
->sub
= subwin(vl
->window
, nlines
- 2, ncols
- 2,
147 begin_y
+ 1, begin_x
+ 1);
148 if (vl
->sub
== NULL
) {
151 box(vl
->window
, 0, 0);
152 mvwprintw(vl
->window
, 0, HEADING_X
, "Value");
154 vl
->panel
= new_panel(vl
->window
);
155 if (vl
->panel
== NULL
) {
159 vl
->list
= multilist_new(vl
, vl
->sub
, &vl_accessors
, 3);
160 if (vl
->list
== NULL
) {
172 void value_list_set_selected(struct value_list
*vl
, bool reverse
)
174 attr_t attr
= A_NORMAL
;
179 mvwchgat(vl
->window
, 0, HEADING_X
, 5, attr
, 0, NULL
);
182 void value_list_resize(struct value_list
*vl
, int nlines
, int ncols
,
183 int begin_y
, int begin_x
)
187 nwin
= newwin(nlines
, ncols
, begin_y
, begin_x
);
191 nsub
= subwin(nwin
, nlines
- 2, ncols
- 2, begin_y
+ 1, begin_x
+ 1);
196 replace_panel(vl
->panel
, nwin
);
201 box(vl
->window
, 0, 0);
202 mvwprintw(vl
->window
, 0, HEADING_X
, "Value");
203 multilist_set_window(vl
->list
, vl
->sub
);
207 static uint32_t get_num_values(TALLOC_CTX
*ctx
, const struct registry_key
*key
)
209 const char *classname
;
210 uint32_t num_subkeys
;
212 NTTIME last_change_time
;
213 uint32_t max_subkeynamelen
;
214 uint32_t max_valnamelen
;
215 uint32_t max_valbufsize
;
218 rv
= reg_key_get_info(ctx
, key
, &classname
, &num_subkeys
,
219 &num_values
, &last_change_time
,
220 &max_subkeynamelen
, &max_valnamelen
,
223 if (W_ERROR_IS_OK(rv
)) {
230 void value_list_show(struct value_list
*vl
)
232 multilist_refresh(vl
->list
);
233 touchwin(vl
->window
);
234 wnoutrefresh(vl
->window
);
235 wnoutrefresh(vl
->sub
);
238 static bool string_is_printable(const char *s
)
242 for (p
= s
; *p
; ++p
) {
251 static WERROR
append_data_summary(TALLOC_CTX
*ctx
, struct value_item
*vitem
)
255 /* This is adapted from print_registry_value() in net_registry_util.c */
257 switch(vitem
->type
) {
260 if (vitem
->data
.length
>= 4) {
261 v
= IVAL(vitem
->data
.data
, 0);
263 tmp
= talloc_asprintf(ctx
, "0x%08x (%u)", v
, v
);
267 case REG_EXPAND_SZ
: {
270 if (!pull_reg_sz(ctx
, &vitem
->data
, &s
)) {
273 vitem
->unprintable
= !string_is_printable(s
);
274 if (vitem
->unprintable
) {
275 tmp
= talloc_asprintf(ctx
, "(unprintable)");
277 tmp
= talloc_asprintf(ctx
, "%s", s
);
286 if (!pull_reg_multi_sz(ctx
, &vitem
->data
, &a
)) {
289 for (len
= 0; a
[len
] != NULL
; ++len
) {
291 tmp
= talloc_asprintf(ctx
, "(%u) ", (unsigned)len
);
295 for (i
= 0; i
< len
; ++i
) {
296 if (!string_is_printable(a
[i
])) {
297 val
= "(unprintable)";
298 vitem
->unprintable
= true;
303 tmp
= talloc_asprintf_append(tmp
,
307 tmp
= talloc_asprintf_append(tmp
,
318 tmp
= talloc_asprintf(ctx
, "(%d bytes)",
319 (int)vitem
->data
.length
);
322 tmp
= talloc_asprintf(ctx
, "(unknown)");
335 static int vitem_cmp(struct value_item
*a
, struct value_item
*b
)
337 return strcmp(a
->value_name
, b
->value_name
);
340 /* load only the value names into memory to enable searching */
341 WERROR
value_list_load_quick(struct value_list
*vl
, struct registry_key
*key
)
345 struct value_item
*vitem
, *new_items
;
348 multilist_set_data(vl
->list
, NULL
);
350 TALLOC_FREE(vl
->values
);
352 nvalues
= get_num_values(vl
, key
);
357 new_items
= talloc_zero_array(vl
, struct value_item
, nvalues
);
358 if (new_items
== NULL
) {
362 for (idx
= 0; idx
< nvalues
; ++idx
) {
363 vitem
= &new_items
[idx
];
364 rv
= reg_key_get_value_by_index(new_items
, key
, idx
,
368 if (!W_ERROR_IS_OK(rv
)) {
369 talloc_free(new_items
);
374 TYPESAFE_QSORT(new_items
, nvalues
, vitem_cmp
);
375 vl
->nvalues
= nvalues
;
376 vl
->values
= new_items
;
381 /* sync up the UI with the list */
382 WERROR
value_list_sync(struct value_list
*vl
)
387 for (idx
= 0; idx
< vl
->nvalues
; ++idx
) {
388 rv
= append_data_summary(vl
->values
, &vl
->values
[idx
]);
389 if (!W_ERROR_IS_OK(rv
)) {
394 rv
= multilist_set_data(vl
->list
, vl
);
395 if (W_ERROR_IS_OK(rv
)) {
396 multilist_refresh(vl
->list
);
402 WERROR
value_list_load(struct value_list
*vl
, struct registry_key
*key
)
406 rv
= value_list_load_quick(vl
, key
);
407 if (!W_ERROR_IS_OK(rv
)) {
411 rv
= value_list_sync(vl
);
416 struct value_item
*value_list_find_next_item(struct value_list
*vl
,
417 struct value_item
*vitem
,
419 regedit_search_match_fn_t match
)
421 struct value_item
*end
;
430 vitem
= &vl
->values
[0];
433 for (end
= &vl
->values
[vl
->nvalues
]; vitem
< end
; ++vitem
) {
434 if (match(vitem
->value_name
, s
)) {
442 struct value_item
*value_list_find_prev_item(struct value_list
*vl
,
443 struct value_item
*vitem
,
445 regedit_search_match_fn_t match
)
447 struct value_item
*end
;
456 vitem
= &vl
->values
[vl
->nvalues
- 1];
459 for (end
= &vl
->values
[-1]; vitem
> end
; --vitem
) {
460 if (match(vitem
->value_name
, s
)) {
468 struct value_item
*value_list_get_current_item(struct value_list
*vl
)
470 return discard_const_p(struct value_item
,
471 multilist_get_current_row(vl
->list
));
474 void value_list_set_current_item_by_name(struct value_list
*vl
,
479 for (i
= 0; i
< vl
->nvalues
; ++i
) {
480 if (strequal(vl
->values
[i
].value_name
, name
)) {
481 multilist_set_current_row(vl
->list
, &vl
->values
[i
]);
487 void value_list_set_current_item(struct value_list
*vl
,
488 const struct value_item
*item
)
490 multilist_set_current_row(vl
->list
, item
);
493 void value_list_driver(struct value_list
*vl
, int c
)
495 multilist_driver(vl
->list
, c
);