1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-09 00:23:50 +03:00

r19872: Move the value cache to srv_winreg_nt.c. Fix some minor issues found while

playing with regedit.exe.

Volker
This commit is contained in:
Volker Lendecke
2006-11-23 22:58:50 +00:00
committed by Gerald (Jerry) Carter
parent 0ed3a21fcc
commit 81bd816fa2
2 changed files with 102 additions and 125 deletions

View File

@@ -320,60 +320,6 @@ NTSTATUS registry_fetch_values(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
return NT_STATUS_OK; return NT_STATUS_OK;
} }
/***********************************************************************
retreive a specific subkey specified by index. Caller is
responsible for freeing memory
***********************************************************************/
BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
{
static REGVAL_CTR *ctr = NULL;
static pstring save_path;
REGISTRY_VALUE *v;
*val = NULL;
/* simple caching for performance; very basic heuristic */
if ( !ctr ) {
DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
return False;
}
pstrcpy( save_path, key->name );
if ( fetch_reg_values( key, ctr) == -1 )
return False;
}
/* clear the cache when val_index == 0 or the path has changed */
else if ( !val_index || !strequal(save_path, key->name) ) {
DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));
TALLOC_FREE( ctr );
if ( !(ctr = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
DEBUG(0,("fetch_reg_values_specific: talloc() failed!\n"));
return False;
}
pstrcpy( save_path, key->name );
if ( fetch_reg_values( key, ctr) == -1 )
return False;
}
if ( !(v = regval_ctr_specific_value( ctr, val_index )) )
return False;
*val = dup_registry_value( v );
return True;
}
/*********************************************************************** /***********************************************************************
High level access check for passing the required access mask to the High level access check for passing the required access mask to the
underlying registry backend underlying registry backend

View File

@@ -32,6 +32,7 @@ static struct generic_mapping reg_generic_map =
struct regkey_info { struct regkey_info {
REGISTRY_KEY *key; REGISTRY_KEY *key;
REGVAL_CTR *value_cache;
}; };
/****************************************************************** /******************************************************************
@@ -73,6 +74,23 @@ static REGISTRY_KEY *find_regkey_by_hnd(pipes_struct *p, POLICY_HND *hnd)
return regkey->key; return regkey->key;
} }
static WERROR fill_value_cache(struct regkey_info *info)
{
if (info->value_cache != NULL) {
return WERR_OK;
}
if (!(info->value_cache = TALLOC_ZERO_P(info, REGVAL_CTR))) {
return WERR_NOMEM;
}
if (fetch_reg_values(info->key, info->value_cache) == -1) {
TALLOC_FREE(info->value_cache);
return WERR_BADFILE;
}
return WERR_OK;
}
/******************************************************************* /*******************************************************************
Function for open a new registry handle and creating a handle Function for open a new registry handle and creating a handle
@@ -382,7 +400,8 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
uint32_t *data_size, uint32_t *value_length) uint32_t *data_size, uint32_t *value_length)
{ {
WERROR status = WERR_BADFILE; WERROR status = WERR_BADFILE;
REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle ); struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
REGISTRY_KEY *regkey;
prs_struct prs_hkpd; prs_struct prs_hkpd;
uint8_t *outbuf; uint8_t *outbuf;
@@ -391,9 +410,11 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
BOOL free_buf = False; BOOL free_buf = False;
BOOL free_prs = False; BOOL free_prs = False;
if ( !regkey ) if ( !info )
return WERR_BADFID; return WERR_BADFID;
regkey = info->key;
*value_length = *type = 0; *value_length = *type = 0;
DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name)); DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
@@ -440,41 +461,36 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
*type = REG_BINARY; *type = REG_BINARY;
} }
else { else {
/* HKPT calls can be handled out of reg_dynamic.c with the REGISTRY_VALUE *val = NULL;
* hkpt_params handler */
REGVAL_CTR *regvals;
uint32 i; uint32 i;
if (!(regvals = TALLOC_ZERO_P(p->mem_ctx, REGVAL_CTR))) { status = fill_value_cache(info);
return WERR_NOMEM;
if (!(W_ERROR_IS_OK(status))) {
return status;
} }
/* for (i=0; i<info->value_cache->num_values; i++) {
* Don't use fetch_reg_values_specific here, there is too much if (strequal(info->value_cache->values[i]->valuename,
* memory copying around. I'll re-add the cache later. VL
*/
if (fetch_reg_values(regkey, regvals) == -1) {
TALLOC_FREE(regvals);
return WERR_BADFILE;
}
for (i=0; i<regvals->num_values; i++) {
if (strequal(regvals->values[i]->valuename,
value_name.name)) { value_name.name)) {
val = info->value_cache->values[i];
break; break;
} }
} }
if (i == regvals->num_values) { if (val == NULL) {
TALLOC_FREE(regvals); if (data_size) {
*data_size = 0;
}
if (value_length) {
*value_length = 0;
}
return WERR_BADFILE; return WERR_BADFILE;
} }
outbuf = regvals->values[i]->data_p; outbuf = val->data_p;
outbuf_size = regvals->values[i]->size; outbuf_size = val->size;
*type = regvals->values[i]->type; *type = val->type;
} }
*value_length = outbuf_size; *value_length = outbuf_size;
@@ -596,31 +612,40 @@ done:
Implementation of REG_ENUM_VALUE Implementation of REG_ENUM_VALUE
****************************************************************************/ ****************************************************************************/
WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length) WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle,
uint32_t enum_index, struct winreg_StringBuf *name,
enum winreg_Type *type, uint8_t *data,
uint32_t *data_size, uint32_t *value_length)
{ {
WERROR status = WERR_OK; WERROR status = WERR_OK;
REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle ); struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
REGISTRY_VALUE *val; REGISTRY_KEY *regkey;
REGISTRY_VALUE *val = NULL;
if ( !regkey ) if ( !info )
return WERR_BADFID; return WERR_BADFID;
if ( !name ) if ( !name )
return WERR_INVALID_PARAM; return WERR_INVALID_PARAM;
DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n", regkey->name));
if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) { regkey = info->key;
status = WERR_NO_MORE_ITEMS;
goto done; DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
regkey->name));
status = fill_value_cache(info);
if (!W_ERROR_IS_OK(status)) {
return status;
} }
DEBUG(10,("_winreg_EnumValue: retrieved value named [%s]\n", val->valuename)); if (enum_index >= info->value_cache->num_values) {
return WERR_BADFILE;
/* subkey has the string name now */ }
if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) { val = info->value_cache->values[enum_index];
status = WERR_NOMEM;
if (!(name->name = talloc_strdup(p->mem_ctx, val->valuename))) {
return WERR_NOMEM;
} }
if (type != NULL) { if (type != NULL) {
@@ -629,33 +654,26 @@ WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t
if (data != NULL) { if (data != NULL) {
if ((data_size == NULL) || (value_length == NULL)) { if ((data_size == NULL) || (value_length == NULL)) {
status = WERR_INVALID_PARAM; return WERR_INVALID_PARAM;
goto done;
} }
if (regval_size(val) > *data_size) { if (val->size > *data_size) {
status = WERR_MORE_DATA; return WERR_MORE_DATA;
goto done;
} }
memcpy( data, regval_data_p(val), regval_size(val) ); memcpy( data, val->data_p, val->size );
status = WERR_OK;
} }
if (value_length != NULL) { if (value_length != NULL) {
*value_length = regval_size( val ); *value_length = val->size;
} }
if (data_size != NULL) { if (data_size != NULL) {
*data_size = regval_size( val ); *data_size = val->size;
} }
done: return WERR_OK;
free_registry_value( val );
return status;
} }
/******************************************************************* /*******************************************************************
reg_shutdwon reg_shutdwon
********************************************************************/ ********************************************************************/
@@ -1275,26 +1293,31 @@ done:
WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size) WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
{ {
REGISTRY_KEY *key = find_regkey_by_hnd(p, handle); struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
REGISTRY_KEY *key;
REGVAL_CTR *values; REGVAL_CTR *values;
BOOL write_result; BOOL write_result;
char *valuename;
if ( !key ) if ( !info )
return WERR_BADFID; return WERR_BADFID;
key = info->key;
if (!name.name || (strlen(name.name) == 0)) {
/*
* This is the "Standard Value" for a key, we don't support
* that (yet...)
*/
return WERR_ACCESS_DENIED;
}
/* access checks first */ /* access checks first */
if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) ) if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
return WERR_ACCESS_DENIED; return WERR_ACCESS_DENIED;
/* verify the name */ DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name,
name.name));
if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
return WERR_INVALID_PARAM;
}
DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) ) if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
return WERR_NOMEM; return WERR_NOMEM;
@@ -1303,7 +1326,8 @@ WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct wi
fetch_reg_values( key, values ); fetch_reg_values( key, values );
regval_ctr_addvalue( values, valuename, type, (const char *)data, size ); regval_ctr_addvalue( values, name.name, type,
(const char *)data, size );
/* now write to the registry backend */ /* now write to the registry backend */
@@ -1313,7 +1337,9 @@ WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct wi
if ( !write_result ) if ( !write_result )
return WERR_REG_IO_FAILURE; return WERR_REG_IO_FAILURE;
TALLOC_FREE(info->value_cache);
return WERR_OK; return WERR_OK;
} }
@@ -1411,13 +1437,16 @@ done:
WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value) WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
{ {
REGISTRY_KEY *key = find_regkey_by_hnd(p, handle); struct regkey_info *info = find_regkey_info_by_hnd(p, handle);
REGISTRY_KEY *key;
REGVAL_CTR *values; REGVAL_CTR *values;
BOOL write_result; BOOL write_result;
char *valuename; char *valuename;
if ( !key ) if ( !info )
return WERR_BADFID; return WERR_BADFID;
key = info->key;
/* access checks first */ /* access checks first */
@@ -1447,7 +1476,9 @@ WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct
if ( !write_result ) if ( !write_result )
return WERR_REG_IO_FAILURE; return WERR_REG_IO_FAILURE;
TALLOC_FREE(info->value_cache);
return WERR_OK; return WERR_OK;
} }