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"
# include "popt_common.h"
# 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"
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>
struct regedit {
WINDOW * main_window ;
PANEL * main_panel ;
WINDOW * path_label ;
WINDOW * key_label ;
WINDOW * value_label ;
struct value_list * vl ;
struct tree_view * keys ;
bool tree_input ;
} ;
2012-07-06 14:08:17 +04:00
2012-07-14 04:07:44 +04:00
/* load all available hives */
static struct tree_node * load_hives ( TALLOC_CTX * mem_ctx ,
struct registry_context * ctx )
{
const char * hives [ ] = {
" HKEY_CLASSES_ROOT " ,
" HKEY_CURRENT_USER " ,
" HKEY_LOCAL_MACHINE " ,
" HKEY_PERFORMANCE_DATA " ,
" HKEY_USERS " ,
" HKEY_CURRENT_CONFIG " ,
" HKEY_DYN_DATA " ,
" HKEY_PERFORMANCE_TEXT " ,
" HKEY_PERFORMANCE_NLSTEXT " ,
NULL
} ;
struct tree_node * root , * prev , * node ;
struct registry_key * key ;
WERROR rv ;
size_t i ;
root = NULL ;
prev = NULL ;
for ( i = 0 ; hives [ i ] ! = NULL ; + + i ) {
rv = reg_get_predefined_key_by_name ( ctx , hives [ i ] , & key ) ;
if ( ! W_ERROR_IS_OK ( rv ) ) {
2012-07-18 13:31:41 +04:00
continue ;
2012-07-14 04:07:44 +04:00
}
node = tree_node_new ( mem_ctx , NULL , hives [ i ] , key ) ;
if ( node = = NULL ) {
return NULL ;
}
if ( root = = NULL ) {
root = node ;
}
if ( prev ) {
tree_node_append ( prev , node ) ;
}
prev = node ;
}
return root ;
}
2012-07-27 14:37:22 +04:00
static void print_heading ( WINDOW * win , bool selected , const char * str )
{
if ( selected ) {
wattron ( win , A_REVERSE ) ;
} else {
wattroff ( win , A_REVERSE ) ;
}
wmove ( win , 0 , 0 ) ;
wclrtoeol ( win ) ;
waddstr ( win , str ) ;
wnoutrefresh ( win ) ;
wrefresh ( win ) ;
}
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 :
2012-07-27 14:37:22 +04:00
menu_driver ( regedit - > keys - > menu , REQ_DOWN_ITEM ) ;
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
value_list_load ( regedit - > vl , node - > key ) ;
2012-07-24 15:12:56 +04:00
break ;
case KEY_UP :
2012-07-27 14:37:22 +04:00
menu_driver ( regedit - > keys - > menu , REQ_UP_ITEM ) ;
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
value_list_load ( regedit - > vl , node - > key ) ;
2012-07-24 15:12:56 +04:00
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 :
2012-07-27 14:37:22 +04:00
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
2012-07-24 15:12:56 +04:00
if ( node & & tree_node_has_children ( node ) ) {
tree_node_load_children ( node ) ;
2012-07-27 14:37:22 +04:00
tree_node_print_path ( regedit - > path_label ,
node - > child_head ) ;
tree_view_update ( regedit - > keys , node - > child_head ) ;
value_list_load ( regedit - > vl , node - > child_head - > key ) ;
2012-07-24 15:12:56 +04:00
}
break ;
case KEY_LEFT :
2012-07-27 14:37:22 +04:00
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
2012-07-24 15:12:56 +04:00
if ( node & & node - > parent ) {
2012-07-27 14:37:22 +04:00
tree_node_print_path ( regedit - > path_label , node - > parent ) ;
2012-07-24 15:12:56 +04:00
node = tree_node_first ( node - > parent ) ;
2012-07-27 14:37:22 +04:00
tree_view_update ( regedit - > keys , node ) ;
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 ' :
case ' N ' : {
char * name ;
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
if ( ! node - > parent ) {
break ;
}
dialog_input ( regedit , & name , " New Key " , regedit - > main_window ,
" Enter name of new key " ) ;
if ( name ) {
WERROR rv ;
struct registry_key * new_key ;
struct tree_node * new_node ;
struct tree_node * list = tree_node_first ( node ) ;
rv = reg_key_add_name ( regedit , node - > parent - > key , name ,
NULL , NULL , & new_key ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
new_node = tree_node_new ( node - > parent ,
node - > parent ,
name , new_key ) ;
SMB_ASSERT ( new_node ) ;
tree_node_append_last ( list , new_node ) ;
tree_view_clear ( regedit - > keys ) ;
tree_view_update ( regedit - > keys , list ) ;
} else {
dialog_notice ( regedit , DIA_ALERT , " New Key " ,
regedit - > main_window ,
" Failed to create key. " ) ;
}
talloc_free ( name ) ;
}
break ;
}
2012-07-27 14:37:22 +04:00
case ' d ' :
2012-08-07 06:11:13 +04:00
case ' D ' : {
int sel ;
2012-07-27 14:37:22 +04:00
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
2012-08-10 05:14:42 +04:00
if ( ! node - > parent ) {
break ;
}
2012-08-09 02:36:01 +04:00
sel = dialog_notice ( regedit , DIA_CONFIRM ,
" Delete Key " ,
regedit - > main_window ,
" 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 ) ) {
tree_view_clear ( regedit - > keys ) ;
pop = tree_node_pop ( & node ) ;
tree_node_free_recursive ( pop ) ;
node = parent - > child_head ;
if ( node = = NULL ) {
node = tree_node_first ( parent ) ;
}
tree_view_update ( regedit - > keys , node ) ;
value_list_load ( regedit - > vl , node - > key ) ;
} else {
dialog_notice ( regedit , DIA_ALERT , " Delete Key " ,
regedit - > main_window ,
" Failed to delete key. " ) ;
}
}
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-07-24 15:12:56 +04:00
switch ( c ) {
case KEY_DOWN :
2012-07-27 14:37:22 +04:00
menu_driver ( regedit - > vl - > menu , REQ_DOWN_ITEM ) ;
2012-07-24 15:12:56 +04:00
break ;
case KEY_UP :
2012-07-27 14:37:22 +04:00
menu_driver ( regedit - > vl - > menu , REQ_UP_ITEM ) ;
break ;
2012-08-07 06:11:13 +04:00
case ' \n ' :
2012-07-27 14:37:22 +04:00
case KEY_ENTER :
2012-08-07 06:11:13 +04:00
vitem = item_userptr ( current_item ( regedit - > vl - > menu ) ) ;
if ( vitem ) {
struct tree_node * node ;
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
2012-08-08 10:41:50 +04:00
dialog_edit_value ( regedit , node - > key , vitem - > type ,
vitem , regedit - > main_window ) ;
value_list_load ( regedit - > vl , node - > key ) ;
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-09 01:16:41 +04:00
int sel ;
2012-08-08 23:09:03 +04:00
2012-08-09 01:16:41 +04:00
sel = dialog_select_type ( regedit , & new_type ,
regedit - > main_window ) ;
if ( sel = = DIALOG_OK ) {
struct tree_node * node ;
node = item_userptr ( current_item ( regedit - > keys - > menu ) ) ;
dialog_edit_value ( regedit , node - > key , new_type , NULL ,
regedit - > main_window ) ;
value_list_load ( regedit - > vl , node - > key ) ;
2012-08-08 23:09:03 +04:00
}
break ;
}
2012-07-27 14:37:22 +04:00
case ' d ' :
case ' D ' :
vitem = item_userptr ( current_item ( regedit - > vl - > menu ) ) ;
if ( vitem ) {
2012-08-07 06:11:13 +04:00
int sel ;
2012-08-09 02:36:01 +04:00
sel = dialog_notice ( regedit , DIA_CONFIRM ,
" Delete Value " ,
regedit - > main_window ,
" Really delete value \" %s \" ? " ,
vitem - > value_name ) ;
2012-08-09 01:16:41 +04:00
if ( sel = = DIALOG_OK ) {
ITEM * it = current_item ( regedit - > keys - > menu ) ;
struct tree_node * node = item_userptr ( it ) ;
reg_del_value ( regedit , node - > key ,
vitem - > value_name ) ;
value_list_load ( regedit - > vl , node - > key ) ;
}
2012-07-27 14:37:22 +04:00
}
break ;
}
value_list_show ( regedit - > vl ) ;
}
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 ) {
case ' \t ' :
regedit - > tree_input = ! regedit - > tree_input ;
print_heading ( regedit - > key_label , regedit - > tree_input = = true ,
" Keys " ) ;
print_heading ( regedit - > value_label , regedit - > tree_input = = false ,
" Values " ) ;
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-07-14 04:07:44 +04:00
/* test navigating available hives */
static void display_test_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-07-13 08:11:55 +04:00
int c ;
initscr ( ) ;
start_color ( ) ;
cbreak ( ) ;
noecho ( ) ;
keypad ( stdscr , TRUE ) ;
2012-07-27 14:37:22 +04:00
regedit = talloc_zero ( mem_ctx , struct regedit ) ;
SMB_ASSERT ( regedit ! = NULL ) ;
regedit - > main_window = newwin ( 25 , 80 , 0 , 0 ) ;
SMB_ASSERT ( regedit - > main_window ! = NULL ) ;
2012-07-13 08:11:55 +04:00
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: " ) ;
regedit - > path_label = derwin ( regedit - > main_window , 1 , 65 , 0 , 6 ) ;
wprintw ( regedit - > path_label , " / " ) ;
2012-07-14 04:16:51 +04:00
2012-07-27 14:37:22 +04:00
root = load_hives ( regedit , ctx ) ;
2012-07-13 08:11:55 +04:00
SMB_ASSERT ( root ! = NULL ) ;
2012-07-27 14:37:22 +04:00
regedit - > key_label = derwin ( regedit - > main_window , 1 , 10 , 2 , 0 ) ;
regedit - > value_label = derwin ( regedit - > main_window , 1 , 10 , 2 , 25 ) ;
print_heading ( regedit - > key_label , true , " Keys " ) ;
regedit - > keys = tree_view_new ( regedit , root , regedit - > main_window ,
15 , 24 , 3 , 0 ) ;
SMB_ASSERT ( regedit - > keys ! = NULL ) ;
print_heading ( regedit - > value_label , false , " Values " ) ;
regedit - > vl = value_list_new ( regedit , regedit - > main_window ,
15 , 40 , 3 , 25 ) ;
SMB_ASSERT ( regedit - > vl ! = NULL ) ;
regedit - > tree_input = true ;
tree_view_show ( regedit - > keys ) ;
value_list_show ( regedit - > vl ) ;
regedit - > main_panel = new_panel ( regedit - > main_window ) ;
SMB_ASSERT ( regedit - > main_panel ! = NULL ) ;
update_panels ( ) ;
doupdate ( ) ;
while ( ( c = wgetch ( regedit - > main_window ) ) ! = ' q ' ) {
2012-08-07 06:11:13 +04:00
handle_main_input ( regedit , c ) ;
2012-07-27 14:37:22 +04:00
update_panels ( ) ;
doupdate ( ) ;
2012-07-13 08:11:55 +04:00
}
endwin ( ) ;
}
2012-07-06 14:08:17 +04:00
int main ( int argc , char * * argv )
{
struct poptOption long_options [ ] = {
POPT_AUTOHELP
/* ... */
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
POPT_TABLEEND
} ;
int opt ;
poptContext pc ;
struct user_auth_info * auth_info ;
TALLOC_CTX * frame ;
struct registry_context * ctx ;
WERROR rv ;
2012-07-13 08:11:55 +04:00
talloc_enable_leak_report_full ( ) ;
2012-07-10 17:16:35 +04:00
2012-07-06 14:08:17 +04:00
frame = talloc_stackframe ( ) ;
setup_logging ( " regedit " , DEBUG_DEFAULT_STDERR ) ;
lp_set_cmdline ( " log level " , " 0 " ) ;
/* process options */
auth_info = user_auth_info_init ( frame ) ;
if ( auth_info = = NULL ) {
exit ( 1 ) ;
}
popt_common_set_auth_info ( auth_info ) ;
pc = poptGetContext ( " regedit " , argc , ( const char * * ) argv , long_options , 0 ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
/* TODO */
}
2012-07-13 12:57:02 +04:00
if ( ! lp_load_global ( get_dyn_CONFIGFILE ( ) ) ) {
DEBUG ( 0 , ( " ERROR loading config file... \n " ) ) ;
exit ( 1 ) ;
}
2012-07-06 14:08:17 +04:00
/* some simple tests */
rv = reg_open_samba3 ( frame , & ctx ) ;
2012-08-02 14:41:49 +04:00
if ( ! W_ERROR_IS_OK ( rv ) ) {
TALLOC_FREE ( frame ) ;
return 1 ;
}
2012-07-06 14:08:17 +04:00
2012-07-13 08:11:55 +04:00
display_test_window ( frame , ctx ) ;
2012-07-06 14:08:17 +04:00
2012-07-13 08:11:55 +04:00
//talloc_report_full(frame, stdout);
2012-07-06 14:08:17 +04:00
TALLOC_FREE ( frame ) ;
return 0 ;
}