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:
committed by
Gerald (Jerry) Carter
parent
0ed3a21fcc
commit
81bd816fa2
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user