mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
68d4e8dfc7
Also, edit the values in bin mode to avoid screen glitches. Reviewed-by: Andreas Schneider <asn@samba.org> Reviewed-by: Michael Adam <obnox@samba.org>
316 lines
6.4 KiB
C
316 lines
6.4 KiB
C
/*
|
|
* Samba Unix/Linux SMB client library
|
|
* Registry Editor
|
|
* Copyright (C) Christopher Davis 2012
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "regedit_valuelist.h"
|
|
#include "lib/registry/registry.h"
|
|
|
|
static void value_list_free_items(ITEM **items)
|
|
{
|
|
size_t i;
|
|
ITEM *item;
|
|
struct value_item *vitem;
|
|
|
|
if (items == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; items[i] != NULL; ++i) {
|
|
item = items[i];
|
|
vitem = item_userptr(item);
|
|
SMB_ASSERT(vitem != NULL);
|
|
free_item(item);
|
|
}
|
|
|
|
talloc_free(items);
|
|
}
|
|
|
|
static int value_list_free(struct value_list *vl)
|
|
{
|
|
if (vl->menu) {
|
|
unpost_menu(vl->menu);
|
|
free_menu(vl->menu);
|
|
}
|
|
if (vl->empty && vl->empty[0]) {
|
|
free_item(vl->empty[0]);
|
|
}
|
|
if (vl->panel) {
|
|
del_panel(vl->panel);
|
|
}
|
|
if (vl->window) {
|
|
delwin(vl->window);
|
|
}
|
|
value_list_free_items(vl->items);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct value_list *value_list_new(TALLOC_CTX *ctx, int nlines, int ncols,
|
|
int begin_y, int begin_x)
|
|
{
|
|
static const char *empty = "(no values)";
|
|
static const char *empty_desc = "";
|
|
struct value_list *vl;
|
|
|
|
vl = talloc_zero(ctx, struct value_list);
|
|
if (vl == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
talloc_set_destructor(vl, value_list_free);
|
|
|
|
vl->empty = talloc_zero_array(vl, ITEM *, 2);
|
|
if (vl->empty == NULL) {
|
|
goto fail;
|
|
}
|
|
vl->empty[0] = new_item(empty, empty_desc);
|
|
if (vl->empty[0] == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
vl->window = newwin(nlines, ncols, begin_y, begin_x);
|
|
if (vl->window == NULL) {
|
|
goto fail;
|
|
}
|
|
vl->panel = new_panel(vl->window);
|
|
if (vl->panel == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
vl->menu = new_menu(vl->empty);
|
|
if (vl->menu == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
set_menu_format(vl->menu, nlines, 1);
|
|
set_menu_win(vl->menu, vl->window);
|
|
|
|
menu_opts_on(vl->menu, O_SHOWDESC);
|
|
set_menu_mark(vl->menu, "* ");
|
|
|
|
return vl;
|
|
|
|
fail:
|
|
talloc_free(vl);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void value_list_resize(struct value_list *vl, int nlines, int ncols,
|
|
int begin_y, int begin_x)
|
|
{
|
|
WINDOW *nwin;
|
|
|
|
unpost_menu(vl->menu);
|
|
nwin = newwin(nlines, ncols, begin_y, begin_x);
|
|
replace_panel(vl->panel, nwin);
|
|
delwin(vl->window);
|
|
vl->window = nwin;
|
|
set_menu_format(vl->menu, nlines, 1);
|
|
set_menu_win(vl->menu, vl->window);
|
|
post_menu(vl->menu);
|
|
}
|
|
|
|
static uint32_t get_num_values(TALLOC_CTX *ctx, const struct registry_key *key)
|
|
{
|
|
const char *classname;
|
|
uint32_t num_subkeys;
|
|
uint32_t num_values;
|
|
NTTIME last_change_time;
|
|
uint32_t max_subkeynamelen;
|
|
uint32_t max_valnamelen;
|
|
uint32_t max_valbufsize;
|
|
WERROR rv;
|
|
|
|
rv = reg_key_get_info(ctx, key, &classname, &num_subkeys,
|
|
&num_values, &last_change_time,
|
|
&max_subkeynamelen, &max_valnamelen,
|
|
&max_valbufsize);
|
|
|
|
if (W_ERROR_IS_OK(rv)) {
|
|
return num_values;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void value_list_show(struct value_list *vl)
|
|
{
|
|
post_menu(vl->menu);
|
|
}
|
|
|
|
static bool string_is_printable(const char *s)
|
|
{
|
|
const char *p;
|
|
|
|
for (p = s; *p; ++p) {
|
|
if (!isprint(*p)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static WERROR append_data_summary(struct value_item *vitem)
|
|
{
|
|
char *tmp;
|
|
|
|
/* This is adapted from print_registry_value() in net_registry_util.c */
|
|
|
|
switch(vitem->type) {
|
|
case REG_DWORD: {
|
|
uint32_t v = 0;
|
|
if (vitem->data.length >= 4) {
|
|
v = IVAL(vitem->data.data, 0);
|
|
}
|
|
tmp = talloc_asprintf_append(vitem->value_desc, "(0x%x)", v);
|
|
break;
|
|
}
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ: {
|
|
const char *s;
|
|
|
|
if (!pull_reg_sz(vitem, &vitem->data, &s)) {
|
|
break;
|
|
}
|
|
vitem->unprintable = !string_is_printable(s);
|
|
if (vitem->unprintable) {
|
|
tmp = talloc_asprintf_append(vitem->value_desc,
|
|
"(unprintable)");
|
|
} else {
|
|
tmp = talloc_asprintf_append(vitem->value_desc,
|
|
"(\"%s\")", s);
|
|
}
|
|
break;
|
|
}
|
|
case REG_MULTI_SZ: {
|
|
size_t i;
|
|
const char **a;
|
|
|
|
if (!pull_reg_multi_sz(vitem, &vitem->data, &a)) {
|
|
break;
|
|
}
|
|
tmp = vitem->value_desc;
|
|
for (i = 0; a[i] != NULL; ++i) {
|
|
if (!string_is_printable(a[i])) {
|
|
tmp = talloc_asprintf_append(tmp,
|
|
"(unprintable)");
|
|
vitem->unprintable = true;
|
|
} else {
|
|
tmp = talloc_asprintf_append(tmp, "\"%s\" ",
|
|
a[i]);
|
|
}
|
|
if (tmp == NULL) {
|
|
return WERR_NOMEM;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case REG_BINARY:
|
|
tmp = talloc_asprintf_append(vitem->value_desc, "(%d bytes)",
|
|
(int)vitem->data.length);
|
|
break;
|
|
default:
|
|
tmp = talloc_asprintf_append(vitem->value_desc,
|
|
"(<unprintable>)");
|
|
break;
|
|
}
|
|
|
|
if (tmp == NULL) {
|
|
return WERR_NOMEM;
|
|
}
|
|
|
|
vitem->value_desc = tmp;
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
WERROR value_list_load(struct value_list *vl, struct registry_key *key)
|
|
{
|
|
uint32_t n_values;
|
|
uint32_t idx;
|
|
struct value_item *vitem;
|
|
ITEM **new_items;
|
|
WERROR rv;
|
|
static const char *empty_name = "(empty)";
|
|
const char *name;
|
|
|
|
unpost_menu(vl->menu);
|
|
|
|
n_values = get_num_values(vl, key);
|
|
if (n_values == 0) {
|
|
set_menu_items(vl->menu, vl->empty);
|
|
return WERR_OK;
|
|
}
|
|
|
|
new_items = talloc_zero_array(vl, ITEM *, n_values + 1);
|
|
if (new_items == NULL) {
|
|
return WERR_NOMEM;
|
|
}
|
|
|
|
for (idx = 0; idx < n_values; ++idx) {
|
|
vitem = talloc_zero(new_items, struct value_item);
|
|
if (vitem == NULL) {
|
|
return WERR_NOMEM;
|
|
}
|
|
|
|
rv = reg_key_get_value_by_index(vitem, key, idx,
|
|
&vitem->value_name,
|
|
&vitem->type,
|
|
&vitem->data);
|
|
|
|
if (!W_ERROR_IS_OK(rv)) {
|
|
talloc_free(vitem);
|
|
return rv;
|
|
}
|
|
|
|
vitem->value_desc = talloc_asprintf(vitem, "%-14s",
|
|
str_regtype(vitem->type));
|
|
if (vitem->value_desc == NULL) {
|
|
talloc_free(vitem);
|
|
return rv;
|
|
}
|
|
|
|
rv = append_data_summary(vitem);
|
|
if (!W_ERROR_IS_OK(rv)) {
|
|
talloc_free(vitem);
|
|
return rv;
|
|
}
|
|
|
|
/* ncurses won't accept empty strings in menu items */
|
|
name = vitem->value_name;
|
|
if (name[0] == '\0') {
|
|
name = empty_name;
|
|
}
|
|
new_items[idx] = new_item(name, vitem->value_desc);
|
|
if (new_items[idx] == NULL) {
|
|
talloc_free(vitem);
|
|
return WERR_NOMEM;
|
|
}
|
|
|
|
set_item_userptr(new_items[idx], vitem);
|
|
}
|
|
|
|
set_menu_items(vl->menu, new_items);
|
|
value_list_free_items(vl->items);
|
|
vl->items = new_items;
|
|
|
|
return WERR_OK;
|
|
}
|