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 02:04:13 +04:00
# include "reg_util_internal.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"
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
}
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 ) ;
return WERR_BADFILE ;
}
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
}
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 ) ;
return WERR_NO_MORE_ITEMS ;
}
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 ,
2007-06-22 15:03:48 +04:00
uint32 access_desired ,
struct registry_key * * pregkey )
{
WERROR result = WERR_OK ;
struct registry_key * regkey ;
2009-03-24 01:02:57 +03:00
struct registry_key_handle * key ;
2009-02-24 17:19:18 +03:00
struct regsubkey_ctr * subkeys = NULL ;
2007-06-22 15:03:48 +04:00
DEBUG ( 7 , ( " regkey_open_onelevel: name = [%s] \n " , name ) ) ;
SMB_ASSERT ( strchr ( name , ' \\ ' ) = = NULL ) ;
if ( ! ( regkey = TALLOC_ZERO_P ( mem_ctx , struct registry_key ) ) | |
! ( regkey - > token = dup_nt_token ( regkey , token ) ) | |
2009-03-24 01:02:57 +03:00
! ( regkey - > key = TALLOC_ZERO_P ( regkey , struct registry_key_handle ) ) )
{
2007-06-22 15:03:48 +04:00
result = WERR_NOMEM ;
goto done ;
}
if ( ! ( W_ERROR_IS_OK ( result = regdb_open ( ) ) ) ) {
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 ) {
result = WERR_BADFILE ;
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 ) {
result = WERR_NOMEM ;
goto done ;
}
/* Tag this as a Performance Counter Key */
if ( StrnCaseCmp ( key - > name , KEY_HKPD , strlen ( KEY_HKPD ) ) = = 0 )
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 */
2008-04-13 02:54:44 +04:00
if ( ! ( key - > ops = reghook_cache_find ( key - > name ) ) ) {
DEBUG ( 0 , ( " reg_open_onelevel: Failed to assign "
2009-03-24 01:14:45 +03:00
" registry_ops to [%s] \n " , key - > name ) ) ;
2007-06-22 15:03:48 +04:00
result = WERR_BADFILE ;
goto done ;
}
2008-01-15 16:55:04 +03:00
2007-06-22 15:03:48 +04:00
/* check if the path really exists; failed is indicated by -1 */
/* if the subkey count failed, bail out */
2009-02-25 01:17:05 +03:00
result = regsubkey_ctr_init ( key , & subkeys ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
2007-06-22 15:03:48 +04:00
goto done ;
}
if ( fetch_reg_keys ( key , subkeys ) = = - 1 ) {
result = WERR_BADFILE ;
goto done ;
}
2008-01-15 16:55:04 +03:00
2007-06-22 15:03:48 +04:00
TALLOC_FREE ( subkeys ) ;
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 ,
uint32 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 )
{
2006-12-05 10:36:14 +03:00
SMB_ASSERT ( hive ! = NULL ) ;
2006-12-01 23:01:09 +03:00
SMB_ASSERT ( hive [ 0 ] ! = ' \0 ' ) ;
SMB_ASSERT ( strchr ( hive , ' \\ ' ) = = NULL ) ;
2006-12-05 10:36:14 +03:00
return regkey_open_onelevel ( mem_ctx , NULL , hive , 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 ,
const char * name , uint32 desired_access ,
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 ;
2006-12-05 10:36:14 +03:00
char * p , * path , * to_free ;
size_t len ;
2006-12-01 23:01:09 +03:00
2006-12-05 10:36:14 +03:00
if ( ! ( path = SMB_STRDUP ( name ) ) ) {
2006-12-01 23:01:09 +03:00
return WERR_NOMEM ;
}
2006-12-05 10:36:14 +03:00
to_free = path ;
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
2006-12-05 10:36:14 +03:00
if ( ! ( name_component = SMB_STRNDUP ( path , ( p - path ) ) ) ) {
err = WERR_NOMEM ;
goto error ;
}
2006-12-01 23:01:09 +03:00
2006-12-05 10:36:14 +03:00
err = regkey_open_onelevel ( mem_ctx , direct_parent ,
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
SAFE_FREE ( name_component ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
goto error ;
}
if ( direct_parent ! = parent ) {
TALLOC_FREE ( direct_parent ) ;
}
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 ) ;
error :
if ( direct_parent ! = parent ) {
TALLOC_FREE ( direct_parent ) ;
}
SAFE_FREE ( to_free ) ;
return err ;
2006-12-01 23:01:09 +03:00
}
WERROR reg_enumkey ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
uint32 idx , char * * name , NTTIME * last_write_time )
{
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 ;
}
if ( ! W_ERROR_IS_OK ( err = fill_subkey_cache ( key ) ) ) {
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 ) ) ) )
{
2006-12-01 23:01:09 +03:00
return WERR_NOMEM ;
}
if ( last_write_time ) {
* last_write_time = 0 ;
}
return WERR_OK ;
}
WERROR reg_enumvalue ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
2006-12-02 13:51:54 +03:00
uint32 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 ;
}
if ( ! ( W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) ) {
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 ) {
return WERR_NOMEM ;
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 ) ;
2006-12-01 23:01:09 +03:00
return WERR_NOMEM ;
}
2008-01-15 16:55:04 +03:00
2006-12-01 23:01:09 +03:00
* pval = val ;
return WERR_OK ;
}
WERROR reg_queryvalue ( TALLOC_CTX * mem_ctx , struct registry_key * key ,
const char * name , struct registry_value * * pval )
{
WERROR err ;
uint32 i ;
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 ) ) {
2006-12-01 23:01:09 +03:00
return reg_enumvalue ( mem_ctx , key , i , NULL , pval ) ;
}
}
return WERR_BADFILE ;
}
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 ) {
return WERR_NOMEM ;
}
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 )
{
uint32 i , max_size ;
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 ) ) ) {
return WERR_BADFILE ;
}
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 ) ) ) {
return WERR_NOMEM ;
}
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 ,
const char * subkeypath , uint32 desired_access ,
struct registry_key * * pkey ,
enum winreg_CreateAction * paction )
{
struct registry_key * key = parent ;
struct registry_key * create_parent ;
TALLOC_CTX * mem_ctx ;
char * path , * end ;
WERROR err ;
if ( ! ( mem_ctx = talloc_new ( ctx ) ) ) return WERR_NOMEM ;
if ( ! ( path = talloc_strdup ( mem_ctx , subkeypath ) ) ) {
err = WERR_NOMEM ;
goto done ;
}
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 ) ) {
goto done ;
}
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 ;
}
goto done ;
2006-12-01 23:01:09 +03:00
}
if ( ! W_ERROR_EQUAL ( err , WERR_BADFILE ) ) {
/*
* Something but " notfound " has happened , so bail out
*/
goto done ;
}
/*
* We have to make a copy of the current key , as we opened it only
* with ENUM_SUBKEY access .
*/
2009-04-15 03:30:12 +04:00
err = reg_openkey ( mem_ctx , key , " " , KEY_CREATE_SUB_KEY ,
2006-12-01 23:01:09 +03:00
& create_parent ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
goto done ;
}
/*
* Actually create the subkey
*/
err = fill_subkey_cache ( create_parent ) ;
if ( ! W_ERROR_IS_OK ( err ) ) goto done ;
2009-02-26 00:06:47 +03:00
err = create_reg_subkey ( key - > key , path ) ;
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
2006-12-01 23:01:09 +03:00
/*
* Now open the newly created key
*/
err = reg_openkey ( ctx , create_parent , path , desired_access , pkey ) ;
if ( W_ERROR_IS_OK ( err ) & & ( paction ! = NULL ) ) {
* paction = REG_CREATED_NEW_KEY ;
}
done :
TALLOC_FREE ( mem_ctx ) ;
return err ;
}
WERROR reg_deletekey ( struct registry_key * parent , const char * path )
{
WERROR err ;
char * name , * end ;
2007-11-06 02:50:47 +03:00
struct registry_key * tmp_key , * key ;
2009-02-26 01:13:07 +03:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2006-12-01 23:01:09 +03:00
2009-02-26 01:13:07 +03:00
name = talloc_strdup ( mem_ctx , path ) ;
if ( name = = NULL ) {
2006-12-01 23:01:09 +03:00
err = WERR_NOMEM ;
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
/* check if the key has subkeys */
2007-11-06 02:50:47 +03:00
err = reg_openkey ( mem_ctx , parent , name , REG_KEY_READ , & key ) ;
2009-02-26 01:13:07 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
err = fill_subkey_cache ( key ) ;
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
2009-02-24 19:30:23 +03:00
if ( regsubkey_ctr_numkeys ( key - > subkeys ) > 0 ) {
2007-06-22 02:18:42 +04:00
err = WERR_ACCESS_DENIED ;
2009-02-26 01:13:07 +03:00
goto done ;
2007-06-22 02:18:42 +04:00
}
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 ,
2009-04-15 03:30:12 +04:00
KEY_CREATE_SUB_KEY , & tmp_key ) ;
2009-02-26 01:13:07 +03:00
W_ERROR_NOT_OK_GOTO_DONE ( err ) ;
2006-12-01 23:01:09 +03:00
2007-06-22 02:18:42 +04:00
parent = tmp_key ;
2006-12-01 23:01:09 +03:00
name = end + 1 ;
}
if ( name [ 0 ] = = ' \0 ' ) {
err = WERR_INVALID_PARAM ;
2009-02-26 01:13:07 +03:00
goto done ;
2006-12-01 23:01:09 +03:00
}
2009-02-26 04:57:59 +03:00
err = delete_reg_subkey ( parent - > key , name ) ;
2007-11-06 02:50:47 +03:00
2009-02-26 01:13:07 +03:00
done :
2006-12-01 23:01:09 +03:00
TALLOC_FREE ( mem_ctx ) ;
return err ;
}
WERROR reg_setvalue ( struct registry_key * key , const char * name ,
const struct registry_value * val )
{
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 ;
}
if ( ! W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) {
return err ;
}
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 ) ;
return WERR_NOMEM ;
}
if ( ! store_reg_values ( key - > key , key - > values ) ) {
TALLOC_FREE ( key - > values ) ;
return WERR_REG_IO_FAILURE ;
}
return WERR_OK ;
}
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 ) {
return WERR_BADFILE ;
} 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 ;
}
if ( ! W_ERROR_IS_OK ( err = fill_value_cache ( key ) ) ) {
return err ;
}
2008-03-31 19:20:07 +04:00
err = reg_value_exists ( key , name ) ;
if ( ! W_ERROR_IS_OK ( err ) ) {
return err ;
}
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 ) ;
return WERR_REG_IO_FAILURE ;
}
return WERR_OK ;
}
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 ) {
return WERR_INVALID_PARAM ;
}
* 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 ;
int i ;
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 ) ;
return WERR_REG_IO_FAILURE ;
}
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 ,
bool del_key )
2007-06-22 15:21:59 +04:00
{
WERROR werr = WERR_OK ;
struct registry_key * key ;
char * subkey_name = NULL ;
2009-02-26 04:59:07 +03:00
uint32 i ;
2010-09-22 08:21:38 +04:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
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 ) ) {
goto done ;
}
2009-02-26 04:59:07 +03:00
werr = fill_subkey_cache ( key ) ;
W_ERROR_NOT_OK_GOTO_DONE ( werr ) ;
/*
* loop from top to bottom for perfomance :
* 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 ) ;
2010-09-22 08:21:38 +04:00
werr = reg_deletekey_recursive_internal ( key , subkey_name , true ) ;
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 */
werr = reg_deletekey ( parent , path ) ;
}
2007-06-22 15:21:59 +04:00
done :
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 ;
}
2010-09-22 08:21:38 +04:00
werr = reg_deletekey_recursive_internal ( parent , path , del_key ) ;
2009-02-24 17:40:05 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
2011-01-30 15:44:31 +03:00
WERROR werr2 ;
2009-02-25 11:53:16 +03:00
DEBUG ( 1 , ( __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 ) ) ) ;
}
}
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