2008-01-15 16:55:04 +03:00
/*
2006-12-01 23:01:09 +03:00
* Unix SMB / CIFS implementation .
* Virtual Windows Registry Layer
* Copyright ( C ) Volker Lendecke 2006
2010-09-21 09:44:56 +04:00
* Copyright ( C ) Michael Adam 2007 - 2010
2006-12-01 23:01:09 +03: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-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2006-12-01 23:01:09 +03:00
* ( at your option ) any later version .
2008-01-15 16:55:04 +03:00
*
2006-12-01 23:01:09 +03: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 .
2008-01-15 16:55:04 +03:00
*
2006-12-01 23:01:09 +03:00
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-12-01 23:01:09 +03:00
*/
/* Attempt to wrap the existing API in a more winreg.idl-like way */
2008-01-17 13:07:28 +03:00
/*
* Here is a list of winreg . idl functions and corresponding implementations
* provided here :
*
* 0x00 winreg_OpenHKCR
* 0x01 winreg_OpenHKCU
* 0x02 winreg_OpenHKLM
* 0x03 winreg_OpenHKPD
* 0x04 winreg_OpenHKU
* 0x05 winreg_CloseKey
* 0x06 winreg_CreateKey reg_createkey
* 0x07 winreg_DeleteKey reg_deletekey
* 0x08 winreg_DeleteValue reg_deletevalue
* 0x09 winreg_EnumKey reg_enumkey
* 0x0a winreg_EnumValue reg_enumvalue
* 0x0b winreg_FlushKey
* 0x0c winreg_GetKeySecurity reg_getkeysecurity
* 0x0d winreg_LoadKey
* 0x0e winreg_NotifyChangeKeyValue
* 0x0f winreg_OpenKey reg_openkey
* 0x10 winreg_QueryInfoKey reg_queryinfokey
* 0x11 winreg_QueryValue reg_queryvalue
* 0x12 winreg_ReplaceKey
2008-02-15 17:31:31 +03:00
* 0x13 winreg_RestoreKey reg_restorekey
2008-02-15 17:14:20 +03:00
* 0x14 winreg_SaveKey reg_savekey
2008-01-17 13:07:28 +03:00
* 0x15 winreg_SetKeySecurity reg_setkeysecurity
* 0x16 winreg_SetValue reg_setvalue
* 0x17 winreg_UnLoadKey
* 0x18 winreg_InitiateSystemShutdown
* 0x19 winreg_AbortSystemShutdown
2008-01-17 13:22:01 +03:00
* 0x1a winreg_GetVersion reg_getversion
2008-01-17 13:07:28 +03:00
* 0x1b winreg_OpenHKCC
* 0x1c winreg_OpenHKDD
2010-09-20 03:51:54 +04:00
* 0x1d winreg_QueryMultipleValues reg_querymultiplevalues
2008-01-17 13:07:28 +03:00
* 0x1e winreg_InitiateSystemShutdownEx
* 0x1f winreg_SaveKeyEx
* 0x20 winreg_OpenHKPT
* 0x21 winreg_OpenHKPN
2010-09-20 03:51:54 +04:00
* 0x22 winreg_QueryMultipleValues2 reg_querymultiplevalues
2008-01-17 13:07:28 +03:00
*
*/
2006-12-01 23:01:09 +03:00
# include "includes.h"
2009-10-02 02:17:06 +04:00
# include "registry.h"
2010-09-21 10:11:18 +04:00
# include "reg_api.h"
2010-05-23 17:25:00 +04:00
# include "reg_cachehook.h"
2010-05-25 00:42:00 +04:00
# include "reg_backend_db.h"
2010-05-25 00:49:42 +04:00
# include "reg_dispatcher.h"
2010-05-25 03:00:37 +04:00
# include "reg_objects.h"
2010-05-28 04:19:32 +04:00
# include "../librpc/gen_ndr/ndr_security.h"
2013-03-20 16:00:26 +04:00
# include "reg_parse_internal.h"
2006-12-01 23:01:09 +03:00
2007-09-29 03:05:52 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_REGISTRY
2008-01-17 02:57:53 +03:00
/**********************************************************************
* Helper functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-12-01 23:01:09 +03:00
static WERROR fill_value_cache ( struct registry_key * key )
{
2010-05-24 01:56:40 +04:00
WERROR werr ;
2006-12-01 23:01:09 +03:00
if ( key - > values ! = NULL ) {
2008-01-14 20:31:11 +03:00
if ( ! reg_values_need_update ( key - > key , key - > values ) ) {
return WERR_OK ;
}
2006-12-01 23:01:09 +03:00
}
2012-04-12 10:18:04 +04:00
TALLOC_FREE ( key - > values ) ;
2010-05-24 01:56:40 +04:00
werr = regval_ctr_init ( key , & ( key - > values ) ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
2006-12-01 23:01:09 +03:00
if ( fetch_reg_values ( key - > key , key - > values ) = = - 1 ) {
TALLOC_FREE ( key - > values ) ;
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2006-12-01 23:01:09 +03:00
}
return WERR_OK ;
}
static WERROR fill_subkey_cache ( struct registry_key * key )
{
2009-02-25 01:17:05 +03:00
WERROR werr ;
2006-12-01 23:01:09 +03:00
if ( key - > subkeys ! = NULL ) {
2008-01-14 20:31:11 +03:00
if ( ! reg_subkeys_need_update ( key - > key , key - > subkeys ) ) {
return WERR_OK ;
}
2006-12-01 23:01:09 +03:00
}
2011-07-14 14:19:01 +04:00
TALLOC_FREE ( key - > subkeys ) ;
2009-02-25 01:17:05 +03:00
werr = regsubkey_ctr_init ( key , & ( key - > subkeys ) ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
2006-12-01 23:01:09 +03:00
if ( fetch_reg_keys ( key - > key , key - > subkeys ) = = - 1 ) {
TALLOC_FREE ( key - > subkeys ) ;
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2006-12-01 23:01:09 +03:00
}
return WERR_OK ;
}
2009-03-24 01:02:57 +03:00
static int regkey_destructor ( struct registry_key_handle * key )
2007-06-22 15:03:48 +04:00
{
return regdb_close ( ) ;
}
static WERROR regkey_open_onelevel ( TALLOC_CTX * mem_ctx ,
struct registry_key * parent ,
const char * name ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2015-04-14 17:50:28 +03:00
uint32_t access_desired ,
2007-06-22 15:03:48 +04:00
struct registry_key * * pregkey )
{
2019-07-10 14:26:06 +03:00
WERROR result ;
2007-06-22 15:03:48 +04:00
struct registry_key * regkey ;
2009-03-24 01:02:57 +03:00
struct registry_key_handle * key ;
2007-06-22 15:03:48 +04:00
DEBUG ( 7 , ( " regkey_open_onelevel: name = [%s] \n " , name ) ) ;
SMB_ASSERT ( strchr ( name , ' \\ ' ) = = NULL ) ;
2011-06-07 05:44:43 +04:00
if ( ! ( regkey = talloc_zero ( mem_ctx , struct registry_key ) ) | |
2023-09-15 01:08:01 +03:00
! ( regkey - > token = security_token_duplicate ( regkey , token ) ) | |
2011-06-07 05:44:43 +04:00
! ( regkey - > key = talloc_zero ( regkey , struct registry_key_handle ) ) )
2009-03-24 01:02:57 +03:00
{
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2007-06-22 15:03:48 +04:00
goto done ;
}
2012-04-23 17:29:41 +04:00
result = regdb_open ( ) ;
if ( ! ( W_ERROR_IS_OK ( result ) ) ) {
2007-06-22 15:03:48 +04:00
goto done ;
}
key = regkey - > key ;
talloc_set_destructor ( key , regkey_destructor ) ;
2010-02-07 13:05:07 +03:00
2007-06-22 15:03:48 +04:00
/* initialization */
2010-02-07 13:05:07 +03:00
2007-06-22 15:03:48 +04:00
key - > type = REG_KEY_GENERIC ;
if ( name [ 0 ] = = ' \0 ' ) {
/*
* Open a copy of the parent key
*/
if ( ! parent ) {
2015-12-03 17:24:11 +03:00
result = WERR_FILE_NOT_FOUND ;
2007-06-22 15:03:48 +04:00
goto done ;
}
key - > name = talloc_strdup ( key , parent - > key - > name ) ;
}
else {
/*
* Normal subkey open
*/
key - > name = talloc_asprintf ( key , " %s%s%s " ,
parent ? parent - > key - > name : " " ,
parent ? " \\ " : " " ,
name ) ;
}
if ( key - > name = = NULL ) {
2015-12-03 17:24:14 +03:00
result = WERR_NOT_ENOUGH_MEMORY ;
2007-06-22 15:03:48 +04:00
goto done ;
}
/* Tag this as a Performance Counter Key */
2011-05-13 22:23:36 +04:00
if ( strncasecmp_m ( key - > name , KEY_HKPD , strlen ( KEY_HKPD ) ) = = 0 )
2007-06-22 15:03:48 +04:00
key - > type = REG_KEY_HKPD ;
2010-02-07 13:05:07 +03:00
2007-06-22 15:03:48 +04:00
/* Look up the table of registry I/O operations */
2012-04-23 17:30:38 +04:00
key - > ops = reghook_cache_find ( key - > name ) ;
if ( key - > ops = = NULL ) {
2008-04-13 02:54:44 +04:00
DEBUG ( 0 , ( " reg_open_onelevel: Failed to assign "
2009-03-24 01:14:45 +03:00
" registry_ops to [%s] \n " , key - > name ) ) ;
2015-12-03 17:24:11 +03:00
result = WERR_FILE_NOT_FOUND ;
2007-06-22 15:03:48 +04:00
goto done ;
}
2008-01-15 16:55:04 +03:00
2012-04-23 18:07:21 +04:00
/* FIXME: Existence is currently checked by fetching the subkeys */
2007-06-22 15:03:48 +04:00
2012-04-23 18:07:21 +04:00
result = fill_subkey_cache ( regkey ) ;
2009-02-25 01:17:05 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
2007-06-22 15:03:48 +04:00
goto done ;
}
if ( ! regkey_access_check ( key , access_desired , & key - > access_granted ,
token ) ) {
result = WERR_ACCESS_DENIED ;
goto done ;
}
* pregkey = regkey ;
result = WERR_OK ;
2010-02-07 13:05:07 +03:00
2007-06-22 15:03:48 +04:00
done :
if ( ! W_ERROR_IS_OK ( result ) ) {
TALLOC_FREE ( regkey ) ;
}
return result ;
}
2006-12-01 23:01:09 +03:00
WERROR reg_openhive ( TALLOC_CTX * mem_ctx , const char * hive ,
2015-04-14 17:50:28 +03:00
uint32_t desired_access ,
2010-08-26 14:04:11 +04:00
const struct security_token * token ,
2006-12-01 23:01:09 +03:00
struct registry_key * * pkey )
{
2013-03-20 16:00:26 +04:00
const struct hive_info * hi ;
2006-12-05 10:36:14 +03:00
SMB_ASSERT ( hive ! = NULL ) ;
2006-12-01 23:01:09 +03:00
SMB_ASSERT ( strchr ( hive , ' \\ ' ) = = NULL ) ;
2013-03-20 16:00:26 +04:00
hi = hive_info ( hive ) ;
if ( hi = = NULL ) {
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2013-03-20 16:00:26 +04:00
}
return regkey_open_onelevel ( mem_ctx , NULL , hi - > short_name , token ,
desired_access , pkey ) ;
2006-12-01 23:01:09 +03:00
}
2008-01-17 02:57:53 +03:00
/**********************************************************************
* The API functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-12-01 23:01:09 +03:00
WERROR reg_openkey ( TALLOC_CTX * mem_ctx , struct registry_key * parent ,
2015-04-14 17:50:28 +03:00
const char * name , uint32_t desired_access ,
2006-12-01 23:01:09 +03:00
struct registry_key * * pkey )
{
2006-12-05 10:36:14 +03:00
struct registry_key * direct_parent = parent ;
2006-12-01 23:01:09 +03:00
WERROR err ;
2012-04-23 17:47:33 +04:00
char * p , * path ;
2006-12-05 10:36:14 +03:00
size_t len ;
2012-04-23 17:47:33 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2006-12-01 23:01:09 +03:00
2012-04-23 17:47:33 +04:00
path = talloc_strdup ( frame , name ) ;
if ( path = = NULL ) {
2015-12-03 17:24:14 +03:00
err = WERR_NOT_ENOUGH_MEMORY ;
2012-04-23 17:47:33 +04:00
goto error ;
2006-12-01 23:01:09 +03:00
}
2006-12-05 10:36:14 +03:00
len = strlen ( path ) ;
2006-12-01 23:01:09 +03:00
2006-12-05 10:36:14 +03:00
if ( ( len > 0 ) & & ( path [ len - 1 ] = = ' \\ ' ) ) {
path [ len - 1 ] = ' \0 ' ;
2006-12-01 23:01:09 +03:00
}
2006-12-05 10:36:14 +03:00
while ( ( p = strchr ( path , ' \\ ' ) ) ! = NULL ) {
char * name_component ;
struct registry_key * tmp ;
2006-12-01 23:01:09 +03:00
2012-04-23 17:47:33 +04:00
name_component = talloc_strndup ( frame , path , ( p - path ) ) ;
if ( name_component = = NULL ) {
2015-12-03 17:24:14 +03:00
err = WERR_NOT_ENOUGH_MEMORY ;
2006-12-05 10:36:14 +03:00
goto error ;
}
2006-12-01 23:01:09 +03:00
2012-04-23 17:47:33 +04:00
err = regkey_open_onelevel ( frame , direct_parent ,
2006-12-05 10:36:14 +03:00
name_component , parent - > token ,
2009-04-15 03:30:12 +04:00
KEY_ENUMERATE_SUB_KEYS , & tmp ) ;
2006-12-05 10:36:14 +03:00
if ( ! W_ERROR_IS_OK ( err ) ) {
goto error ;
}
direct_parent = tmp ;
path = p + 1 ;
2006-12-01 23:01:09 +03:00
}
2006-12-05 10:36:14 +03:00
err = regkey_open_onelevel ( mem_ctx , direct_parent , path , parent - > token ,
desired_access , pkey ) ;
2012-04-23 17:47:33 +04:00
error :
talloc_free ( frame ) ;
2006-12-05 10:36:14 +03:00
return err ;
2006-12-01 23:01:09 +03:00
}
WERROR reg_enumkey ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
2015-04-14 17:50:28 +03:00
uint32_t idx , char * * name , NTTIME * last_write_time )
2006-12-01 23:01:09 +03:00
{
WERROR err ;
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_ENUMERATE_SUB_KEYS ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
2012-07-03 16:42:46 +04:00
err = fill_subkey_cache ( key ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
2006-12-01 23:01:09 +03:00
return err ;
}
2009-02-24 19:30:23 +03:00
if ( idx > = regsubkey_ctr_numkeys ( key - > subkeys ) ) {
2006-12-01 23:01:09 +03:00
return WERR_NO_MORE_ITEMS ;
}
2009-02-24 23:12:26 +03:00
if ( ! ( * name = talloc_strdup ( mem_ctx ,
regsubkey_ctr_specific_key ( key - > subkeys , idx ) ) ) )
{
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-01 23:01:09 +03:00
}
if ( last_write_time ) {
* last_write_time = 0 ;
}
return WERR_OK ;
}
WERROR reg_enumvalue ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
2015-04-14 17:50:28 +03:00
uint32_t idx , char * * pname , struct registry_value * * pval )
2006-12-01 23:01:09 +03:00
{
struct registry_value * val ;
2010-05-24 01:56:40 +04:00
struct regval_blob * blob ;
2006-12-01 23:01:09 +03:00
WERROR err ;
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_QUERY_VALUE ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
2012-07-03 16:42:12 +04:00
err = fill_value_cache ( key ) ;
if ( ! ( W_ERROR_IS_OK ( err ) ) ) {
2006-12-01 23:01:09 +03:00
return err ;
}
2010-05-24 01:56:40 +04:00
if ( idx > = regval_ctr_numvals ( key - > values ) ) {
2007-04-24 04:12:28 +04:00
return WERR_NO_MORE_ITEMS ;
2006-12-01 23:01:09 +03:00
}
2010-05-24 01:56:40 +04:00
blob = regval_ctr_specific_value ( key - > values , idx ) ;
2010-06-29 18:13:15 +04:00
val = talloc_zero ( mem_ctx , struct registry_value ) ;
if ( val = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-01 23:01:09 +03:00
}
2010-06-29 18:13:15 +04:00
val - > type = regval_type ( blob ) ;
val - > data = data_blob_talloc ( mem_ctx , regval_data_p ( blob ) , regval_size ( blob ) ) ;
2006-12-01 23:01:09 +03:00
if ( pname
& & ! ( * pname = talloc_strdup (
2010-05-24 01:56:40 +04:00
mem_ctx , regval_name ( blob ) ) ) ) {
2010-07-01 03:22:11 +04:00
TALLOC_FREE ( val ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-01 23:01:09 +03:00
}
2008-01-15 16:55:04 +03:00
2006-12-01 23:01:09 +03:00
* pval = val ;
return WERR_OK ;
}
2012-03-30 02:10:14 +04:00
static WERROR reg_enumvalue_nocachefill ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
2015-04-14 17:50:28 +03:00
uint32_t idx , char * * pname ,
2012-03-30 02:10:14 +04:00
struct registry_value * * pval )
{
struct registry_value * val ;
struct regval_blob * blob ;
if ( ! ( key - > key - > access_granted & KEY_QUERY_VALUE ) ) {
return WERR_ACCESS_DENIED ;
}
if ( idx > = regval_ctr_numvals ( key - > values ) ) {
return WERR_NO_MORE_ITEMS ;
}
blob = regval_ctr_specific_value ( key - > values , idx ) ;
val = talloc_zero ( mem_ctx , struct registry_value ) ;
if ( val = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2012-03-30 02:10:14 +04:00
}
val - > type = regval_type ( blob ) ;
val - > data = data_blob_talloc ( mem_ctx , regval_data_p ( blob ) , regval_size ( blob ) ) ;
if ( pname
& & ! ( * pname = talloc_strdup (
mem_ctx , regval_name ( blob ) ) ) ) {
TALLOC_FREE ( val ) ;
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2012-03-30 02:10:14 +04:00
}
* pval = val ;
return WERR_OK ;
}
2006-12-01 23:01:09 +03:00
WERROR reg_queryvalue ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
const char * name , struct registry_value * * pval )
{
WERROR err ;
2015-04-14 17:50:28 +03:00
uint32_t i ;
2006-12-01 23:01:09 +03:00
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_QUERY_VALUE ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
if ( ! ( W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) ) {
return err ;
}
2010-05-24 01:56:40 +04:00
for ( i = 0 ; i < regval_ctr_numvals ( key - > values ) ; i + + ) {
struct regval_blob * blob ;
blob = regval_ctr_specific_value ( key - > values , i ) ;
if ( strequal ( regval_name ( blob ) , name ) ) {
2012-03-30 02:10:14 +04:00
/*
* don ' t use reg_enumvalue here :
* re - reading the values from the disk
* would change the indexing and break
* this function .
*/
return reg_enumvalue_nocachefill ( mem_ctx , key , i ,
NULL , pval ) ;
2006-12-01 23:01:09 +03:00
}
}
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2006-12-01 23:01:09 +03:00
}
2010-06-30 04:02:43 +04:00
WERROR reg_querymultiplevalues ( TALLOC_CTX * mem_ctx ,
struct registry_key * key ,
uint32_t num_names ,
const char * * names ,
uint32_t * pnum_vals ,
struct registry_value * * pvals )
{
WERROR err ;
uint32_t i , n , found = 0 ;
struct registry_value * vals ;
if ( num_names = = 0 ) {
return WERR_OK ;
}
if ( ! ( key - > key - > access_granted & KEY_QUERY_VALUE ) ) {
return WERR_ACCESS_DENIED ;
}
if ( ! ( W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) ) {
return err ;
}
vals = talloc_zero_array ( mem_ctx , struct registry_value , num_names ) ;
if ( vals = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-06-30 04:02:43 +04:00
}
for ( n = 0 ; n < num_names ; n + + ) {
for ( i = 0 ; i < regval_ctr_numvals ( key - > values ) ; i + + ) {
struct regval_blob * blob ;
blob = regval_ctr_specific_value ( key - > values , i ) ;
if ( strequal ( regval_name ( blob ) , names [ n ] ) ) {
struct registry_value * v ;
err = reg_enumvalue ( mem_ctx , key , i , NULL , & v ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
return err ;
}
vals [ n ] = * v ;
found + + ;
}
}
}
* pvals = vals ;
* pnum_vals = found ;
return WERR_OK ;
}
2006-12-01 23:01:09 +03:00
WERROR reg_queryinfokey ( struct registry_key * key , uint32_t * num_subkeys ,
uint32_t * max_subkeylen , uint32_t * max_subkeysize ,
uint32_t * num_values , uint32_t * max_valnamelen ,
uint32_t * max_valbufsize , uint32_t * secdescsize ,
NTTIME * last_changed_time )
{
2015-04-14 17:50:28 +03:00
uint32_t i , max_size ;
2006-12-01 23:01:09 +03:00
size_t max_len ;
TALLOC_CTX * mem_ctx ;
WERROR err ;
struct security_descriptor * secdesc ;
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_QUERY_VALUE ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
if ( ! W_ERROR_IS_OK ( fill_subkey_cache ( key ) ) | |
! W_ERROR_IS_OK ( fill_value_cache ( key ) ) ) {
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2006-12-01 23:01:09 +03:00
}
max_len = 0 ;
2009-02-24 19:30:23 +03:00
for ( i = 0 ; i < regsubkey_ctr_numkeys ( key - > subkeys ) ; i + + ) {
2009-02-24 23:12:26 +03:00
max_len = MAX ( max_len ,
strlen ( regsubkey_ctr_specific_key ( key - > subkeys , i ) ) ) ;
2006-12-01 23:01:09 +03:00
}
2009-02-24 19:30:23 +03:00
* num_subkeys = regsubkey_ctr_numkeys ( key - > subkeys ) ;
2006-12-01 23:01:09 +03:00
* max_subkeylen = max_len ;
* max_subkeysize = 0 ; /* Class length? */
max_len = 0 ;
max_size = 0 ;
2010-05-24 01:56:40 +04:00
for ( i = 0 ; i < regval_ctr_numvals ( key - > values ) ; i + + ) {
struct regval_blob * blob ;
blob = regval_ctr_specific_value ( key - > values , i ) ;
max_len = MAX ( max_len , strlen ( regval_name ( blob ) ) ) ;
max_size = MAX ( max_size , regval_size ( blob ) ) ;
2006-12-01 23:01:09 +03:00
}
2010-05-24 01:56:40 +04:00
* num_values = regval_ctr_numvals ( key - > values ) ;
2006-12-01 23:01:09 +03:00
* max_valnamelen = max_len ;
* max_valbufsize = max_size ;
if ( ! ( mem_ctx = talloc_new ( key ) ) ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-01 23:01:09 +03:00
}
err = regkey_get_secdesc ( mem_ctx , key - > key , & secdesc ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
TALLOC_FREE ( mem_ctx ) ;
return err ;
}
2010-05-10 02:42:06 +04:00
* secdescsize = ndr_size_security_descriptor ( secdesc , 0 ) ;
2006-12-01 23:01:09 +03:00
TALLOC_FREE ( mem_ctx ) ;
* last_changed_time = 0 ;
return WERR_OK ;
}
WERROR reg_createkey ( TALLOC_CTX * ctx , struct registry_key * parent ,
2015-04-14 17:50:28 +03:00
const char * subkeypath , uint32_t desired_access ,
2006-12-01 23:01:09 +03:00
struct registry_key * * pkey ,
enum winreg_CreateAction * paction )
{
struct registry_key * key = parent ;
TALLOC_CTX * mem_ctx ;
char * path , * end ;
WERROR err ;
2012-04-23 18:44:15 +04:00
uint32_t access_granted ;
2006-12-01 23:01:09 +03:00
2012-04-12 19:58:26 +04:00
mem_ctx = talloc_new ( ctx ) ;
if ( mem_ctx = = NULL ) {
2015-12-03 17:24:14 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2012-04-12 19:58:26 +04:00
}
2006-12-01 23:01:09 +03:00
2012-04-12 19:58:26 +04:00
path = talloc_strdup ( mem_ctx , subkeypath ) ;
if ( path = = NULL ) {
2015-12-03 17:24:14 +03:00
err = WERR_NOT_ENOUGH_MEMORY ;
2006-12-01 23:01:09 +03:00
goto done ;
}
2012-04-13 00:17:35 +04:00
err = regdb_transaction_start ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_createkey: failed to start transaction: %s \n " ,
win_errstr ( err ) ) ) ;
goto done ;
}
2006-12-01 23:01:09 +03:00
while ( ( end = strchr ( path , ' \\ ' ) ) ! = NULL ) {
struct registry_key * tmp ;
enum winreg_CreateAction action ;
* end = ' \0 ' ;
err = reg_createkey ( mem_ctx , key , path ,
2009-04-15 03:30:12 +04:00
KEY_ENUMERATE_SUB_KEYS , & tmp , & action ) ;
2006-12-01 23:01:09 +03:00
if ( ! W_ERROR_IS_OK ( err ) ) {
2012-04-13 00:17:35 +04:00
goto trans_done ;
2006-12-01 23:01:09 +03:00
}
if ( key ! = parent ) {
TALLOC_FREE ( key ) ;
}
key = tmp ;
path = end + 1 ;
}
/*
* At this point , " path " contains the one - element subkey of " key " . We
* can try to open it .
*/
err = reg_openkey ( ctx , key , path , desired_access , pkey ) ;
if ( W_ERROR_IS_OK ( err ) ) {
2006-12-03 19:51:31 +03:00
if ( paction ! = NULL ) {
* paction = REG_OPENED_EXISTING_KEY ;
}
2012-04-13 00:17:35 +04:00
goto trans_done ;
2006-12-01 23:01:09 +03:00
}
2015-12-03 17:24:11 +03:00
if ( ! W_ERROR_EQUAL ( err , WERR_FILE_NOT_FOUND ) ) {
2006-12-01 23:01:09 +03:00
/*
* Something but " notfound " has happened , so bail out
*/
2012-04-13 00:17:35 +04:00
goto trans_done ;
2006-12-01 23:01:09 +03:00
}
/*
2012-04-23 18:44:15 +04:00
* We may ( e . g . in the iteration ) have opened the key with ENUM_SUBKEY .
* Instead of re - opening the key with CREATE_SUB_KEY , we simply
* duplicate the access check here and skip the expensive full open .
2006-12-01 23:01:09 +03:00
*/
2012-04-23 18:44:15 +04:00
if ( ! regkey_access_check ( key - > key , KEY_CREATE_SUB_KEY , & access_granted ,
key - > token ) )
{
err = WERR_ACCESS_DENIED ;
2014-10-08 17:39:28 +04:00
goto trans_done ;
2006-12-01 23:01:09 +03:00
}
/*
* Actually create the subkey
*/
2009-02-26 00:06:47 +03:00
err = create_reg_subkey ( key - > key , path ) ;
2012-04-13 00:17:35 +04:00
if ( ! W_ERROR_IS_OK ( err ) ) {
goto trans_done ;
}
2006-12-01 23:01:09 +03:00
/*
* Now open the newly created key
*/
2012-04-23 18:44:15 +04:00
err = reg_openkey ( ctx , key , path , desired_access , pkey ) ;
2006-12-01 23:01:09 +03:00
if ( W_ERROR_IS_OK ( err ) & & ( paction ! = NULL ) ) {
* paction = REG_CREATED_NEW_KEY ;
}
2012-04-13 00:17:35 +04:00
trans_done :
if ( W_ERROR_IS_OK ( err ) ) {
err = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_createkey: Error committing transaction: %s \n " , win_errstr ( err ) ) ) ;
}
} else {
WERROR err1 = regdb_transaction_cancel ( ) ;
if ( ! W_ERROR_IS_OK ( err1 ) ) {
DEBUG ( 0 , ( " reg_createkey: Error cancelling transaction: %s \n " , win_errstr ( err1 ) ) ) ;
}
}
2006-12-01 23:01:09 +03:00
done :
TALLOC_FREE ( mem_ctx ) ;
return err ;
}
2011-08-01 17:27:46 +04:00
static WERROR reg_deletekey_internal ( TALLOC_CTX * mem_ctx ,
struct registry_key * parent ,
const char * path , bool lazy )
2006-12-01 23:01:09 +03:00
{
WERROR err ;
char * name , * end ;
2011-08-01 17:27:46 +04:00
struct registry_key * key ;
2009-02-26 01:13:07 +03:00
name = talloc_strdup ( mem_ctx , path ) ;
if ( name = = NULL ) {
2015-12-03 17:24:14 +03:00
err = WERR_NOT_ENOUGH_MEMORY ;
2009-02-26 01:13:07 +03:00
goto done ;
2006-12-01 23:01:09 +03:00
}
2007-06-22 02:18:42 +04:00
/* no subkeys - proceed with delete */
2009-02-26 01:13:07 +03:00
end = strrchr ( name , ' \\ ' ) ;
if ( end ! = NULL ) {
2006-12-01 23:01:09 +03:00
* end = ' \0 ' ;
err = reg_openkey ( mem_ctx , parent , name ,
2011-08-01 17:27:46 +04:00
KEY_CREATE_SUB_KEY , & key ) ;
2009-02-26 01:13:07 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
2006-12-01 23:01:09 +03:00
2011-08-01 17:27:46 +04:00
parent = key ;
2006-12-01 23:01:09 +03:00
name = end + 1 ;
}
if ( name [ 0 ] = = ' \0 ' ) {
2015-12-03 17:24:24 +03:00
err = WERR_INVALID_PARAMETER ;
2009-02-26 01:13:07 +03:00
goto done ;
2006-12-01 23:01:09 +03:00
}
2011-08-01 17:27:46 +04:00
err = delete_reg_subkey ( parent - > key , name , lazy ) ;
done :
return err ;
}
WERROR reg_deletekey ( struct registry_key * parent , const char * path )
{
WERROR err ;
struct registry_key * key ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
/* check if the key has subkeys */
err = reg_openkey ( mem_ctx , parent , path , REG_KEY_READ , & key ) ;
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
2012-04-13 00:53:24 +04:00
err = regdb_transaction_start ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_deletekey: Error starting transaction: %s \n " ,
win_errstr ( err ) ) ) ;
goto done ;
}
2011-08-01 17:27:46 +04:00
err = fill_subkey_cache ( key ) ;
2012-04-13 00:53:24 +04:00
if ( ! W_ERROR_IS_OK ( err ) ) {
goto trans_done ;
}
2007-11-06 02:50:47 +03:00
2011-08-01 17:27:46 +04:00
if ( regsubkey_ctr_numkeys ( key - > subkeys ) > 0 ) {
err = WERR_ACCESS_DENIED ;
2012-04-13 00:53:24 +04:00
goto trans_done ;
2011-08-01 17:27:46 +04:00
}
err = reg_deletekey_internal ( mem_ctx , parent , path , false ) ;
2012-04-13 00:53:24 +04:00
trans_done :
if ( W_ERROR_IS_OK ( err ) ) {
err = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_deletekey: Error committing transaction: %s \n " , win_errstr ( err ) ) ) ;
}
} else {
WERROR err1 = regdb_transaction_cancel ( ) ;
if ( ! W_ERROR_IS_OK ( err1 ) ) {
DEBUG ( 0 , ( " reg_deletekey: Error cancelling transaction: %s \n " , win_errstr ( err1 ) ) ) ;
}
}
2009-02-26 01:13:07 +03:00
done :
2006-12-01 23:01:09 +03:00
TALLOC_FREE ( mem_ctx ) ;
return err ;
}
2011-08-01 17:27:46 +04:00
2006-12-01 23:01:09 +03:00
WERROR reg_setvalue ( struct registry_key * key , const char * name ,
const struct registry_value * val )
{
2011-02-15 20:16:43 +03:00
struct regval_blob * existing ;
2006-12-01 23:01:09 +03:00
WERROR err ;
int res ;
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_SET_VALUE ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
2012-04-12 15:38:32 +04:00
err = regdb_transaction_start ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_setvalue: Failed to start transaction: %s \n " ,
win_errstr ( err ) ) ) ;
return err ;
}
2012-04-20 17:19:47 +04:00
err = fill_value_cache ( key ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_setvalue: Error filling value cache: %s \n " , win_errstr ( err ) ) ) ;
2012-04-12 15:38:32 +04:00
goto done ;
2006-12-01 23:01:09 +03:00
}
2011-02-15 20:16:43 +03:00
existing = regval_ctr_getvalue ( key - > values , name ) ;
if ( ( existing ! = NULL ) & &
( regval_size ( existing ) = = val - > data . length ) & &
( memcmp ( regval_data_p ( existing ) , val - > data . data ,
2012-04-12 15:38:32 +04:00
val - > data . length ) = = 0 ) )
{
err = WERR_OK ;
goto done ;
2011-02-15 20:16:43 +03:00
}
2006-12-01 23:01:09 +03:00
res = regval_ctr_addvalue ( key - > values , name , val - > type ,
2010-06-29 18:13:15 +04:00
val - > data . data , val - > data . length ) ;
2006-12-01 23:01:09 +03:00
if ( res = = 0 ) {
TALLOC_FREE ( key - > values ) ;
2015-12-03 17:24:14 +03:00
err = WERR_NOT_ENOUGH_MEMORY ;
2012-04-12 15:38:32 +04:00
goto done ;
2006-12-01 23:01:09 +03:00
}
if ( ! store_reg_values ( key - > key , key - > values ) ) {
TALLOC_FREE ( key - > values ) ;
2012-04-12 15:38:32 +04:00
DEBUG ( 0 , ( " reg_setvalue: store_reg_values failed \n " ) ) ;
2015-12-03 17:24:29 +03:00
err = WERR_REGISTRY_IO_FAILED ;
2012-04-12 15:38:32 +04:00
goto done ;
2006-12-01 23:01:09 +03:00
}
2012-04-12 15:38:32 +04:00
err = WERR_OK ;
done :
if ( W_ERROR_IS_OK ( err ) ) {
err = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_setvalue: Error committing transaction: %s \n " , win_errstr ( err ) ) ) ;
}
} else {
WERROR err1 = regdb_transaction_cancel ( ) ;
if ( ! W_ERROR_IS_OK ( err1 ) ) {
DEBUG ( 0 , ( " reg_setvalue: Error cancelling transaction: %s \n " , win_errstr ( err1 ) ) ) ;
}
}
return err ;
2006-12-01 23:01:09 +03:00
}
2008-03-31 19:20:07 +04:00
static WERROR reg_value_exists ( struct registry_key * key , const char * name )
{
2010-05-24 01:56:40 +04:00
struct regval_blob * blob ;
2008-03-31 19:20:07 +04:00
2010-05-24 01:56:40 +04:00
blob = regval_ctr_getvalue ( key - > values , name ) ;
2008-03-31 19:20:07 +04:00
2010-05-24 01:56:40 +04:00
if ( blob = = NULL ) {
2015-12-03 17:24:11 +03:00
return WERR_FILE_NOT_FOUND ;
2010-05-24 01:56:40 +04:00
} else {
return WERR_OK ;
}
2008-03-31 19:20:07 +04:00
}
2006-12-01 23:01:09 +03:00
WERROR reg_deletevalue ( struct registry_key * key , const char * name )
{
WERROR err ;
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_SET_VALUE ) ) {
2006-12-01 23:01:09 +03:00
return WERR_ACCESS_DENIED ;
}
2012-04-12 19:52:43 +04:00
err = regdb_transaction_start ( ) ;
2012-04-12 19:46:02 +04:00
if ( ! W_ERROR_IS_OK ( err ) ) {
2012-04-12 19:52:43 +04:00
DEBUG ( 0 , ( " reg_deletevalue: Failed to start transaction: %s \n " ,
win_errstr ( err ) ) ) ;
2006-12-01 23:01:09 +03:00
return err ;
}
2012-04-12 19:52:43 +04:00
err = fill_value_cache ( key ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_deletevalue; Error filling value cache: %s \n " ,
win_errstr ( err ) ) ) ;
goto done ;
}
2008-03-31 19:20:07 +04:00
err = reg_value_exists ( key , name ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
2012-04-12 19:52:43 +04:00
goto done ;
2008-03-31 19:20:07 +04:00
}
2006-12-01 23:01:09 +03:00
regval_ctr_delvalue ( key - > values , name ) ;
if ( ! store_reg_values ( key - > key , key - > values ) ) {
TALLOC_FREE ( key - > values ) ;
2015-12-03 17:24:29 +03:00
err = WERR_REGISTRY_IO_FAILED ;
2012-04-12 19:52:43 +04:00
DEBUG ( 0 , ( " reg_deletevalue: store_reg_values failed \n " ) ) ;
goto done ;
2006-12-01 23:01:09 +03:00
}
2012-04-12 19:52:43 +04:00
err = WERR_OK ;
done :
if ( W_ERROR_IS_OK ( err ) ) {
err = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
DEBUG ( 0 , ( " reg_deletevalue: Error committing transaction: %s \n " , win_errstr ( err ) ) ) ;
}
} else {
WERROR err1 = regdb_transaction_cancel ( ) ;
if ( ! W_ERROR_IS_OK ( err1 ) ) {
DEBUG ( 0 , ( " reg_deletevalue: Error cancelling transaction: %s \n " , win_errstr ( err1 ) ) ) ;
}
}
return err ;
2006-12-01 23:01:09 +03:00
}
2008-01-17 13:02:15 +03:00
WERROR reg_getkeysecurity ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
struct security_descriptor * * psecdesc )
{
return regkey_get_secdesc ( mem_ctx , key - > key , psecdesc ) ;
}
WERROR reg_setkeysecurity ( struct registry_key * key ,
struct security_descriptor * psecdesc )
{
return regkey_set_secdesc ( key - > key , psecdesc ) ;
}
2008-01-17 02:57:53 +03:00
2008-01-17 13:22:01 +03:00
WERROR reg_getversion ( uint32_t * version )
{
if ( version = = NULL ) {
2015-12-03 17:24:24 +03:00
return WERR_INVALID_PARAMETER ;
2008-01-17 13:22:01 +03:00
}
* version = 0x00000005 ; /* Windows 2000 registry API version */
return WERR_OK ;
}
2008-01-17 02:57:53 +03:00
/**********************************************************************
* Higher level utility functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 19:29:42 +04:00
WERROR reg_deleteallvalues ( struct registry_key * key )
{
WERROR err ;
2022-07-01 19:24:53 +03:00
uint32_t i ;
2007-08-14 19:29:42 +04:00
2009-04-15 03:30:12 +04:00
if ( ! ( key - > key - > access_granted & KEY_SET_VALUE ) ) {
2007-08-14 19:29:42 +04:00
return WERR_ACCESS_DENIED ;
}
if ( ! W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) {
return err ;
}
2010-05-24 01:56:40 +04:00
for ( i = 0 ; i < regval_ctr_numvals ( key - > values ) ; i + + ) {
struct regval_blob * blob ;
blob = regval_ctr_specific_value ( key - > values , i ) ;
regval_ctr_delvalue ( key - > values , regval_name ( blob ) ) ;
2007-08-14 19:29:42 +04:00
}
if ( ! store_reg_values ( key - > key , key - > values ) ) {
TALLOC_FREE ( key - > values ) ;
2015-12-03 17:24:29 +03:00
return WERR_REGISTRY_IO_FAILED ;
2007-08-14 19:29:42 +04:00
}
return WERR_OK ;
}
2007-04-09 14:38:55 +04:00
2007-06-22 15:21:59 +04:00
/*
2008-01-15 16:55:04 +03:00
* Utility function to delete a registry key with all its subkeys .
* Note that reg_deletekey returns ACCESS_DENIED when called on a
2007-06-22 15:21:59 +04:00
* key that has subkeys .
*/
2010-09-22 08:21:38 +04:00
static WERROR reg_deletekey_recursive_internal ( struct registry_key * parent ,
2008-01-17 02:16:58 +03:00
const char * path ,
2011-08-01 17:27:46 +04:00
bool del_key , bool lazy )
2007-06-22 15:21:59 +04:00
{
2019-07-10 14:26:06 +03:00
WERROR werr ;
2007-06-22 15:21:59 +04:00
struct registry_key * key ;
char * subkey_name = NULL ;
2015-04-14 17:50:28 +03:00
uint32_t i ;
2010-09-22 08:21:38 +04:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2007-06-22 15:21:59 +04:00
2011-08-15 01:48:41 +04:00
DEBUG ( 5 , ( " reg_deletekey_recursive_internal: deleting '%s' from '%s' \n " ,
path , parent - > key - > name ) ) ;
2007-06-22 15:21:59 +04:00
/* recurse through subkeys first */
2007-12-31 05:25:54 +03:00
werr = reg_openkey ( mem_ctx , parent , path , REG_KEY_ALL , & key ) ;
2007-06-22 15:21:59 +04:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2011-08-15 01:48:41 +04:00
DEBUG ( 3 , ( " reg_deletekey_recursive_internal: error opening "
" subkey '%s' of '%s': '%s' \n " ,
path , parent - > key - > name , win_errstr ( werr ) ) ) ;
2007-06-22 15:21:59 +04:00
goto done ;
}
2009-02-26 04:59:07 +03:00
werr = fill_subkey_cache ( key ) ;
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
/*
2017-02-17 22:53:39 +03:00
* loop from top to bottom for performance :
2009-02-26 04:59:07 +03:00
* this way , we need to rehash the regsubkey containers less
*/
for ( i = regsubkey_ctr_numkeys ( key - > subkeys ) ; i > 0 ; i - - ) {
subkey_name = regsubkey_ctr_specific_key ( key - > subkeys , i - 1 ) ;
2011-08-01 17:27:46 +04:00
werr = reg_deletekey_recursive_internal ( key , subkey_name , true , del_key ) ;
2009-02-26 04:59:07 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
2007-06-22 15:21:59 +04:00
}
2007-09-27 05:26:19 +04:00
if ( del_key ) {
/* now delete the actual key */
2011-08-01 17:27:46 +04:00
werr = reg_deletekey_internal ( mem_ctx , parent , path , lazy ) ;
2007-09-27 05:26:19 +04:00
}
2007-06-22 15:21:59 +04:00
done :
2011-08-15 01:48:41 +04:00
DEBUG ( 5 , ( " reg_deletekey_recursive_internal: done deleting '%s' from "
" '%s': %s \n " ,
path , parent - > key - > name , win_errstr ( werr ) ) ) ;
2007-06-22 15:21:59 +04:00
TALLOC_FREE ( mem_ctx ) ;
return werr ;
}
2007-09-27 05:26:19 +04:00
2010-09-22 08:21:38 +04:00
static WERROR reg_deletekey_recursive_trans ( struct registry_key * parent ,
2009-02-24 17:40:05 +03:00
const char * path ,
bool del_key )
{
WERROR werr ;
werr = regdb_transaction_start ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_deletekey_recursive_trans: "
" error starting transaction: %s \n " ,
win_errstr ( werr ) ) ) ;
return werr ;
}
2011-08-01 17:27:46 +04:00
werr = reg_deletekey_recursive_internal ( parent , path , del_key , false ) ;
2009-02-24 17:40:05 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2011-01-30 15:44:31 +03:00
WERROR werr2 ;
2015-12-03 17:24:11 +03:00
DEBUG ( W_ERROR_EQUAL ( werr , WERR_FILE_NOT_FOUND ) ? 5 : 1 ,
2012-05-02 13:22:54 +04:00
( __location__ " : failed to delete key '%s' from key "
" '%s': %s \n " , path , parent - > key - > name ,
win_errstr ( werr ) ) ) ;
2011-01-30 15:44:31 +03:00
werr2 = regdb_transaction_cancel ( ) ;
if ( ! W_ERROR_IS_OK ( werr2 ) ) {
2009-02-24 17:40:05 +03:00
DEBUG ( 0 , ( " reg_deletekey_recursive_trans: "
" error cancelling transaction: %s \n " ,
2011-01-30 15:44:31 +03:00
win_errstr ( werr2 ) ) ) ;
/*
* return the original werr or the
* error from cancelling the transaction ?
*/
2009-02-24 17:40:05 +03:00
}
} else {
werr = regdb_transaction_commit ( ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( " reg_deletekey_recursive_trans: "
" error committing transaction: %s \n " ,
win_errstr ( werr ) ) ) ;
2011-08-15 01:48:41 +04:00
} else {
2013-12-20 00:29:32 +04:00
DEBUG ( 5 , ( " reg_deletekey_recursive_trans: deleted key '%s' from '%s' \n " ,
2011-08-15 01:48:41 +04:00
path , parent - > key - > name ) ) ;
2009-02-24 17:40:05 +03:00
}
}
return werr ;
}
2010-09-22 08:21:38 +04:00
WERROR reg_deletekey_recursive ( struct registry_key * parent ,
2007-09-27 05:26:19 +04:00
const char * path )
{
2010-09-22 08:21:38 +04:00
return reg_deletekey_recursive_trans ( parent , path , true ) ;
2007-09-27 05:26:19 +04:00
}
2010-09-22 08:21:38 +04:00
WERROR reg_deletesubkeys_recursive ( struct registry_key * parent ,
2007-09-27 05:26:19 +04:00
const char * path )
{
2010-09-22 08:21:38 +04:00
return reg_deletekey_recursive_trans ( parent , path , false ) ;
2007-09-27 05:26:19 +04:00
}
2008-01-17 12:19:12 +03:00