2012-07-27 14:37:22 +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 "includes.h"
2012-08-11 08:56:58 +04:00
# include "regedit.h"
2012-07-27 14:37:22 +04:00
# include "regedit_dialog.h"
2012-08-07 06:11:13 +04:00
# include "regedit_valuelist.h"
2012-08-09 07:44:58 +04:00
# include "regedit_hexedit.h"
2012-08-07 06:11:13 +04:00
# include "util_reg.h"
# include "lib/registry/registry.h"
2012-07-27 14:37:22 +04:00
# include <stdarg.h>
2012-08-07 06:11:13 +04:00
# include <form.h>
2012-07-27 14:37:22 +04:00
2012-08-09 04:49:06 +04:00
static char * string_trim_n ( TALLOC_CTX * ctx , const char * buf , size_t n )
{
char * str ;
str = talloc_strndup ( ctx , buf , n ) ;
if ( str ) {
trim_string ( str , " " , " " ) ;
}
return str ;
}
static char * string_trim ( TALLOC_CTX * ctx , const char * buf )
{
char * str ;
str = talloc_strdup ( ctx , buf ) ;
if ( str ) {
trim_string ( str , " " , " " ) ;
}
return str ;
}
2012-07-27 14:37:22 +04:00
static int dialog_free ( struct dialog * dia )
{
if ( dia - > window ) {
delwin ( dia - > window ) ;
}
if ( dia - > sub_window ) {
delwin ( dia - > sub_window ) ;
}
if ( dia - > panel ) {
del_panel ( dia - > panel ) ;
}
if ( dia - > choices ) {
unpost_menu ( dia - > choices ) ;
free_menu ( dia - > choices ) ;
}
if ( dia - > choice_items ) {
ITEM * * it ;
for ( it = dia - > choice_items ; * it ! = NULL ; + + it ) {
free_item ( * it ) ;
}
}
return 0 ;
}
struct dialog * dialog_new ( TALLOC_CTX * ctx , const char * title , int nlines ,
int ncols , int y , int x )
{
struct dialog * dia ;
dia = talloc_zero ( ctx , struct dialog ) ;
if ( dia = = NULL ) {
return NULL ;
}
talloc_set_destructor ( dia , dialog_free ) ;
dia - > window = newwin ( nlines , ncols , y , x ) ;
if ( dia - > window = = NULL ) {
goto fail ;
}
box ( dia - > window , 0 , 0 ) ;
mvwaddstr ( dia - > window , 0 , 1 , title ) ;
/* body of the dialog within the box outline */
dia - > sub_window = derwin ( dia - > window , nlines - 2 , ncols - 2 , 1 , 1 ) ;
if ( dia - > sub_window = = NULL ) {
goto fail ;
}
dia - > panel = new_panel ( dia - > window ) ;
if ( dia - > panel = = NULL ) {
goto fail ;
}
return dia ;
fail :
talloc_free ( dia ) ;
return NULL ;
}
2012-08-11 08:56:58 +04:00
static void center_dialog_above_window ( int * nlines , int * ncols ,
2012-07-28 05:39:54 +04:00
int * y , int * x )
2012-07-27 14:37:22 +04:00
{
2012-07-28 05:39:54 +04:00
int centery , centerx ;
2012-07-27 14:37:22 +04:00
2012-08-11 08:56:58 +04:00
centery = LINES / 2 ;
centerx = COLS / 2 ;
2012-07-28 05:39:54 +04:00
* y = 0 ;
* x = 0 ;
2012-08-11 08:56:58 +04:00
if ( * nlines > LINES ) {
* nlines = LINES ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * ncols > COLS ) {
* ncols = COLS ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * nlines / 2 < centery ) {
2012-08-11 07:05:20 +04:00
* y = centery - * nlines / 2 ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * ncols / 2 < centerx ) {
2012-08-11 07:05:20 +04:00
* x = centerx - * ncols / 2 ;
2012-07-28 05:39:54 +04:00
}
}
2012-08-11 08:56:58 +04:00
static int dialog_getch ( struct dialog * dia )
{
int c ;
c = regedit_getch ( ) ;
if ( c = = KEY_RESIZE ) {
int nlines , ncols , y , x ;
getmaxyx ( dia - > window , nlines , ncols ) ;
getbegyx ( dia - > window , y , x ) ;
if ( dia - > centered ) {
center_dialog_above_window ( & nlines , & ncols , & y , & x ) ;
} else {
if ( nlines + y > LINES ) {
if ( nlines > LINES ) {
y = 0 ;
} else {
y = LINES - nlines ;
}
}
if ( ncols + x > COLS ) {
if ( ncols > COLS ) {
x = 0 ;
} else {
x = COLS - ncols ;
}
}
}
move_panel ( dia - > panel , y , x ) ;
doupdate ( ) ;
}
return c ;
}
2012-07-28 05:39:54 +04:00
struct dialog * dialog_center_new ( TALLOC_CTX * ctx , const char * title , int nlines ,
2012-08-11 08:56:58 +04:00
int ncols )
2012-07-28 05:39:54 +04:00
{
2012-08-11 08:56:58 +04:00
struct dialog * dia ;
2012-07-28 05:39:54 +04:00
int y , x ;
2012-08-11 08:56:58 +04:00
center_dialog_above_window ( & nlines , & ncols , & y , & x ) ;
2012-07-27 14:37:22 +04:00
2012-08-11 08:56:58 +04:00
dia = dialog_new ( ctx , title , nlines , ncols , y , x ) ;
if ( dia ) {
dia - > centered = true ;
}
return dia ;
2012-07-27 14:37:22 +04:00
}
struct dialog * dialog_choice_new ( TALLOC_CTX * ctx , const char * title ,
const char * * choices , int nlines ,
int ncols , int y , int x )
{
size_t nchoices , i ;
struct dialog * dia ;
dia = dialog_new ( ctx , title , nlines , ncols , y , x ) ;
if ( dia = = NULL ) {
return NULL ;
}
dia - > menu_window = derwin ( dia - > sub_window , 1 , ncols - 3 ,
nlines - 3 , 0 ) ;
if ( dia - > menu_window = = NULL ) {
goto fail ;
}
for ( nchoices = 0 ; choices [ nchoices ] ! = NULL ; + + nchoices )
;
dia - > choice_items = talloc_zero_array ( dia , ITEM * , nchoices + 1 ) ;
if ( dia - > choice_items = = NULL ) {
goto fail ;
}
for ( i = 0 ; i < nchoices ; + + i ) {
char * desc = talloc_strdup ( dia , choices [ i ] ) ;
if ( desc = = NULL ) {
goto fail ;
}
dia - > choice_items [ i ] = new_item ( desc , desc ) ;
if ( dia - > choice_items [ i ] = = NULL ) {
goto fail ;
}
/* store choice index */
set_item_userptr ( dia - > choice_items [ i ] , ( void * ) ( uintptr_t ) i ) ;
}
dia - > choices = new_menu ( dia - > choice_items ) ;
if ( dia - > choices = = NULL ) {
goto fail ;
}
set_menu_format ( dia - > choices , 1 , ncols ) ;
set_menu_win ( dia - > choices , dia - > sub_window ) ;
set_menu_sub ( dia - > choices , dia - > menu_window ) ;
menu_opts_off ( dia - > choices , O_SHOWDESC ) ;
set_menu_mark ( dia - > choices , " * " ) ;
post_menu ( dia - > choices ) ;
wmove ( dia - > sub_window , 0 , 0 ) ;
return dia ;
fail :
talloc_free ( dia ) ;
return NULL ;
}
struct dialog * dialog_choice_center_new ( TALLOC_CTX * ctx , const char * title ,
const char * * choices , int nlines ,
2012-08-11 08:56:58 +04:00
int ncols )
2012-07-27 14:37:22 +04:00
{
2012-07-28 05:39:54 +04:00
int y , x ;
2012-08-11 08:56:58 +04:00
struct dialog * dia ;
center_dialog_above_window ( & nlines , & ncols , & y , & x ) ;
2012-07-27 14:37:22 +04:00
2012-08-11 08:56:58 +04:00
dia = dialog_choice_new ( ctx , title , choices , nlines , ncols , y , x ) ;
if ( dia ) {
dia - > centered = true ;
}
2012-07-27 14:37:22 +04:00
2012-08-11 08:56:58 +04:00
return dia ;
2012-07-27 14:37:22 +04:00
}
2012-08-07 06:11:13 +04:00
static int handle_menu_input ( MENU * menu , int c )
2012-07-27 14:37:22 +04:00
{
2012-08-07 06:11:13 +04:00
ITEM * item ;
switch ( c ) {
case KEY_LEFT :
menu_driver ( menu , REQ_LEFT_ITEM ) ;
break ;
case KEY_RIGHT :
menu_driver ( menu , REQ_RIGHT_ITEM ) ;
break ;
case KEY_ENTER :
case ' \n ' :
item = current_item ( menu ) ;
return ( int ) ( uintptr_t ) item_userptr ( item ) ;
}
return - 1 ;
}
2012-08-09 04:49:06 +04:00
static void handle_form_input ( FORM * frm , int c )
{
switch ( c ) {
case ' \n ' :
form_driver ( frm , REQ_NEW_LINE ) ;
break ;
case KEY_UP :
form_driver ( frm , REQ_UP_CHAR ) ;
break ;
case KEY_DOWN :
form_driver ( frm , REQ_DOWN_CHAR ) ;
break ;
case ' \b ' :
case KEY_BACKSPACE :
form_driver ( frm , REQ_DEL_PREV ) ;
break ;
case KEY_LEFT :
form_driver ( frm , REQ_LEFT_CHAR ) ;
break ;
case KEY_RIGHT :
form_driver ( frm , REQ_RIGHT_CHAR ) ;
break ;
default :
form_driver ( frm , c ) ;
break ;
}
}
2012-08-09 02:36:01 +04:00
static int modal_loop ( struct dialog * dia )
2012-08-07 06:11:13 +04:00
{
int c ;
int selection = - 1 ;
update_panels ( ) ;
doupdate ( ) ;
while ( selection = = - 1 ) {
2012-08-11 08:56:58 +04:00
c = dialog_getch ( dia ) ;
2012-08-07 06:11:13 +04:00
selection = handle_menu_input ( dia - > choices , c ) ;
update_panels ( ) ;
doupdate ( ) ;
}
talloc_free ( dia ) ;
return selection ;
2012-07-27 14:37:22 +04:00
}
2012-08-09 04:49:06 +04:00
static struct dialog * dialog_msg_new ( TALLOC_CTX * ctx , const char * title ,
2012-08-11 08:56:58 +04:00
const char * * choices , int nlines ,
const char * msg , va_list ap )
2012-08-09 02:36:01 +04:00
{
struct dialog * dia ;
char * str ;
2012-08-09 04:49:06 +04:00
int width ;
# define MIN_WIDTH 20
str = talloc_vasprintf ( ctx , msg , ap ) ;
if ( str = = NULL ) {
return NULL ;
}
width = strlen ( str ) + 2 ;
if ( width < MIN_WIDTH ) {
width = MIN_WIDTH ;
}
2012-08-11 08:56:58 +04:00
dia = dialog_choice_center_new ( ctx , title , choices , nlines , width ) ;
2012-08-09 04:49:06 +04:00
if ( dia = = NULL ) {
return NULL ;
}
waddstr ( dia - > sub_window , str ) ;
talloc_free ( str ) ;
return dia ;
}
int dialog_input ( TALLOC_CTX * ctx , char * * output , const char * title ,
2012-08-11 08:56:58 +04:00
const char * msg , . . . )
2012-08-09 04:49:06 +04:00
{
va_list ap ;
struct dialog * dia ;
2012-08-09 02:36:01 +04:00
const char * choices [ ] = {
" Ok " ,
" Cancel " ,
NULL
} ;
2012-08-09 04:49:06 +04:00
FIELD * field [ 2 ] = { 0 } ;
FORM * input ;
WINDOW * input_win ;
int y , x ;
int rv = - 1 ;
bool input_section = true ;
2012-08-09 02:36:01 +04:00
va_start ( ap , msg ) ;
2012-08-11 08:56:58 +04:00
dia = dialog_msg_new ( ctx , title , choices , 7 , msg , ap ) ;
2012-08-09 02:36:01 +04:00
va_end ( ap ) ;
2012-08-09 04:49:06 +04:00
if ( dia = = NULL ) {
2012-08-09 02:36:01 +04:00
return - 1 ;
}
2012-08-09 04:49:06 +04:00
getmaxyx ( dia - > sub_window , y , x ) ;
input_win = derwin ( dia - > sub_window , 1 , x - 2 , 2 , 1 ) ;
if ( input_win = = NULL ) {
goto finish ;
}
field [ 0 ] = new_field ( 1 , x - 2 , 0 , 0 , 0 , 0 ) ;
if ( field [ 0 ] = = NULL ) {
goto finish ;
}
field_opts_off ( field [ 0 ] , O_BLANK | O_AUTOSKIP | O_STATIC ) ;
set_field_back ( field [ 0 ] , A_REVERSE ) ;
input = new_form ( field ) ;
form_opts_off ( input , O_NL_OVERLOAD | O_BS_OVERLOAD ) ;
set_form_win ( input , dia - > sub_window ) ;
set_form_sub ( input , input_win ) ;
set_current_field ( input , field [ 0 ] ) ;
post_form ( input ) ;
* output = NULL ;
update_panels ( ) ;
doupdate ( ) ;
while ( rv = = - 1 ) {
2012-08-11 08:56:58 +04:00
int c = dialog_getch ( dia ) ;
2012-08-09 04:49:06 +04:00
if ( c = = ' \t ' | | c = = KEY_BTAB ) {
if ( input_section ) {
if ( form_driver ( input , REQ_VALIDATION ) = = E_OK ) {
input_section = false ;
menu_driver ( dia - > choices , REQ_FIRST_ITEM ) ;
}
} else {
input_section = true ;
set_current_field ( input , field [ 0 ] ) ;
}
2012-08-11 08:56:58 +04:00
} else if ( input_section ) {
2012-08-09 04:49:06 +04:00
handle_form_input ( input , c ) ;
} else {
rv = handle_menu_input ( dia - > choices , c ) ;
if ( rv = = DIALOG_OK ) {
const char * buf = field_buffer ( field [ 0 ] , 0 ) ;
* output = string_trim ( ctx , buf ) ;
}
}
2012-08-11 08:56:58 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-08-09 04:49:06 +04:00
}
finish :
if ( input ) {
unpost_form ( input ) ;
free_form ( input ) ;
}
if ( field [ 0 ] ) {
free_field ( field [ 0 ] ) ;
}
if ( input_win ) {
delwin ( input_win ) ;
}
talloc_free ( dia ) ;
return rv ;
}
int dialog_notice ( TALLOC_CTX * ctx , enum dialog_type type ,
2012-08-11 08:56:58 +04:00
const char * title , const char * msg , . . . )
2012-08-09 04:49:06 +04:00
{
va_list ap ;
struct dialog * dia ;
const char * choices [ ] = {
" Ok " ,
" Cancel " ,
NULL
} ;
2012-08-09 02:36:01 +04:00
if ( type = = DIA_ALERT ) {
choices [ 1 ] = NULL ;
}
2012-08-09 04:49:06 +04:00
va_start ( ap , msg ) ;
2012-08-11 08:56:58 +04:00
dia = dialog_msg_new ( ctx , title , choices , 5 , msg , ap ) ;
2012-08-09 04:49:06 +04:00
va_end ( ap ) ;
2012-08-09 02:36:01 +04:00
if ( dia = = NULL ) {
return - 1 ;
}
return modal_loop ( dia ) ;
}
2012-08-07 06:11:13 +04:00
# define MAX_FIELDS 8
enum input_section {
IN_NAME ,
IN_DATA ,
IN_MENU
} ;
2012-08-08 06:19:28 +04:00
struct edit_dialog {
struct dialog * dia ;
WINDOW * input_win ;
FORM * input ;
FIELD * field [ MAX_FIELDS ] ;
2012-08-09 07:44:58 +04:00
struct hexedit * buf ;
2012-08-08 06:19:28 +04:00
enum input_section section ;
} ;
2012-08-08 10:41:50 +04:00
static int edit_dialog_free ( struct edit_dialog * edit )
{
if ( edit - > input ) {
unpost_form ( edit - > input ) ;
}
if ( edit - > field [ 0 ] ) {
free_field ( edit - > field [ 0 ] ) ;
}
if ( edit - > field [ 1 ] ) {
free_field ( edit - > field [ 1 ] ) ;
}
delwin ( edit - > input_win ) ;
return 0 ;
}
2012-08-08 06:19:28 +04:00
static WERROR fill_value_buffer ( struct edit_dialog * edit ,
const struct value_item * vitem )
2012-08-07 06:11:13 +04:00
{
char * tmp ;
switch ( vitem - > type ) {
case REG_DWORD : {
uint32_t v = 0 ;
if ( vitem - > data . length > = 4 ) {
v = IVAL ( vitem - > data . data , 0 ) ;
2012-07-27 14:37:22 +04:00
}
2012-08-08 06:19:28 +04:00
tmp = talloc_asprintf ( edit , " 0x%x " , v ) ;
if ( tmp = = NULL ) {
return WERR_NOMEM ;
}
set_field_buffer ( edit - > field [ 1 ] , 0 , tmp ) ;
2012-08-07 06:11:13 +04:00
talloc_free ( tmp ) ;
2012-07-27 14:37:22 +04:00
break ;
}
2012-08-07 06:11:13 +04:00
case REG_SZ :
case REG_EXPAND_SZ : {
const char * s ;
2012-08-08 06:19:28 +04:00
if ( ! pull_reg_sz ( edit , & vitem - > data , & s ) ) {
return WERR_NOMEM ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
set_field_buffer ( edit - > field [ 1 ] , 0 , s ) ;
2012-08-07 06:11:13 +04:00
break ;
}
2012-08-08 06:19:28 +04:00
case REG_MULTI_SZ : {
const char * * p , * * a ;
char * buf = NULL ;
if ( ! pull_reg_multi_sz ( edit , & vitem - > data , & a ) ) {
return WERR_NOMEM ;
}
for ( p = a ; * p ! = NULL ; + + p ) {
if ( buf = = NULL ) {
buf = talloc_asprintf ( edit , " %s \n " , * p ) ;
} else {
buf = talloc_asprintf_append ( buf , " %s \n " , * p ) ;
}
if ( buf = = NULL ) {
return WERR_NOMEM ;
}
}
set_field_buffer ( edit - > field [ 1 ] , 0 , buf ) ;
talloc_free ( buf ) ;
}
2012-08-09 07:44:58 +04:00
case REG_BINARY :
/* initialized upon dialog creation */
break ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
return WERR_OK ;
2012-08-07 06:11:13 +04:00
}
2012-08-09 02:36:01 +04:00
static bool value_exists ( TALLOC_CTX * ctx , const struct registry_key * key ,
const char * name )
{
uint32_t type ;
DATA_BLOB blob ;
WERROR rv ;
rv = reg_key_get_value_by_name ( ctx , key , name , & type , & blob ) ;
return W_ERROR_IS_OK ( rv ) ;
}
2012-08-08 10:41:50 +04:00
static WERROR set_value ( struct edit_dialog * edit , struct registry_key * key ,
2012-08-09 02:36:01 +04:00
uint32_t type , bool new_value )
2012-08-08 10:41:50 +04:00
{
WERROR rv ;
DATA_BLOB blob ;
char * name = string_trim ( edit , field_buffer ( edit - > field [ 0 ] , 0 ) ) ;
2012-08-09 07:44:58 +04:00
if ( ! new_value & & ! edit - > buf & & ! field_status ( edit - > field [ 1 ] ) ) {
2012-08-08 10:41:50 +04:00
return WERR_OK ;
}
2012-08-09 02:36:01 +04:00
if ( new_value & & value_exists ( edit , key , name ) ) {
return WERR_FILE_EXISTS ;
}
2012-08-08 10:41:50 +04:00
switch ( type ) {
case REG_DWORD : {
uint32_t val ;
int base = 10 ;
2012-08-09 07:44:58 +04:00
const char * buf = field_buffer ( edit - > field [ 1 ] , 0 ) ;
2012-08-08 10:41:50 +04:00
if ( buf [ 0 ] = = ' 0 ' & & tolower ( buf [ 1 ] ) = = ' x ' ) {
base = 16 ;
}
val = strtoul ( buf , NULL , base ) ;
blob = data_blob_talloc ( edit , NULL , sizeof ( val ) ) ;
SIVAL ( blob . data , 0 , val ) ;
rv = WERR_OK ;
break ;
}
case REG_SZ :
case REG_EXPAND_SZ : {
2012-08-09 07:44:58 +04:00
const char * buf = field_buffer ( edit - > field [ 1 ] , 0 ) ;
2012-08-08 10:41:50 +04:00
char * str = string_trim ( edit , buf ) ;
2012-08-09 07:44:58 +04:00
2012-08-08 10:41:50 +04:00
if ( ! str | | ! push_reg_sz ( edit , & blob , str ) ) {
rv = WERR_NOMEM ;
}
break ;
}
case REG_MULTI_SZ : {
int rows , cols , max ;
const char * * arr ;
size_t i ;
2012-08-09 07:44:58 +04:00
const char * buf = field_buffer ( edit - > field [ 1 ] , 0 ) ;
2012-08-08 10:41:50 +04:00
dynamic_field_info ( edit - > field [ 1 ] , & rows , & cols , & max ) ;
arr = talloc_zero_array ( edit , const char * , rows + 1 ) ;
if ( arr = = NULL ) {
return WERR_NOMEM ;
}
for ( i = 0 ; * buf ; + + i , buf + = cols ) {
SMB_ASSERT ( i < rows ) ;
arr [ i ] = string_trim_n ( edit , buf , cols ) ;
}
if ( ! push_reg_multi_sz ( edit , & blob , arr ) ) {
rv = WERR_NOMEM ;
}
break ;
}
2012-08-09 07:44:58 +04:00
case REG_BINARY :
blob = data_blob_talloc ( edit , NULL , edit - > buf - > len ) ;
memcpy ( blob . data , edit - > buf - > data , edit - > buf - > len ) ;
break ;
2012-08-08 10:41:50 +04:00
}
rv = reg_val_set ( key , name , type , blob ) ;
return rv ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
static void section_down ( struct edit_dialog * edit )
{
switch ( edit - > section ) {
case IN_NAME :
if ( form_driver ( edit - > input , REQ_VALIDATION ) = = E_OK ) {
edit - > section = IN_DATA ;
2012-08-09 07:44:58 +04:00
if ( edit - > buf ) {
hexedit_set_cursor ( edit - > buf ) ;
} else {
set_current_field ( edit - > input , edit - > field [ 1 ] ) ;
}
2012-08-08 06:19:28 +04:00
}
break ;
case IN_DATA :
2012-08-09 07:44:58 +04:00
if ( edit - > buf | |
form_driver ( edit - > input , REQ_VALIDATION ) = = E_OK ) {
2012-08-08 06:19:28 +04:00
edit - > section = IN_MENU ;
menu_driver ( edit - > dia - > choices , REQ_FIRST_ITEM ) ;
}
break ;
case IN_MENU :
edit - > section = IN_NAME ;
set_current_field ( edit - > input , edit - > field [ 0 ] ) ;
break ;
}
2012-08-11 08:56:58 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-08-08 06:19:28 +04:00
}
static void section_up ( struct edit_dialog * edit )
{
switch ( edit - > section ) {
case IN_NAME :
if ( form_driver ( edit - > input , REQ_VALIDATION ) = = E_OK ) {
edit - > section = IN_MENU ;
menu_driver ( edit - > dia - > choices , REQ_FIRST_ITEM ) ;
}
break ;
case IN_DATA :
2012-08-09 07:44:58 +04:00
if ( edit - > buf | |
form_driver ( edit - > input , REQ_VALIDATION ) = = E_OK ) {
2012-08-08 06:19:28 +04:00
edit - > section = IN_NAME ;
set_current_field ( edit - > input , edit - > field [ 0 ] ) ;
}
break ;
case IN_MENU :
edit - > section = IN_DATA ;
2012-08-09 07:44:58 +04:00
if ( edit - > buf ) {
hexedit_set_cursor ( edit - > buf ) ;
} else {
set_current_field ( edit - > input , edit - > field [ 1 ] ) ;
}
2012-08-08 06:19:28 +04:00
break ;
}
2012-08-11 08:56:58 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-08-08 06:19:28 +04:00
}
2012-08-09 07:44:58 +04:00
static void handle_hexedit_input ( struct hexedit * buf , int c )
{
switch ( c ) {
case KEY_UP :
hexedit_driver ( buf , HE_CURSOR_UP ) ;
break ;
case KEY_DOWN :
hexedit_driver ( buf , HE_CURSOR_DOWN ) ;
break ;
case KEY_LEFT :
hexedit_driver ( buf , HE_CURSOR_LEFT ) ;
break ;
case KEY_RIGHT :
hexedit_driver ( buf , HE_CURSOR_RIGHT ) ;
break ;
default :
hexedit_driver ( buf , c ) ;
break ;
}
hexedit_set_cursor ( buf ) ;
}
2012-08-08 10:41:50 +04:00
WERROR dialog_edit_value ( TALLOC_CTX * ctx , struct registry_key * key , uint32_t type ,
2012-08-11 08:56:58 +04:00
const struct value_item * vitem )
2012-08-07 06:11:13 +04:00
{
2012-08-08 06:19:28 +04:00
struct edit_dialog * edit ;
2012-08-07 06:11:13 +04:00
const char * choices [ ] = {
" Ok " ,
" Cancel " ,
2012-08-09 07:44:58 +04:00
" Resize " ,
2012-08-07 06:11:13 +04:00
NULL
} ;
2012-08-09 07:44:58 +04:00
# define DIALOG_RESIZE 2
2012-08-07 06:11:13 +04:00
char * title ;
2012-08-08 06:19:28 +04:00
int nlines , ncols , val_rows ;
2012-08-08 10:41:50 +04:00
WERROR rv = WERR_NOMEM ;
int selection ;
2012-08-08 06:19:28 +04:00
edit = talloc_zero ( ctx , struct edit_dialog ) ;
if ( edit = = NULL ) {
2012-08-08 10:41:50 +04:00
return rv ;
2012-08-08 06:19:28 +04:00
}
2012-08-08 10:41:50 +04:00
talloc_set_destructor ( edit , edit_dialog_free ) ;
2012-08-07 06:11:13 +04:00
2012-08-09 02:36:01 +04:00
title = talloc_asprintf ( edit , " Edit %s value " , str_regtype ( type ) ) ;
2012-08-07 06:11:13 +04:00
if ( title = = NULL ) {
2012-08-08 06:19:28 +04:00
goto finish ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
nlines = 9 ;
2012-08-09 02:36:01 +04:00
if ( type = = REG_MULTI_SZ ) {
2012-08-08 06:19:28 +04:00
nlines + = 4 ;
2012-08-09 07:44:58 +04:00
} else if ( type = = REG_BINARY ) {
nlines + = 10 ;
}
/* don't include a resize button */
if ( type ! = REG_BINARY ) {
choices [ 2 ] = NULL ;
2012-08-08 06:19:28 +04:00
}
2012-08-07 06:11:13 +04:00
ncols = 50 ;
2012-08-08 10:41:50 +04:00
edit - > dia = dialog_choice_center_new ( edit , title , choices , nlines ,
2012-08-11 08:56:58 +04:00
ncols ) ;
2012-08-08 10:41:50 +04:00
talloc_free ( title ) ;
2012-08-08 06:19:28 +04:00
if ( edit - > dia = = NULL ) {
2012-08-07 06:11:13 +04:00
goto finish ;
}
2012-08-08 06:19:28 +04:00
/* name */
edit - > field [ 0 ] = new_field ( 1 , ncols - 4 , 1 , 1 , 0 , 0 ) ;
2012-08-08 10:41:50 +04:00
if ( edit - > field [ 0 ] = = NULL ) {
goto finish ;
}
2012-08-07 06:11:13 +04:00
2012-08-08 06:19:28 +04:00
/* data */
2012-08-09 07:44:58 +04:00
if ( type = = REG_BINARY ) {
size_t len = 8 ;
const void * buf = NULL ;
if ( vitem ) {
len = vitem - > data . length ;
buf = vitem - > data . data ;
}
edit - > buf = hexedit_new ( edit , edit - > dia - > sub_window , 10 ,
5 , 0 , buf , len ) ;
if ( edit - > buf = = NULL ) {
goto finish ;
}
hexedit_refresh ( edit - > buf ) ;
hexedit_set_cursor ( edit - > buf ) ;
edit - > input_win = derwin ( edit - > dia - > sub_window , 2 ,
ncols - 3 , 0 , 0 ) ;
} else {
val_rows = 1 ;
if ( type = = REG_MULTI_SZ ) {
val_rows + = 4 ;
}
edit - > field [ 1 ] = new_field ( val_rows , ncols - 4 , 4 , 1 , 0 , 0 ) ;
if ( edit - > field [ 1 ] = = NULL ) {
goto finish ;
}
edit - > input_win = derwin ( edit - > dia - > sub_window , nlines - 3 ,
ncols - 3 , 0 , 0 ) ;
2012-08-08 06:19:28 +04:00
}
2012-08-09 07:44:58 +04:00
if ( edit - > input_win = = NULL ) {
2012-08-08 10:41:50 +04:00
goto finish ;
}
2012-08-09 07:44:58 +04:00
2012-08-08 06:19:28 +04:00
set_field_back ( edit - > field [ 0 ] , A_REVERSE ) ;
field_opts_off ( edit - > field [ 0 ] , O_BLANK | O_AUTOSKIP | O_STATIC ) ;
2012-08-09 07:44:58 +04:00
if ( edit - > field [ 1 ] ) {
set_field_back ( edit - > field [ 1 ] , A_REVERSE ) ;
field_opts_off ( edit - > field [ 1 ] , O_BLANK | O_AUTOSKIP | O_STATIC | O_WRAP ) ;
if ( type = = REG_DWORD ) {
set_field_type ( edit - > field [ 1 ] , TYPE_REGEXP ,
" ^ *([0-9]+|0[xX][0-9a-fA-F]+) *$ " ) ;
}
2012-08-09 02:36:01 +04:00
}
2012-08-07 06:11:13 +04:00
if ( vitem ) {
2012-08-08 06:19:28 +04:00
set_field_buffer ( edit - > field [ 0 ] , 0 , vitem - > value_name ) ;
field_opts_off ( edit - > field [ 0 ] , O_EDIT ) ;
fill_value_buffer ( edit , vitem ) ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
edit - > input = new_form ( edit - > field ) ;
2012-08-08 10:41:50 +04:00
if ( edit - > input = = NULL ) {
goto finish ;
}
2012-08-08 06:19:28 +04:00
form_opts_off ( edit - > input , O_NL_OVERLOAD | O_BS_OVERLOAD ) ;
2012-08-07 06:11:13 +04:00
2012-08-08 06:19:28 +04:00
set_form_win ( edit - > input , edit - > dia - > sub_window ) ;
set_form_sub ( edit - > input , edit - > input_win ) ;
post_form ( edit - > input ) ;
mvwprintw ( edit - > dia - > sub_window , 0 , 0 , " Name " ) ;
mvwprintw ( edit - > dia - > sub_window , 3 , 0 , " Data " ) ;
2012-08-07 06:11:13 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-08-08 06:19:28 +04:00
edit - > section = IN_NAME ;
2012-08-07 06:11:13 +04:00
while ( 1 ) {
2012-08-11 08:56:58 +04:00
int c = dialog_getch ( edit - > dia ) ;
2012-08-07 06:11:13 +04:00
if ( c = = ' \t ' ) {
2012-08-08 06:19:28 +04:00
section_down ( edit ) ;
continue ;
} else if ( c = = KEY_BTAB ) {
section_up ( edit ) ;
2012-08-07 06:11:13 +04:00
continue ;
}
2012-08-09 07:44:58 +04:00
if ( edit - > section = = IN_NAME ) {
2012-08-08 06:19:28 +04:00
handle_form_input ( edit - > input , c ) ;
2012-08-09 07:44:58 +04:00
} else if ( edit - > section = = IN_DATA ) {
if ( edit - > buf ) {
handle_hexedit_input ( edit - > buf , c ) ;
} else {
handle_form_input ( edit - > input , c ) ;
}
2012-08-07 06:11:13 +04:00
} else {
2012-08-08 10:41:50 +04:00
selection = handle_menu_input ( edit - > dia - > choices , c ) ;
2012-08-09 02:36:01 +04:00
if ( selection = = DIALOG_OK ) {
rv = set_value ( edit , key , type , vitem = = NULL ) ;
if ( W_ERROR_EQUAL ( rv , WERR_FILE_EXISTS ) ) {
dialog_notice ( edit , DIA_ALERT ,
2012-08-11 08:56:58 +04:00
" Value exists " ,
2012-08-09 02:36:01 +04:00
" Value name already exists. " ) ;
selection = - 1 ;
} else {
goto finish ;
}
2012-08-09 07:44:58 +04:00
} else if ( selection = = DIALOG_RESIZE ) {
char * n ;
size_t newlen = 0 ;
2012-08-11 08:56:58 +04:00
dialog_input ( edit , & n , " Resize buffer " ,
2012-08-09 07:44:58 +04:00
" Enter new size " ) ;
if ( n ) {
newlen = strtoul ( n , NULL , 10 ) ;
hexedit_resize_buffer ( edit - > buf , newlen ) ;
hexedit_refresh ( edit - > buf ) ;
talloc_free ( n ) ;
}
2012-08-09 02:36:01 +04:00
} else if ( selection = = DIALOG_CANCEL ) {
rv = WERR_OK ;
2012-08-07 06:11:13 +04:00
goto finish ;
}
}
update_panels ( ) ;
doupdate ( ) ;
}
finish :
2012-08-08 10:41:50 +04:00
talloc_free ( edit ) ;
2012-08-07 06:11:13 +04:00
return rv ;
2012-07-27 14:37:22 +04:00
}
2012-08-08 23:09:03 +04:00
2012-08-11 08:56:58 +04:00
int dialog_select_type ( TALLOC_CTX * ctx , int * type )
2012-08-08 23:09:03 +04:00
{
struct dialog * dia ;
const char * choices [ ] = {
" OK " ,
" Cancel " ,
NULL
} ;
const char * reg_types [ ] = {
" REG_DWORD " ,
" REG_SZ " ,
" REG_EXPAND_SZ " ,
" REG_MULTI_SZ " ,
2012-08-09 07:44:58 +04:00
" REG_BINARY " ,
2012-08-08 23:09:03 +04:00
} ;
# define NTYPES (sizeof(reg_types) / sizeof(const char*))
ITEM * * item ;
MENU * list ;
WINDOW * type_win ;
int sel = - 1 ;
size_t i ;
2012-08-11 08:56:58 +04:00
dia = dialog_choice_center_new ( ctx , " New Value " , choices , 10 , 20 ) ;
2012-08-08 23:09:03 +04:00
if ( dia = = NULL ) {
return - 1 ;
}
mvwprintw ( dia - > sub_window , 0 , 0 , " Choose type: " ) ;
type_win = derwin ( dia - > sub_window , 6 , 18 , 1 , 0 ) ;
if ( type_win = = NULL ) {
goto finish ;
}
item = talloc_zero_array ( dia , ITEM * , NTYPES + 1 ) ;
if ( item = = NULL ) {
goto finish ;
}
for ( i = 0 ; i < NTYPES ; + + i ) {
int t = regtype_by_string ( reg_types [ i ] ) ;
item [ i ] = new_item ( reg_types [ i ] , reg_types [ i ] ) ;
if ( item [ i ] = = NULL ) {
goto finish ;
}
set_item_userptr ( item [ i ] , ( void * ) ( uintptr_t ) t ) ;
}
list = new_menu ( item ) ;
if ( list = = NULL ) {
goto finish ;
}
set_menu_format ( list , 7 , 1 ) ;
set_menu_win ( list , dia - > sub_window ) ;
set_menu_sub ( list , type_win ) ;
menu_opts_off ( list , O_SHOWDESC ) ;
set_menu_mark ( list , " * " ) ;
post_menu ( list ) ;
update_panels ( ) ;
doupdate ( ) ;
while ( sel = = - 1 ) {
ITEM * it ;
2012-08-11 08:56:58 +04:00
int c = dialog_getch ( dia ) ;
2012-08-08 23:09:03 +04:00
switch ( c ) {
case KEY_UP :
menu_driver ( list , REQ_UP_ITEM ) ;
break ;
case KEY_DOWN :
menu_driver ( list , REQ_DOWN_ITEM ) ;
break ;
case KEY_LEFT :
menu_driver ( dia - > choices , REQ_LEFT_ITEM ) ;
break ;
case KEY_RIGHT :
menu_driver ( dia - > choices , REQ_RIGHT_ITEM ) ;
break ;
case ' \n ' :
case KEY_ENTER :
it = current_item ( list ) ;
* type = ( int ) ( uintptr_t ) item_userptr ( it ) ;
it = current_item ( dia - > choices ) ;
sel = ( int ) ( uintptr_t ) item_userptr ( it ) ;
break ;
}
2012-08-11 08:56:58 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-08-08 23:09:03 +04:00
}
finish :
if ( list ) {
unpost_menu ( list ) ;
free_menu ( list ) ;
}
if ( item ) {
ITEM * * it ;
for ( it = item ; * it ; + + it ) {
free_item ( * it ) ;
}
}
if ( type_win ) {
delwin ( type_win ) ;
}
talloc_free ( dia ) ;
return sel ;
}