2012-07-18 13:31:41 +04:00
/*
* 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"
2012-07-20 14:53:42 +04:00
static void value_list_free_items ( ITEM * * items )
2012-07-18 13:31:41 +04:00
{
size_t i ;
ITEM * item ;
struct value_item * vitem ;
2012-07-20 14:53:42 +04:00
if ( items = = NULL ) {
2012-07-18 13:31:41 +04:00
return ;
}
2012-07-20 14:53:42 +04:00
for ( i = 0 ; items [ i ] ! = NULL ; + + i ) {
item = items [ i ] ;
2012-07-18 13:31:41 +04:00
vitem = item_userptr ( item ) ;
SMB_ASSERT ( vitem ! = NULL ) ;
free_item ( item ) ;
}
2012-07-20 14:53:42 +04:00
talloc_free ( items ) ;
2012-07-18 13:31:41 +04:00
}
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 ] ) ;
}
2012-08-11 07:05:20 +04:00
if ( vl - > panel ) {
del_panel ( vl - > panel ) ;
}
if ( vl - > window ) {
delwin ( vl - > window ) ;
}
2012-07-20 14:53:42 +04:00
value_list_free_items ( vl - > items ) ;
2012-07-18 13:31:41 +04:00
return 0 ;
}
2012-08-11 07:05:20 +04:00
struct value_list * value_list_new ( TALLOC_CTX * ctx , int nlines , int ncols ,
int begin_y , int begin_x )
2012-07-18 13:31:41 +04:00
{
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 ) ;
2012-07-20 14:53:42 +04:00
vl - > empty = talloc_zero_array ( vl , ITEM * , 2 ) ;
2012-07-18 13:31:41 +04:00
if ( vl - > empty = = NULL ) {
goto fail ;
}
vl - > empty [ 0 ] = new_item ( empty , empty_desc ) ;
if ( vl - > empty [ 0 ] = = NULL ) {
goto fail ;
}
2012-08-11 07:05:20 +04:00
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 ;
}
2012-07-18 13:31:41 +04:00
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 ) ;
2012-08-11 07:05:20 +04:00
2012-07-18 13:31:41 +04:00
menu_opts_on ( vl - > menu , O_SHOWDESC ) ;
set_menu_mark ( vl - > menu , " * " ) ;
return vl ;
fail :
talloc_free ( vl ) ;
return NULL ;
}
2012-08-11 07:05:20 +04:00
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 ) ;
}
2012-07-18 13:31:41 +04:00
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 ) ;
}
2012-08-20 07:09:53 +04:00
static bool string_is_printable ( const char * s )
{
const char * p ;
for ( p = s ; * p ; + + p ) {
if ( ! isprint ( * p ) ) {
return false ;
}
}
return true ;
}
2012-07-20 14:53:42 +04:00
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 ;
}
2012-08-20 07:09:53 +04:00
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 ) ;
}
2012-07-20 14:53:42 +04:00
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 ) {
2012-08-20 07:09:53 +04:00
if ( ! string_is_printable ( a [ i ] ) ) {
tmp = talloc_asprintf_append ( tmp ,
" (unprintable) " ) ;
vitem - > unprintable = true ;
} else {
tmp = talloc_asprintf_append ( tmp , " \" %s \" " ,
a [ i ] ) ;
}
2012-07-20 14:53:42 +04:00
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 ;
}
2012-07-18 13:31:41 +04:00
WERROR value_list_load ( struct value_list * vl , struct registry_key * key )
{
uint32_t n_values ;
uint32_t idx ;
struct value_item * vitem ;
2012-07-20 14:53:42 +04:00
ITEM * * new_items ;
2012-07-18 13:31:41 +04:00
WERROR rv ;
2012-08-09 01:37:20 +04:00
static const char * empty_name = " (empty) " ;
const char * name ;
2012-07-18 13:31:41 +04:00
unpost_menu ( vl - > menu ) ;
n_values = get_num_values ( vl , key ) ;
if ( n_values = = 0 ) {
2012-07-20 14:53:42 +04:00
set_menu_items ( vl - > menu , vl - > empty ) ;
2012-07-18 13:31:41 +04:00
return WERR_OK ;
}
2012-07-20 14:53:42 +04:00
new_items = talloc_zero_array ( vl , ITEM * , n_values + 1 ) ;
if ( new_items = = NULL ) {
2012-07-18 13:31:41 +04:00
return WERR_NOMEM ;
}
for ( idx = 0 ; idx < n_values ; + + idx ) {
2012-07-20 14:53:42 +04:00
vitem = talloc_zero ( new_items , struct value_item ) ;
2012-07-18 13:31:41 +04:00
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 ;
}
2012-08-12 02:00:55 +04:00
vitem - > value_desc = talloc_asprintf ( vitem , " %-14s " ,
2012-07-20 14:53:42 +04:00
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 ;
}
2012-07-18 13:31:41 +04:00
2012-08-09 01:37:20 +04:00
/* 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 ;
}
2012-07-20 14:53:42 +04:00
set_item_userptr ( new_items [ idx ] , vitem ) ;
2012-07-18 13:31:41 +04:00
}
2012-07-20 14:53:42 +04:00
set_menu_items ( vl - > menu , new_items ) ;
value_list_free_items ( vl - > items ) ;
vl - > items = new_items ;
2012-07-18 13:31:41 +04:00
return WERR_OK ;
}