2012-07-06 14:08:17 +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"
2021-01-13 16:18:58 +03:00
# include "lib/cmdline/cmdline.h"
2023-08-07 07:17:28 +03:00
# include "lib/param/param.h"
2012-07-06 14:08:17 +04:00
# include "lib/util/data_blob.h"
# include "lib/registry/registry.h"
# include "regedit.h"
2012-07-13 08:11:55 +04:00
# include "regedit_treeview.h"
2012-07-18 13:31:41 +04:00
# include "regedit_valuelist.h"
2012-07-27 14:37:22 +04:00
# include "regedit_dialog.h"
2014-06-10 05:29:56 +04:00
# include "regedit_list.h"
2012-07-10 17:16:35 +04:00
# include <ncurses.h>
# include <menu.h>
2012-07-27 14:37:22 +04:00
# include <panel.h>
2012-08-11 07:05:20 +04:00
# define KEY_START_X 0
2014-05-21 03:17:42 +04:00
# define KEY_START_Y 1
2012-08-11 07:05:20 +04:00
# define KEY_WIDTH (COLS / 4)
2012-08-16 08:05:01 +04:00
# define KEY_HEIGHT (LINES - KEY_START_Y - 2)
2012-08-11 07:05:20 +04:00
# define VAL_START_X KEY_WIDTH
2014-05-21 03:17:42 +04:00
# define VAL_START_Y 1
2012-08-11 07:05:20 +04:00
# define VAL_WIDTH (COLS - KEY_WIDTH)
2012-08-16 08:05:01 +04:00
# define VAL_HEIGHT (LINES - VAL_START_Y - 2)
2014-05-21 03:17:42 +04:00
2012-08-16 08:05:01 +04:00
# define HELP1_START_Y (LINES - 2)
# define HELP1_START_X 0
# define HELP1_WIDTH (LINES)
# define HELP2_START_Y (LINES - 1)
# define HELP2_START_X 0
# define HELP2_WIDTH (LINES)
2012-08-12 09:10:51 +04:00
# define PATH_START_Y 0
# define PATH_START_X 6
2012-08-12 10:22:06 +04:00
# define PATH_MAX_Y (COLS - 1)
# define PATH_WIDTH (COLS - 6)
2012-08-12 09:10:51 +04:00
# define PATH_WIDTH_MAX 1024
2012-08-11 07:05:20 +04:00
2012-07-27 14:37:22 +04:00
struct regedit {
2014-07-01 10:14:20 +04:00
struct registry_context * registry_context ;
2012-07-27 14:37:22 +04:00
WINDOW * main_window ;
WINDOW * path_label ;
2012-08-12 10:22:06 +04:00
size_t path_len ;
2012-07-27 14:37:22 +04:00
struct value_list * vl ;
struct tree_view * keys ;
bool tree_input ;
2014-06-03 08:50:01 +04:00
struct regedit_search_opts active_search ;
2012-07-27 14:37:22 +04:00
} ;
2012-07-06 14:08:17 +04:00
2012-08-11 08:56:58 +04:00
static struct regedit * regedit_main = NULL ;
2012-08-12 09:10:51 +04:00
static void show_path ( struct regedit * regedit )
{
2012-08-12 10:22:06 +04:00
int start_pad = 0 ;
int start_win = PATH_START_X ;
if ( PATH_START_X + regedit - > path_len > COLS ) {
start_pad = 3 + PATH_START_X + regedit - > path_len - COLS ;
mvprintw ( PATH_START_Y , start_win , " ... " ) ;
start_win + = 3 ;
}
2012-08-12 10:29:13 +04:00
copywin ( regedit - > path_label , regedit - > main_window , 0 , start_pad ,
PATH_START_Y , start_win , PATH_START_Y , PATH_MAX_Y , false ) ;
2014-05-23 02:23:52 +04:00
mvchgat ( 0 , 0 , COLS , A_BOLD , PAIR_YELLOW_CYAN , NULL ) ;
2012-08-12 09:10:51 +04:00
}
static void print_path ( struct regedit * regedit , struct tree_node * node )
{
2012-08-12 10:22:06 +04:00
regedit - > path_len = tree_node_print_path ( regedit - > path_label , node ) ;
2012-08-12 10:29:13 +04:00
show_path ( regedit ) ;
2012-08-12 09:10:51 +04:00
}
2012-08-13 09:38:06 +04:00
static void print_help ( struct regedit * regedit )
{
const char * khelp = " [n] New Key [s] New Subkey [d] Del Key "
" [LEFT] Ascend [RIGHT] Descend " ;
2012-08-20 07:02:51 +04:00
const char * vhelp = " [n] New Value [d] Del Value [ENTER] Edit "
" [b] Edit binary " ;
2012-08-13 09:38:06 +04:00
const char * msg = " KEYS " ;
const char * help = khelp ;
2014-06-03 08:50:01 +04:00
const char * genhelp = " [TAB] Switch sections [q] Quit "
" [UP] List up [DOWN] List down "
" [/] Search [x] Next " ;
2012-08-13 09:38:06 +04:00
int i , pad ;
if ( ! regedit - > tree_input ) {
msg = " VALUES " ;
help = vhelp ;
}
2012-08-16 08:05:01 +04:00
move ( HELP1_START_Y , HELP1_START_X ) ;
2012-08-13 09:38:06 +04:00
clrtoeol ( ) ;
2014-05-23 02:23:52 +04:00
attron ( COLOR_PAIR ( PAIR_BLACK_CYAN ) ) ;
2012-08-16 08:05:01 +04:00
mvaddstr ( HELP1_START_Y , HELP1_START_X , help ) ;
2012-08-13 09:38:06 +04:00
pad = COLS - strlen ( msg ) - strlen ( help ) ;
for ( i = 0 ; i < pad ; + + i ) {
addch ( ' ' ) ;
}
2014-05-23 02:23:52 +04:00
attroff ( COLOR_PAIR ( PAIR_BLACK_CYAN ) ) ;
attron ( COLOR_PAIR ( PAIR_YELLOW_CYAN ) | A_BOLD ) ;
2012-08-16 07:50:00 +04:00
addstr ( msg ) ;
2014-05-23 02:23:52 +04:00
attroff ( COLOR_PAIR ( PAIR_YELLOW_CYAN ) | A_BOLD ) ;
2012-08-16 08:05:01 +04:00
move ( HELP2_START_Y , HELP2_START_X ) ;
clrtoeol ( ) ;
mvaddstr ( HELP2_START_Y , HELP2_START_X , genhelp ) ;
2012-08-13 09:38:06 +04:00
}
2012-08-11 07:05:20 +04:00
static void print_heading ( struct regedit * regedit )
2012-07-27 14:37:22 +04:00
{
2012-08-11 07:05:20 +04:00
if ( regedit - > tree_input ) {
2014-05-21 03:17:42 +04:00
tree_view_set_selected ( regedit - > keys , true ) ;
value_list_set_selected ( regedit - > vl , false ) ;
2012-07-27 14:37:22 +04:00
} else {
2014-05-21 03:17:42 +04:00
tree_view_set_selected ( regedit - > keys , false ) ;
value_list_set_selected ( regedit - > vl , true ) ;
2012-07-27 14:37:22 +04:00
}
2012-08-13 09:38:06 +04:00
print_help ( regedit ) ;
2012-07-27 14:37:22 +04:00
}
2012-08-20 05:29:06 +04:00
static void load_values ( struct regedit * regedit )
{
struct tree_node * node ;
2014-06-03 08:50:01 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2012-08-20 05:29:06 +04:00
value_list_load ( regedit - > vl , node - > key ) ;
}
2012-08-11 00:16:20 +04:00
static void add_reg_key ( struct regedit * regedit , struct tree_node * node ,
bool subkey )
{
2014-08-05 08:48:04 +04:00
const char * name ;
2012-08-11 00:16:20 +04:00
const char * msg ;
2014-07-01 10:19:53 +04:00
if ( ! subkey & & tree_node_is_top_level ( node ) ) {
2012-08-11 00:16:20 +04:00
return ;
}
msg = " Enter name of new key " ;
if ( subkey ) {
msg = " Enter name of new subkey " ;
}
2016-08-08 07:21:14 +03:00
dialog_input ( regedit , & name , " New Key " , " %s " , msg ) ;
2012-08-11 00:16:20 +04:00
if ( name ) {
WERROR rv ;
struct registry_key * new_key ;
2015-02-25 15:19:44 +03:00
struct tree_node * new_node = NULL ;
2012-08-11 00:16:20 +04:00
struct tree_node * list ;
struct tree_node * parent ;
if ( subkey ) {
parent = node ;
list = node - > child_head ;
} else {
parent = node - > parent ;
list = tree_node_first ( node ) ;
SMB_ASSERT ( list ! = NULL ) ;
}
rv = reg_key_add_name ( regedit , parent - > key , name ,
NULL , NULL , & new_key ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
/* The list of subkeys may not be present in
cache yet , so if not , don ' t bother allocating
a new node for the key . */
if ( list ) {
new_node = tree_node_new ( parent , parent ,
name , new_key ) ;
SMB_ASSERT ( new_node ) ;
2014-06-03 08:50:01 +04:00
tree_node_insert_sorted ( list , new_node ) ;
2014-06-28 05:01:36 +04:00
} else {
/* Reopen the parent key to make sure the
new subkey will be noticed . */
2014-07-28 04:39:06 +04:00
tree_node_reopen_key ( regedit - > registry_context ,
parent ) ;
2012-08-11 00:16:20 +04:00
}
list = tree_node_first ( node ) ;
tree_view_clear ( regedit - > keys ) ;
tree_view_update ( regedit - > keys , list ) ;
2014-06-26 18:51:22 +04:00
if ( ! subkey ) {
node = new_node ;
}
tree_view_set_current_node ( regedit - > keys , node ) ;
2014-07-28 04:48:05 +04:00
load_values ( regedit ) ;
2012-08-11 00:16:20 +04:00
} else {
2014-06-26 08:55:27 +04:00
msg = get_friendly_werror_msg ( rv ) ;
2012-08-11 00:16:20 +04:00
dialog_notice ( regedit , DIA_ALERT , " New Key " ,
2014-06-26 08:55:27 +04:00
" Failed to create key: %s " , msg ) ;
2012-08-11 00:16:20 +04:00
}
2014-08-05 08:48:04 +04:00
talloc_free ( discard_const ( name ) ) ;
2012-08-11 00:16:20 +04:00
}
}
2014-08-01 10:24:19 +04:00
enum search_flags {
SEARCH_NEXT = ( 1 < < 0 ) ,
SEARCH_PREV = ( 1 < < 1 ) ,
SEARCH_REPEAT = ( 1 < < 2 )
} ;
static WERROR regedit_search ( struct regedit * regedit , struct tree_node * node ,
struct value_item * vitem , unsigned flags )
2014-06-03 08:50:01 +04:00
{
struct regedit_search_opts * opts ;
struct tree_node * found ;
2014-08-01 10:24:19 +04:00
struct value_item * found_value ;
bool search_key , need_sync ;
char * save_value_name ;
2014-06-03 08:50:01 +04:00
WERROR rv ;
2014-08-03 04:29:31 +04:00
bool ( * iterate ) ( struct tree_node * * , bool , WERROR * ) ;
struct value_item * ( * find_item ) ( struct value_list * ,
struct value_item * ,
const char * ,
regedit_search_match_fn_t ) ;
2014-06-03 08:50:01 +04:00
opts = & regedit - > active_search ;
if ( ! opts - > query | | ! opts - > match ) {
return WERR_OK ;
}
SMB_ASSERT ( opts - > search_key | | opts - > search_value ) ;
2014-08-01 10:24:19 +04:00
rv = WERR_OK ;
found = NULL ;
found_value = NULL ;
save_value_name = NULL ;
search_key = opts - > search_key ;
need_sync = false ;
2014-08-03 04:29:31 +04:00
iterate = tree_node_next ;
find_item = value_list_find_next_item ;
if ( flags & SEARCH_PREV ) {
iterate = tree_node_prev ;
find_item = value_list_find_prev_item ;
}
2014-08-01 10:24:19 +04:00
if ( opts - > search_value ) {
struct value_item * it ;
it = value_list_get_current_item ( regedit - > vl ) ;
if ( it ) {
save_value_name = talloc_strdup ( regedit ,
it - > value_name ) ;
if ( save_value_name = = NULL ) {
2015-12-03 17:24:17 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2014-08-01 10:24:19 +04:00
}
}
if ( vitem ) {
search_key = false ;
2014-06-03 08:50:01 +04:00
}
2014-08-01 10:24:19 +04:00
}
if ( ! vitem & & ( flags & SEARCH_REPEAT ) ) {
2014-06-03 08:50:01 +04:00
if ( opts - > search_value ) {
2014-08-01 10:24:19 +04:00
search_key = false ;
2014-08-03 04:29:31 +04:00
} else if ( ! iterate ( & node , opts - > search_recursive , & rv ) ) {
2014-08-01 10:24:19 +04:00
beep ( ) ;
return rv ;
}
}
do {
if ( search_key ) {
SMB_ASSERT ( opts - > search_key = = true ) ;
if ( opts - > match ( node - > name , opts - > query ) ) {
found = node ;
} else if ( opts - > search_value ) {
search_key = false ;
2014-06-03 08:50:01 +04:00
}
}
2014-08-01 10:24:19 +04:00
if ( ! search_key ) {
SMB_ASSERT ( opts - > search_value = = true ) ;
if ( ! vitem ) {
rv = value_list_load_quick ( regedit - > vl ,
node - > key ) ;
if ( ! W_ERROR_IS_OK ( rv ) ) {
goto out ;
}
need_sync = true ;
}
2014-08-03 04:29:31 +04:00
found_value = find_item ( regedit - > vl , vitem , opts - > query ,
opts - > match ) ;
2014-08-01 10:24:19 +04:00
if ( found_value ) {
found = node ;
} else {
vitem = NULL ;
search_key = opts - > search_key ;
}
2014-06-03 08:50:01 +04:00
}
2014-08-03 04:29:31 +04:00
} while ( ! found & & iterate ( & node , opts - > search_recursive , & rv ) ) ;
2014-08-01 10:24:19 +04:00
if ( ! W_ERROR_IS_OK ( rv ) ) {
goto out ;
2014-06-03 08:50:01 +04:00
}
if ( found ) {
/* Put the cursor on the node that was found */
if ( ! tree_view_is_node_visible ( regedit - > keys , found ) ) {
tree_view_update ( regedit - > keys ,
tree_node_first ( found ) ) ;
print_path ( regedit , found ) ;
}
tree_view_set_current_node ( regedit - > keys , found ) ;
2014-08-01 10:24:19 +04:00
if ( found_value ) {
if ( need_sync ) {
value_list_sync ( regedit - > vl ) ;
}
value_list_set_current_item ( regedit - > vl , found_value ) ;
regedit - > tree_input = false ;
} else {
load_values ( regedit ) ;
regedit - > tree_input = true ;
}
2014-06-03 08:50:01 +04:00
tree_view_show ( regedit - > keys ) ;
value_list_show ( regedit - > vl ) ;
2014-08-01 10:24:19 +04:00
print_heading ( regedit ) ;
2014-06-03 08:50:01 +04:00
} else {
2014-08-01 10:24:19 +04:00
if ( need_sync ) {
load_values ( regedit ) ;
value_list_set_current_item_by_name ( regedit - > vl ,
save_value_name ) ;
}
2014-06-03 08:50:01 +04:00
beep ( ) ;
}
2014-08-01 10:24:19 +04:00
out :
talloc_free ( save_value_name ) ;
return rv ;
}
static void regedit_search_repeat ( struct regedit * regedit , unsigned flags )
{
struct tree_node * node ;
struct value_item * vitem ;
struct regedit_search_opts * opts ;
opts = & regedit - > active_search ;
if ( opts - > query = = NULL ) {
return ;
}
node = tree_view_get_current_node ( regedit - > keys ) ;
vitem = NULL ;
if ( opts - > search_value & & ! regedit - > tree_input ) {
vitem = value_list_get_current_item ( regedit - > vl ) ;
}
regedit_search ( regedit , node , vitem , flags | SEARCH_REPEAT ) ;
2014-06-03 08:50:01 +04:00
}
2012-07-27 14:37:22 +04:00
static void handle_tree_input ( struct regedit * regedit , int c )
2012-07-24 15:12:56 +04:00
{
struct tree_node * node ;
switch ( c ) {
case KEY_DOWN :
2014-06-10 05:29:56 +04:00
tree_view_driver ( regedit - > keys , ML_CURSOR_DOWN ) ;
2012-08-20 05:29:06 +04:00
load_values ( regedit ) ;
2012-07-24 15:12:56 +04:00
break ;
case KEY_UP :
2014-06-10 05:29:56 +04:00
tree_view_driver ( regedit - > keys , ML_CURSOR_UP ) ;
2012-08-20 05:29:06 +04:00
load_values ( regedit ) ;
2012-07-24 15:12:56 +04:00
break ;
2014-08-11 05:26:14 +04:00
case KEY_NPAGE :
tree_view_driver ( regedit - > keys , ML_CURSOR_PGDN ) ;
load_values ( regedit ) ;
break ;
case KEY_PPAGE :
tree_view_driver ( regedit - > keys , ML_CURSOR_PGUP ) ;
load_values ( regedit ) ;
break ;
case KEY_HOME :
tree_view_driver ( regedit - > keys , ML_CURSOR_HOME ) ;
load_values ( regedit ) ;
break ;
case KEY_END :
tree_view_driver ( regedit - > keys , ML_CURSOR_END ) ;
load_values ( regedit ) ;
break ;
2012-07-26 12:56:31 +04:00
case ' \n ' :
2012-07-24 15:12:56 +04:00
case KEY_ENTER :
case KEY_RIGHT :
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2012-07-24 15:12:56 +04:00
if ( node & & tree_node_has_children ( node ) ) {
2014-06-26 08:48:52 +04:00
WERROR rv ;
rv = tree_node_load_children ( node ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
print_path ( regedit , node - > child_head ) ;
tree_view_update ( regedit - > keys , node - > child_head ) ;
value_list_load ( regedit - > vl , node - > child_head - > key ) ;
} else {
2014-06-26 08:55:27 +04:00
const char * msg = get_friendly_werror_msg ( rv ) ;
2014-06-26 08:48:52 +04:00
dialog_notice ( regedit , DIA_ALERT , " Loading Subkeys " ,
2014-06-26 08:55:27 +04:00
" Failed to load subkeys: %s " , msg ) ;
2014-06-26 08:48:52 +04:00
}
2012-07-24 15:12:56 +04:00
}
break ;
case KEY_LEFT :
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2014-07-01 10:19:53 +04:00
if ( node & & ! tree_node_is_top_level ( node ) ) {
2012-08-12 09:10:51 +04:00
print_path ( regedit , node - > parent ) ;
2014-06-26 09:51:27 +04:00
node = node - > parent ;
tree_view_update ( regedit - > keys , tree_node_first ( node ) ) ;
tree_view_set_current_node ( regedit - > keys , node ) ;
2012-07-27 14:37:22 +04:00
value_list_load ( regedit - > vl , node - > key ) ;
2012-07-24 15:12:56 +04:00
}
break ;
2012-08-10 05:14:42 +04:00
case ' n ' :
2012-08-11 00:16:20 +04:00
case ' N ' :
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2012-08-11 00:16:20 +04:00
add_reg_key ( regedit , node , false ) ;
break ;
case ' s ' :
case ' S ' :
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2012-08-11 00:16:20 +04:00
add_reg_key ( regedit , node , true ) ;
2012-08-10 05:14:42 +04:00
break ;
2012-07-27 14:37:22 +04:00
case ' d ' :
2012-08-07 06:11:13 +04:00
case ' D ' : {
int sel ;
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2014-07-01 10:19:53 +04:00
if ( tree_node_is_top_level ( node ) ) {
2012-08-10 05:14:42 +04:00
break ;
}
2012-08-09 02:36:01 +04:00
sel = dialog_notice ( regedit , DIA_CONFIRM ,
" Delete Key " ,
" Really delete key \" %s \" ? " ,
node - > name ) ;
2012-08-10 05:14:42 +04:00
if ( sel = = DIALOG_OK ) {
WERROR rv ;
struct tree_node * pop ;
struct tree_node * parent = node - > parent ;
rv = reg_key_del ( node , parent - > key , node - > name ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
2014-07-28 04:39:06 +04:00
tree_node_reopen_key ( regedit - > registry_context ,
parent ) ;
2012-08-10 05:14:42 +04:00
tree_view_clear ( regedit - > keys ) ;
pop = tree_node_pop ( & node ) ;
2014-07-01 10:14:20 +04:00
talloc_free ( pop ) ;
2012-08-10 05:14:42 +04:00
node = parent - > child_head ;
if ( node = = NULL ) {
node = tree_node_first ( parent ) ;
2012-08-12 09:10:51 +04:00
print_path ( regedit , node ) ;
2012-08-10 05:14:42 +04:00
}
tree_view_update ( regedit - > keys , node ) ;
value_list_load ( regedit - > vl , node - > key ) ;
} else {
2014-06-26 08:55:27 +04:00
const char * msg = get_friendly_werror_msg ( rv ) ;
2012-08-10 05:14:42 +04:00
dialog_notice ( regedit , DIA_ALERT , " Delete Key " ,
2014-06-26 08:55:27 +04:00
" Failed to delete key: %s " , msg ) ;
2012-08-10 05:14:42 +04:00
}
}
2012-07-27 14:37:22 +04:00
break ;
2012-07-24 15:12:56 +04:00
}
2012-08-07 06:11:13 +04:00
}
2012-07-27 14:37:22 +04:00
tree_view_show ( regedit - > keys ) ;
value_list_show ( regedit - > vl ) ;
2012-07-24 15:12:56 +04:00
}
2012-07-27 14:37:22 +04:00
static void handle_value_input ( struct regedit * regedit , int c )
2012-07-24 15:12:56 +04:00
{
2012-07-27 14:37:22 +04:00
struct value_item * vitem ;
2012-08-20 07:02:51 +04:00
bool binmode = false ;
2014-07-27 06:49:33 +04:00
WERROR err ;
int sel ;
2012-07-27 14:37:22 +04:00
2012-07-24 15:12:56 +04:00
switch ( c ) {
case KEY_DOWN :
2014-06-10 21:35:19 +04:00
value_list_driver ( regedit - > vl , ML_CURSOR_DOWN ) ;
2012-07-24 15:12:56 +04:00
break ;
case KEY_UP :
2014-06-10 21:35:19 +04:00
value_list_driver ( regedit - > vl , ML_CURSOR_UP ) ;
2012-07-27 14:37:22 +04:00
break ;
2014-08-11 05:26:14 +04:00
case KEY_NPAGE :
value_list_driver ( regedit - > vl , ML_CURSOR_PGDN ) ;
break ;
case KEY_PPAGE :
value_list_driver ( regedit - > vl , ML_CURSOR_PGUP ) ;
break ;
case KEY_HOME :
value_list_driver ( regedit - > vl , ML_CURSOR_HOME ) ;
break ;
case KEY_END :
value_list_driver ( regedit - > vl , ML_CURSOR_END ) ;
break ;
2012-08-20 07:02:51 +04:00
case ' b ' :
case ' B ' :
binmode = true ;
2017-07-26 18:55:35 +03:00
FALL_THROUGH ;
2012-08-07 06:11:13 +04:00
case ' \n ' :
2012-07-27 14:37:22 +04:00
case KEY_ENTER :
2014-06-10 21:35:19 +04:00
vitem = value_list_get_current_item ( regedit - > vl ) ;
2012-08-07 06:11:13 +04:00
if ( vitem ) {
struct tree_node * node ;
2014-07-27 06:49:33 +04:00
const char * name = NULL ;
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2014-07-27 06:49:33 +04:00
sel = dialog_edit_value ( regedit , node - > key , vitem - > type ,
vitem , binmode , & err , & name ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
const char * msg = get_friendly_werror_msg ( err ) ;
dialog_notice ( regedit , DIA_ALERT , " Error " ,
" Error editing value: \n %s " , msg ) ;
} else if ( sel = = DIALOG_OK ) {
2014-07-28 04:39:06 +04:00
tree_node_reopen_key ( regedit - > registry_context ,
node ) ;
2014-07-27 06:49:33 +04:00
value_list_load ( regedit - > vl , node - > key ) ;
value_list_set_current_item_by_name ( regedit - > vl ,
name ) ;
talloc_free ( discard_const ( name ) ) ;
}
2012-08-07 06:11:13 +04:00
}
2012-07-24 15:12:56 +04:00
break ;
2012-08-08 23:09:03 +04:00
case ' n ' :
case ' N ' : {
int new_type ;
2012-08-11 08:56:58 +04:00
sel = dialog_select_type ( regedit , & new_type ) ;
2012-08-09 01:16:41 +04:00
if ( sel = = DIALOG_OK ) {
struct tree_node * node ;
2014-07-27 06:49:33 +04:00
const char * name = NULL ;
2014-06-10 05:29:56 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
2014-07-27 06:49:33 +04:00
sel = dialog_edit_value ( regedit , node - > key , new_type ,
NULL , false , & err , & name ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
const char * msg = get_friendly_werror_msg ( err ) ;
dialog_notice ( regedit , DIA_ALERT , " Error " ,
" Error creating value: \n %s " , msg ) ;
} else if ( sel = = DIALOG_OK ) {
2014-07-28 04:39:06 +04:00
tree_node_reopen_key ( regedit - > registry_context ,
node ) ;
2014-07-27 06:49:33 +04:00
value_list_load ( regedit - > vl , node - > key ) ;
value_list_set_current_item_by_name ( regedit - > vl ,
name ) ;
talloc_free ( discard_const ( name ) ) ;
}
2012-08-08 23:09:03 +04:00
}
break ;
}
2012-07-27 14:37:22 +04:00
case ' d ' :
case ' D ' :
2014-06-10 21:35:19 +04:00
vitem = value_list_get_current_item ( regedit - > vl ) ;
2012-07-27 14:37:22 +04:00
if ( vitem ) {
2012-08-09 02:36:01 +04:00
sel = dialog_notice ( regedit , DIA_CONFIRM ,
" Delete Value " ,
" Really delete value \" %s \" ? " ,
vitem - > value_name ) ;
2012-08-09 01:16:41 +04:00
if ( sel = = DIALOG_OK ) {
2014-06-10 05:29:56 +04:00
struct tree_node * node ;
node = tree_view_get_current_node ( regedit - > keys ) ;
2012-08-09 01:16:41 +04:00
reg_del_value ( regedit , node - > key ,
vitem - > value_name ) ;
2014-07-28 04:39:06 +04:00
tree_node_reopen_key ( regedit - > registry_context ,
node ) ;
2012-08-09 01:16:41 +04:00
value_list_load ( regedit - > vl , node - > key ) ;
}
2012-07-27 14:37:22 +04:00
}
break ;
}
value_list_show ( regedit - > vl ) ;
}
2014-06-03 08:50:01 +04:00
static bool find_substring ( const char * haystack , const char * needle )
{
return strstr ( haystack , needle ) ! = NULL ;
}
static bool find_substring_nocase ( const char * haystack , const char * needle )
{
return strcasestr ( haystack , needle ) ! = NULL ;
}
2012-07-27 14:37:22 +04:00
static void handle_main_input ( struct regedit * regedit , int c )
2012-07-24 15:12:56 +04:00
{
2012-07-27 14:37:22 +04:00
switch ( c ) {
2014-07-01 10:14:20 +04:00
case 18 : { /* CTRL-R */
struct tree_node * root , * node ;
const char * * path ;
node = tree_view_get_current_node ( regedit - > keys ) ;
path = tree_node_get_path ( regedit , node ) ;
2014-07-01 10:19:53 +04:00
SMB_ASSERT ( path ! = NULL ) ;
root = tree_node_new_root ( regedit , regedit - > registry_context ) ;
SMB_ASSERT ( root ! = NULL ) ;
2014-07-01 10:14:20 +04:00
tree_view_set_root ( regedit - > keys , root ) ;
tree_view_set_path ( regedit - > keys , path ) ;
node = tree_view_get_current_node ( regedit - > keys ) ;
value_list_load ( regedit - > vl , node - > key ) ;
tree_view_show ( regedit - > keys ) ;
value_list_show ( regedit - > vl ) ;
print_path ( regedit , node ) ;
talloc_free ( discard_const ( path ) ) ;
break ;
}
2014-06-03 08:50:01 +04:00
case ' f ' :
case ' F ' :
case ' / ' : {
int rv ;
struct regedit_search_opts * opts ;
2014-08-01 10:24:19 +04:00
struct tree_node * node ;
2014-06-03 08:50:01 +04:00
opts = & regedit - > active_search ;
rv = dialog_search_input ( regedit , opts ) ;
if ( rv = = DIALOG_OK ) {
SMB_ASSERT ( opts - > query ! = NULL ) ;
2014-07-31 09:04:50 +04:00
opts - > match = find_substring_nocase ;
2014-08-03 04:29:31 +04:00
node = regedit - > keys - > root - > child_head ;
2014-07-31 09:04:50 +04:00
if ( opts - > search_case ) {
opts - > match = find_substring ;
2014-06-03 08:50:01 +04:00
}
2014-07-31 09:04:50 +04:00
if ( ! opts - > search_recursive ) {
2014-08-01 10:24:19 +04:00
node = tree_view_get_current_node ( regedit - > keys ) ;
node = tree_node_first ( node ) ;
2014-06-03 08:50:01 +04:00
}
2014-08-01 10:24:19 +04:00
regedit_search ( regedit , node , NULL , SEARCH_NEXT ) ;
2014-06-03 08:50:01 +04:00
}
break ;
}
case ' x ' :
2014-08-01 10:24:19 +04:00
regedit_search_repeat ( regedit , SEARCH_NEXT ) ;
2014-06-03 08:50:01 +04:00
break ;
2014-08-03 04:29:31 +04:00
case ' X ' :
regedit_search_repeat ( regedit , SEARCH_PREV ) ;
break ;
2012-07-27 14:37:22 +04:00
case ' \t ' :
regedit - > tree_input = ! regedit - > tree_input ;
2012-08-11 07:05:20 +04:00
print_heading ( regedit ) ;
2012-07-27 14:37:22 +04:00
break ;
default :
if ( regedit - > tree_input ) {
handle_tree_input ( regedit , c ) ;
} else {
handle_value_input ( regedit , c ) ;
}
2012-07-24 15:12:56 +04:00
}
}
2012-08-11 08:56:58 +04:00
int regedit_getch ( void )
{
int c ;
SMB_ASSERT ( regedit_main ) ;
c = getch ( ) ;
if ( c = = KEY_RESIZE ) {
tree_view_resize ( regedit_main - > keys , KEY_HEIGHT , KEY_WIDTH ,
KEY_START_Y , KEY_START_X ) ;
value_list_resize ( regedit_main - > vl , VAL_HEIGHT , VAL_WIDTH ,
VAL_START_Y , VAL_START_X ) ;
print_heading ( regedit_main ) ;
2012-08-12 10:29:13 +04:00
show_path ( regedit_main ) ;
2012-08-11 08:56:58 +04:00
}
return c ;
}
2014-07-02 03:00:16 +04:00
static void regedit_panic_handler ( const char * msg )
{
endwin ( ) ;
2020-02-26 02:02:36 +03:00
smb_panic_log ( msg ) ;
2014-07-02 03:00:16 +04:00
smb_panic_s3 ( msg ) ;
}
2012-08-11 08:56:58 +04:00
static void display_window ( TALLOC_CTX * mem_ctx , struct registry_context * ctx )
2012-07-13 08:11:55 +04:00
{
2012-07-27 14:37:22 +04:00
struct regedit * regedit ;
2012-07-24 15:12:56 +04:00
struct tree_node * root ;
2012-10-26 21:52:08 +04:00
bool colors ;
2012-10-26 21:21:50 +04:00
int key ;
2012-07-13 08:11:55 +04:00
initscr ( ) ;
2012-10-26 21:52:08 +04:00
2012-07-13 08:11:55 +04:00
cbreak ( ) ;
noecho ( ) ;
2014-07-02 03:00:16 +04:00
fault_configure ( regedit_panic_handler ) ;
2012-10-26 21:52:08 +04:00
colors = has_colors ( ) ;
if ( colors ) {
start_color ( ) ;
use_default_colors ( ) ;
2014-05-19 22:08:09 +04:00
assume_default_colors ( COLOR_WHITE , COLOR_BLUE ) ;
2014-05-23 02:23:52 +04:00
init_pair ( PAIR_YELLOW_CYAN , COLOR_YELLOW , COLOR_CYAN ) ;
init_pair ( PAIR_BLACK_CYAN , COLOR_BLACK , COLOR_CYAN ) ;
2014-06-10 05:29:56 +04:00
init_pair ( PAIR_YELLOW_BLUE , COLOR_YELLOW , COLOR_BLUE ) ;
2012-10-26 21:52:08 +04:00
}
2012-07-27 14:37:22 +04:00
regedit = talloc_zero ( mem_ctx , struct regedit ) ;
SMB_ASSERT ( regedit ! = NULL ) ;
2012-08-11 08:56:58 +04:00
regedit_main = regedit ;
2012-07-27 14:37:22 +04:00
2014-07-01 10:14:20 +04:00
regedit - > registry_context = ctx ;
2012-08-11 07:05:20 +04:00
regedit - > main_window = stdscr ;
2012-07-27 14:37:22 +04:00
keypad ( regedit - > main_window , TRUE ) ;
2012-07-13 08:11:55 +04:00
2012-07-27 14:37:22 +04:00
mvwprintw ( regedit - > main_window , 0 , 0 , " Path: " ) ;
2012-08-12 09:10:51 +04:00
regedit - > path_label = newpad ( 1 , PATH_WIDTH_MAX ) ;
SMB_ASSERT ( regedit - > path_label ) ;
2012-07-27 14:37:22 +04:00
wprintw ( regedit - > path_label , " / " ) ;
2012-08-12 10:29:13 +04:00
show_path ( regedit_main ) ;
2012-07-14 04:16:51 +04:00
2014-07-01 10:19:53 +04:00
root = tree_node_new_root ( regedit , ctx ) ;
2012-07-13 08:11:55 +04:00
SMB_ASSERT ( root ! = NULL ) ;
2012-08-11 07:05:20 +04:00
regedit - > keys = tree_view_new ( regedit , root , KEY_HEIGHT , KEY_WIDTH ,
KEY_START_Y , KEY_START_X ) ;
2012-07-27 14:37:22 +04:00
SMB_ASSERT ( regedit - > keys ! = NULL ) ;
2012-08-11 07:05:20 +04:00
regedit - > vl = value_list_new ( regedit , VAL_HEIGHT , VAL_WIDTH ,
VAL_START_Y , VAL_START_X ) ;
2012-07-27 14:37:22 +04:00
SMB_ASSERT ( regedit - > vl ! = NULL ) ;
regedit - > tree_input = true ;
2012-08-11 07:05:20 +04:00
print_heading ( regedit ) ;
2012-07-27 14:37:22 +04:00
tree_view_show ( regedit - > keys ) ;
2012-08-20 05:29:06 +04:00
load_values ( regedit ) ;
2012-07-27 14:37:22 +04:00
value_list_show ( regedit - > vl ) ;
update_panels ( ) ;
doupdate ( ) ;
2012-10-26 21:21:50 +04:00
do {
key = regedit_getch ( ) ;
handle_main_input ( regedit , key ) ;
2012-07-27 14:37:22 +04:00
update_panels ( ) ;
doupdate ( ) ;
2016-03-09 17:25:26 +03:00
} while ( key ! = ' q ' & & key ! = ' Q ' ) ;
2012-07-13 08:11:55 +04:00
endwin ( ) ;
}
2021-01-13 16:18:58 +03:00
int main ( int argc , char * * argv )
2012-07-06 14:08:17 +04:00
{
2021-01-13 16:18:58 +03:00
const char * * argv_const = discard_const_p ( const char * , argv ) ;
2012-07-06 14:08:17 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
/* ... */
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
2021-01-13 16:18:58 +03:00
POPT_COMMON_VERSION
2012-07-06 14:08:17 +04:00
POPT_TABLEEND
} ;
int opt ;
poptContext pc ;
TALLOC_CTX * frame ;
struct registry_context * ctx ;
WERROR rv ;
2021-01-13 16:18:58 +03:00
bool ok ;
2023-08-07 07:17:28 +03:00
struct loadparm_context * lp_ctx = NULL ;
2012-07-06 14:08:17 +04:00
frame = talloc_stackframe ( ) ;
2021-01-13 16:18:58 +03:00
smb_init_locale ( ) ;
ok = samba_cmdline_init ( frame ,
SAMBA_CMDLINE_CONFIG_CLIENT ,
false /* require_smbconf */ ) ;
if ( ! ok ) {
DBG_ERR ( " Failed to init cmdline parser! \n " ) ;
TALLOC_FREE ( frame ) ;
exit ( 1 ) ;
}
2023-08-07 07:17:28 +03:00
lp_ctx = samba_cmdline_get_lp_ctx ( ) ;
lpcfg_set_cmdline ( lp_ctx , " log level " , " 0 " ) ;
2012-07-06 14:08:17 +04:00
/* process options */
2021-01-13 16:18:58 +03:00
pc = samba_popt_get_context ( getprogname ( ) ,
argc ,
argv_const ,
long_options ,
0 ) ;
if ( pc = = NULL ) {
DBG_ERR ( " Failed to setup popt context! \n " ) ;
TALLOC_FREE ( frame ) ;
exit ( 1 ) ;
}
2012-07-06 14:08:17 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
2021-09-10 08:10:39 +03:00
switch ( opt ) {
case POPT_ERROR_BADOPT :
fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
}
2012-07-06 14:08:17 +04:00
}
2021-01-13 16:18:58 +03:00
poptFreeContext ( pc ) ;
samba_cmdline_burn ( argc , argv ) ;
2012-07-06 14:08:17 +04:00
rv = reg_open_samba3 ( frame , & ctx ) ;
2012-08-02 14:41:49 +04:00
if ( ! W_ERROR_IS_OK ( rv ) ) {
2014-08-07 17:17:28 +04:00
fprintf ( stderr , " Unable to open registry: %s \n " ,
win_errstr ( rv ) ) ;
2012-08-02 14:41:49 +04:00
TALLOC_FREE ( frame ) ;
return 1 ;
}
2012-07-06 14:08:17 +04:00
2012-08-11 08:56:58 +04:00
display_window ( frame , ctx ) ;
2012-07-06 14:08:17 +04:00
2023-10-24 12:59:35 +03:00
gfree_all ( ) ;
2012-07-06 14:08:17 +04:00
TALLOC_FREE ( frame ) ;
return 0 ;
}