2007-10-06 04:17:44 +04:00
/*
2005-09-29 16:00:49 +04:00
Unix SMB / CIFS implementation .
2007-08-26 19:16:40 +04:00
Reading registry patch files
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
Copyright ( C ) Jelmer Vernooij 2004 - 2007
Copyright ( C ) Wilco Baan Hofman 2006
2008-09-15 21:00:07 +04:00
Copyright ( C ) Matthias Dieter Wallnöfer 2008
2005-09-29 16:00:49 +04:00
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-09-29 16:00:49 +04:00
( at your option ) any later version .
2007-10-06 04:17:44 +04:00
2005-09-29 16:00:49 +04:00
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 .
2007-10-06 04:17:44 +04:00
2005-09-29 16:00:49 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-09-29 16:00:49 +04:00
*/
# include "includes.h"
# include "lib/registry/registry.h"
# include "system/filesys.h"
2007-10-06 04:17:44 +04:00
_PUBLIC_ WERROR reg_preg_diff_load ( int fd ,
2008-02-25 14:51:55 +03:00
struct smb_iconv_convenience * iconv_convenience ,
2007-10-06 04:17:44 +04:00
const struct reg_diff_callbacks * callbacks ,
void * callback_data ) ;
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
_PUBLIC_ WERROR reg_dotreg_diff_load ( int fd ,
2008-02-21 18:01:19 +03:00
struct smb_iconv_convenience * iconv_convenience ,
2007-10-06 04:17:44 +04:00
const struct reg_diff_callbacks * callbacks ,
void * callback_data ) ;
2005-09-29 16:00:49 +04:00
/*
* Generate difference between two keys
*/
2007-10-06 04:17:44 +04:00
WERROR reg_generate_diff_key ( struct registry_key * oldkey ,
struct registry_key * newkey ,
const char * path ,
const struct reg_diff_callbacks * callbacks ,
void * callback_data )
2005-09-29 16:00:49 +04:00
{
int i ;
2008-04-15 13:52:33 +04:00
struct registry_key * t1 = NULL , * t2 = NULL ;
2007-08-26 19:16:40 +04:00
char * tmppath ;
const char * keyname1 ;
WERROR error , error1 , error2 ;
2005-09-29 16:00:49 +04:00
TALLOC_CTX * mem_ctx = talloc_init ( " writediff " ) ;
2007-08-26 19:16:40 +04:00
uint32_t old_num_subkeys , old_num_values ,
new_num_subkeys , new_num_values ;
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
if ( oldkey ! = NULL ) {
2007-10-06 04:17:44 +04:00
error = reg_key_get_info ( mem_ctx , oldkey , NULL ,
& old_num_subkeys , & old_num_values ,
2008-01-07 23:11:29 +03:00
NULL , NULL , NULL , NULL ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting key info: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error ) ) ) ;
2008-09-15 21:00:07 +04:00
talloc_free ( mem_ctx ) ;
2007-08-26 19:16:40 +04:00
return error ;
}
} else {
old_num_subkeys = 0 ;
old_num_values = 0 ;
}
2005-09-29 16:00:49 +04:00
2008-10-03 16:29:47 +04:00
/* Subkeys that were changed or deleted */
2007-08-26 19:16:40 +04:00
for ( i = 0 ; i < old_num_subkeys ; i + + ) {
2007-10-06 04:17:44 +04:00
error1 = reg_key_get_subkey_by_index ( mem_ctx , oldkey , i ,
2008-09-15 21:00:07 +04:00
& keyname1 , NULL , NULL ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error1 ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting subkey by index: %s \n " ,
win_errstr ( error1 ) ) ) ;
2005-09-29 16:00:49 +04:00
continue ;
2007-08-26 19:16:40 +04:00
}
if ( newkey ! = NULL ) {
error2 = reg_open_key ( mem_ctx , newkey , keyname1 , & t2 ) ;
} else {
2008-01-18 05:37:06 +03:00
error2 = WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
t2 = NULL ;
}
2005-09-29 16:00:49 +04:00
2008-10-03 16:29:47 +04:00
if ( ! W_ERROR_IS_OK ( error2 ) & & ! W_ERROR_EQUAL ( error2 , WERR_BADFILE ) ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error occured while getting subkey by name: %s \n " ,
win_errstr ( error2 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
2005-09-29 16:00:49 +04:00
return error2 ;
}
2008-10-03 16:29:47 +04:00
/* if "error2" is going to be "WERR_BADFILE", then newkey */
/* didn't have such a subkey and therefore add a del diff */
2007-08-26 19:16:40 +04:00
tmppath = talloc_asprintf ( mem_ctx , " %s \\ %s " , path , keyname1 ) ;
2008-10-03 16:29:47 +04:00
if ( ! W_ERROR_IS_OK ( error2 ) )
callbacks - > del_key ( callback_data , tmppath ) ;
2008-09-15 21:00:07 +04:00
/* perform here also the recursive invocation */
error1 = reg_open_key ( mem_ctx , oldkey , keyname1 , & t1 ) ;
if ( ! W_ERROR_IS_OK ( error1 ) ) {
DEBUG ( 0 , ( " Error occured while getting subkey by name: %s \n " ,
win_errstr ( error1 ) ) ) ;
talloc_free ( mem_ctx ) ;
return error1 ;
}
reg_generate_diff_key ( t1 , t2 , tmppath , callbacks , callback_data ) ;
2007-10-06 04:17:44 +04:00
talloc_free ( tmppath ) ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
if ( newkey ! = NULL ) {
2007-10-06 04:17:44 +04:00
error = reg_key_get_info ( mem_ctx , newkey , NULL ,
& new_num_subkeys , & new_num_values ,
2008-01-07 23:11:29 +03:00
NULL , NULL , NULL , NULL ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting key info: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error ) ) ) ;
2008-09-15 21:00:07 +04:00
talloc_free ( mem_ctx ) ;
2007-08-26 19:16:40 +04:00
return error ;
}
} else {
new_num_subkeys = 0 ;
new_num_values = 0 ;
2005-09-29 16:00:49 +04:00
}
/* Subkeys that were added */
2007-08-26 19:16:40 +04:00
for ( i = 0 ; i < new_num_subkeys ; i + + ) {
2008-09-15 21:00:07 +04:00
error1 = reg_key_get_subkey_by_index ( mem_ctx , newkey , i ,
& keyname1 , NULL , NULL ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error1 ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting subkey by index: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error1 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
return error1 ;
}
if ( oldkey ! = NULL ) {
error2 = reg_open_key ( mem_ctx , oldkey , keyname1 , & t1 ) ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
if ( W_ERROR_IS_OK ( error2 ) )
continue ;
} else {
2008-09-15 21:00:07 +04:00
error2 = WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
t1 = NULL ;
}
2007-10-06 04:17:44 +04:00
2008-01-18 05:37:06 +03:00
if ( ! W_ERROR_EQUAL ( error2 , WERR_BADFILE ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting subkey by name: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error2 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
2005-09-29 16:00:49 +04:00
return error2 ;
}
/* oldkey didn't have such a subkey, add add diff */
2007-08-26 19:16:40 +04:00
tmppath = talloc_asprintf ( mem_ctx , " %s \\ %s " , path , keyname1 ) ;
callbacks - > add_key ( callback_data , tmppath ) ;
2005-09-29 16:00:49 +04:00
2008-09-15 21:00:07 +04:00
/* perform here also the recursive invocation */
error1 = reg_open_key ( mem_ctx , newkey , keyname1 , & t2 ) ;
if ( ! W_ERROR_IS_OK ( error1 ) ) {
DEBUG ( 0 , ( " Error occured while getting subkey by name: %s \n " ,
win_errstr ( error1 ) ) ) ;
talloc_free ( mem_ctx ) ;
return error1 ;
}
reg_generate_diff_key ( t1 , t2 , tmppath , callbacks , callback_data ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( tmppath ) ;
2005-09-29 16:00:49 +04:00
}
2008-09-15 21:00:07 +04:00
/* Values that were added or changed */
2007-08-26 19:16:40 +04:00
for ( i = 0 ; i < new_num_values ; i + + ) {
const char * name ;
uint32_t type1 , type2 ;
DATA_BLOB contents1 , contents2 ;
2007-10-06 04:17:44 +04:00
error1 = reg_key_get_value_by_index ( mem_ctx , newkey , i ,
& name , & type1 , & contents1 ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error1 ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Unable to get value by index: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error1 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
return error1 ;
}
if ( oldkey ! = NULL ) {
2007-10-06 04:17:44 +04:00
error2 = reg_key_get_value_by_name ( mem_ctx , oldkey ,
name , & type2 ,
& contents2 ) ;
} else
2008-01-18 04:45:00 +03:00
error2 = WERR_BADFILE ;
2007-10-06 04:17:44 +04:00
2008-09-15 21:00:07 +04:00
if ( ! W_ERROR_IS_OK ( error2 )
& & ! W_ERROR_EQUAL ( error2 , WERR_BADFILE ) ) {
DEBUG ( 0 , ( " Error occurred while getting value by name: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error2 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
2005-09-29 16:00:49 +04:00
return error2 ;
}
2008-09-15 21:00:07 +04:00
if ( W_ERROR_IS_OK ( error2 )
& & ( data_blob_cmp ( & contents1 , & contents2 ) = = 0 )
& & ( type1 = = type2 ) )
2005-09-29 16:00:49 +04:00
continue ;
2007-10-06 04:17:44 +04:00
callbacks - > set_value ( callback_data , path , name ,
type1 , contents1 ) ;
2005-09-29 16:00:49 +04:00
}
/* Values that were deleted */
2007-08-26 19:16:40 +04:00
for ( i = 0 ; i < old_num_values ; i + + ) {
const char * name ;
2008-09-15 21:00:07 +04:00
uint32_t type ;
DATA_BLOB contents ;
2007-10-06 04:17:44 +04:00
error1 = reg_key_get_value_by_index ( mem_ctx , oldkey , i , & name ,
2008-09-15 21:00:07 +04:00
& type , & contents ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error1 ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Unable to get value by index: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error1 ) ) ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( mem_ctx ) ;
return error1 ;
}
2008-09-15 21:00:07 +04:00
if ( newkey ! = NULL )
error2 = reg_key_get_value_by_name ( mem_ctx , newkey ,
name , & type , & contents ) ;
else
error2 = WERR_BADFILE ;
2005-09-29 16:00:49 +04:00
if ( W_ERROR_IS_OK ( error2 ) )
continue ;
2008-01-18 04:45:00 +03:00
if ( ! W_ERROR_EQUAL ( error2 , WERR_BADFILE ) ) {
2008-09-15 21:00:07 +04:00
DEBUG ( 0 , ( " Error occurred while getting value by name: %s \n " ,
2007-10-06 04:17:44 +04:00
win_errstr ( error2 ) ) ) ;
2008-09-15 21:00:07 +04:00
talloc_free ( mem_ctx ) ;
2005-09-29 16:00:49 +04:00
return error2 ;
}
2007-08-26 19:16:40 +04:00
callbacks - > del_value ( callback_data , path , name ) ;
2005-09-29 16:00:49 +04:00
}
talloc_free ( mem_ctx ) ;
return WERR_OK ;
}
2006-03-06 13:09:53 +03:00
/**
2007-10-06 04:17:44 +04:00
* Generate diff between two registry contexts
2005-09-29 16:00:49 +04:00
*/
2007-10-06 04:17:44 +04:00
_PUBLIC_ WERROR reg_generate_diff ( struct registry_context * ctx1 ,
struct registry_context * ctx2 ,
2007-08-26 19:16:40 +04:00
const struct reg_diff_callbacks * callbacks ,
void * callback_data )
2005-09-29 16:00:49 +04:00
{
int i ;
WERROR error ;
2008-09-15 21:00:07 +04:00
for ( i = 0 ; reg_predefined_keys [ i ] . name ; i + + ) {
2007-08-26 19:16:40 +04:00
struct registry_key * r1 = NULL , * r2 = NULL ;
2008-09-15 21:00:07 +04:00
error = reg_get_predefined_key ( ctx1 ,
reg_predefined_keys [ i ] . handle , & r1 ) ;
2007-10-06 04:17:44 +04:00
if ( ! W_ERROR_IS_OK ( error ) & &
2008-01-18 05:37:06 +03:00
! W_ERROR_EQUAL ( error , WERR_BADFILE ) ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Unable to open hive %s for backend 1 \n " ,
2008-09-15 21:00:07 +04:00
reg_predefined_keys [ i ] . name ) ) ;
continue ;
2005-09-29 16:00:49 +04:00
}
2007-10-06 04:17:44 +04:00
2008-09-15 21:00:07 +04:00
error = reg_get_predefined_key ( ctx2 ,
reg_predefined_keys [ i ] . handle , & r2 ) ;
2007-10-06 04:17:44 +04:00
if ( ! W_ERROR_IS_OK ( error ) & &
2008-01-18 05:37:06 +03:00
! W_ERROR_EQUAL ( error , WERR_BADFILE ) ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Unable to open hive %s for backend 2 \n " ,
2008-09-15 21:00:07 +04:00
reg_predefined_keys [ i ] . name ) ) ;
2005-09-29 16:00:49 +04:00
continue ;
2008-09-15 21:00:07 +04:00
}
2005-09-29 16:00:49 +04:00
2008-09-15 21:00:07 +04:00
error = reg_generate_diff_key ( r1 , r2 ,
reg_predefined_keys [ i ] . name , callbacks ,
callback_data ) ;
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error ) ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Unable to determine diff: %s \n " ,
win_errstr ( error ) ) ) ;
2007-08-26 19:16:40 +04:00
return error ;
2005-09-29 16:00:49 +04:00
}
}
2007-08-26 19:16:40 +04:00
if ( callbacks - > done ! = NULL ) {
callbacks - > done ( callback_data ) ;
}
2005-09-29 16:00:49 +04:00
return WERR_OK ;
}
2006-03-06 13:09:53 +03:00
/**
2005-09-29 16:00:49 +04:00
* Load diff file
*/
2007-10-06 04:17:44 +04:00
_PUBLIC_ WERROR reg_diff_load ( const char * filename ,
2008-02-21 20:09:47 +03:00
struct smb_iconv_convenience * iconv_convenience ,
2007-10-06 04:17:44 +04:00
const struct reg_diff_callbacks * callbacks ,
2007-09-07 17:31:15 +04:00
void * callback_data )
2005-09-29 16:00:49 +04:00
{
int fd ;
2007-08-26 19:16:40 +04:00
char hdr [ 4 ] ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
fd = open ( filename , O_RDONLY , 0 ) ;
2005-09-29 16:00:49 +04:00
if ( fd = = - 1 ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error opening registry patch file `%s' \n " ,
filename ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_GENERAL_FAILURE ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
if ( read ( fd , & hdr , 4 ) ! = 4 ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error reading registry patch file `%s' \n " ,
filename ) ) ;
2009-07-18 20:30:33 +04:00
close ( fd ) ;
2007-08-26 19:16:40 +04:00
return WERR_GENERAL_FAILURE ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
/* Reset position in file */
lseek ( fd , 0 , SEEK_SET ) ;
2008-04-15 13:52:33 +04:00
#if 0 /* These backends are not supported yet. */
2007-08-26 19:16:40 +04:00
if ( strncmp ( hdr , " CREG " , 4 ) = = 0 ) {
/* Must be a W9x CREG Config.pol file */
return reg_creg_diff_load ( diff , fd ) ;
} else if ( strncmp ( hdr , " regf " , 4 ) = = 0 ) {
/* Must be a REGF NTConfig.pol file */
return reg_regf_diff_load ( diff , fd ) ;
2007-10-06 04:17:44 +04:00
} else
# endif
2007-08-26 19:16:40 +04:00
if ( strncmp ( hdr , " PReg " , 4 ) = = 0 ) {
/* Must be a GPO Registry.pol file */
2008-02-25 14:51:55 +03:00
return reg_preg_diff_load ( fd , iconv_convenience , callbacks , callback_data ) ;
2007-08-26 19:16:40 +04:00
} else {
/* Must be a normal .REG file */
2008-02-21 20:09:47 +03:00
return reg_dotreg_diff_load ( fd , iconv_convenience , callbacks , callback_data ) ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
}
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
/**
* The reg_diff_apply functions
*/
2007-10-06 04:17:44 +04:00
static WERROR reg_diff_apply_add_key ( void * _ctx , const char * key_name )
2007-08-26 19:16:40 +04:00
{
2007-09-07 17:31:15 +04:00
struct registry_context * ctx = ( struct registry_context * ) _ctx ;
2007-08-26 19:16:40 +04:00
struct registry_key * tmp ;
2008-04-15 21:57:29 +04:00
char * buf , * buf_ptr ;
2007-08-26 19:16:40 +04:00
WERROR error ;
2005-09-29 16:00:49 +04:00
2008-04-15 21:57:29 +04:00
/* Recursively create the path */
buf = talloc_strdup ( ctx , key_name ) ;
buf_ptr = buf ;
while ( * buf_ptr + + ! = ' \0 ' ) {
if ( * buf_ptr = = ' \\ ' ) {
* buf_ptr = ' \0 ' ;
error = reg_key_add_abs ( ctx , ctx , buf , 0 , NULL , & tmp ) ;
if ( ! W_ERROR_EQUAL ( error , WERR_ALREADY_EXISTS ) & &
! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error adding new key '%s': %s \n " ,
key_name , win_errstr ( error ) ) ) ;
return error ;
}
* buf_ptr + + = ' \\ ' ;
}
}
/* Add the key */
2007-08-26 19:16:40 +04:00
error = reg_key_add_abs ( ctx , ctx , key_name , 0 , NULL , & tmp ) ;
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
if ( ! W_ERROR_EQUAL ( error , WERR_ALREADY_EXISTS ) & &
2008-04-15 21:57:29 +04:00
! W_ERROR_IS_OK ( error ) ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error adding new key '%s': %s \n " ,
key_name , win_errstr ( error ) ) ) ;
2007-08-26 19:16:40 +04:00
return error ;
}
return WERR_OK ;
}
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
static WERROR reg_diff_apply_del_key ( void * _ctx , const char * key_name )
2007-08-26 19:16:40 +04:00
{
2007-09-07 17:31:15 +04:00
struct registry_context * ctx = ( struct registry_context * ) _ctx ;
2005-09-29 16:00:49 +04:00
2008-10-03 16:29:47 +04:00
/* We can't proof here for success, because a common superkey could */
/* have been deleted before the subkey's (diff order). This removed */
/* therefore all childs recursively and the "WERR_BADFILE" result is */
/* expected. */
2005-09-29 16:00:49 +04:00
2008-10-03 16:29:47 +04:00
reg_key_del_abs ( ctx , key_name ) ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
static WERROR reg_diff_apply_set_value ( void * _ctx , const char * path ,
const char * value_name ,
uint32_t value_type , DATA_BLOB value )
2007-08-26 19:16:40 +04:00
{
2007-09-07 17:31:15 +04:00
struct registry_context * ctx = ( struct registry_context * ) _ctx ;
2007-08-26 19:16:40 +04:00
struct registry_key * tmp ;
WERROR error ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
/* Open key */
error = reg_open_key_abs ( ctx , ctx , path , & tmp ) ;
2005-09-29 16:00:49 +04:00
2008-01-18 05:37:06 +03:00
if ( W_ERROR_EQUAL ( error , WERR_BADFILE ) ) {
2007-08-26 19:16:40 +04:00
DEBUG ( 0 , ( " Error opening key '%s' \n " , path ) ) ;
return error ;
}
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
/* Set value */
2007-10-06 04:17:44 +04:00
error = reg_val_set ( tmp , value_name ,
2007-08-26 19:16:40 +04:00
value_type , value ) ;
if ( ! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error setting value '%s' \n " , value_name ) ) ;
return error ;
2007-10-06 04:17:44 +04:00
}
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
static WERROR reg_diff_apply_del_value ( void * _ctx , const char * key_name ,
const char * value_name )
2007-08-26 19:16:40 +04:00
{
2007-09-07 17:31:15 +04:00
struct registry_context * ctx = ( struct registry_context * ) _ctx ;
2007-08-26 19:16:40 +04:00
struct registry_key * tmp ;
WERROR error ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
/* Open key */
error = reg_open_key_abs ( ctx , ctx , key_name , & tmp ) ;
if ( ! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error opening key '%s' \n " , key_name ) ) ;
return error ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
error = reg_del_value ( tmp , value_name ) ;
if ( ! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error deleting value '%s' \n " , value_name ) ) ;
return error ;
}
2007-10-06 04:17:44 +04:00
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
return WERR_OK ;
2005-09-29 16:00:49 +04:00
}
2007-08-26 19:16:40 +04:00
static WERROR reg_diff_apply_del_all_values ( void * _ctx , const char * key_name )
2005-09-29 16:00:49 +04:00
{
2007-09-07 17:31:15 +04:00
struct registry_context * ctx = ( struct registry_context * ) _ctx ;
2007-08-26 19:16:40 +04:00
struct registry_key * key ;
2005-09-29 16:00:49 +04:00
WERROR error ;
2008-10-03 16:29:47 +04:00
const char * value_name ;
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
error = reg_open_key_abs ( ctx , ctx , key_name , & key ) ;
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
if ( ! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error opening key '%s' \n " , key_name ) ) ;
return error ;
}
2005-09-29 16:00:49 +04:00
2008-01-07 23:11:29 +03:00
W_ERROR_NOT_OK_RETURN ( reg_key_get_info ( ctx , key , NULL ,
2008-10-03 16:29:47 +04:00
NULL , NULL , NULL , NULL , NULL , NULL ) ) ;
2007-08-26 19:16:40 +04:00
2008-10-03 16:29:47 +04:00
while ( W_ERROR_IS_OK ( reg_key_get_value_by_index (
ctx , key , 0 , & value_name , NULL , NULL ) ) ) {
error = reg_del_value ( key , value_name ) ;
if ( ! W_ERROR_IS_OK ( error ) ) {
DEBUG ( 0 , ( " Error deleting value '%s' \n " , value_name ) ) ;
return error ;
}
2007-08-26 19:16:40 +04:00
}
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
2005-09-29 16:00:49 +04:00
2007-10-06 04:17:44 +04:00
/**
* Apply diff to a registry context
2007-08-26 19:16:40 +04:00
*/
2008-10-24 16:57:03 +04:00
_PUBLIC_ WERROR reg_diff_apply ( struct registry_context * ctx ,
struct smb_iconv_convenience * iconv_convenience ,
const char * filename )
2007-08-26 19:16:40 +04:00
{
struct reg_diff_callbacks callbacks ;
2005-09-29 16:00:49 +04:00
2007-08-26 19:16:40 +04:00
callbacks . add_key = reg_diff_apply_add_key ;
callbacks . del_key = reg_diff_apply_del_key ;
callbacks . set_value = reg_diff_apply_set_value ;
callbacks . del_value = reg_diff_apply_del_value ;
callbacks . del_all_values = reg_diff_apply_del_all_values ;
callbacks . done = NULL ;
2005-09-29 16:00:49 +04:00
2008-10-24 16:57:03 +04:00
return reg_diff_load ( filename , iconv_convenience ,
2008-02-21 20:09:47 +03:00
& callbacks , ctx ) ;
2005-09-29 16:00:49 +04:00
}