summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/registry/reg_frontend.c54
-rw-r--r--source3/rpc_server/srv_winreg_nt.c169
2 files changed, 100 insertions, 123 deletions
diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c
index 1c8859982d..b361359985 100644
--- a/source3/registry/reg_frontend.c
+++ b/source3/registry/reg_frontend.c
@@ -321,60 +321,6 @@ NTSTATUS registry_fetch_values(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
}
/***********************************************************************
- 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
underlying registry backend
***********************************************************************/
diff --git a/source3/rpc_server/srv_winreg_nt.c b/source3/rpc_server/srv_winreg_nt.c
index 5342a9512c..ffce49cd9c 100644
--- a/source3/rpc_server/srv_winreg_nt.c
+++ b/source3/rpc_server/srv_winreg_nt.c
@@ -32,6 +32,7 @@ static struct generic_mapping reg_generic_map =
struct regkey_info {
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;
}
+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
@@ -382,7 +400,8 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
uint32_t *data_size, uint32_t *value_length)
{
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;
uint8_t *outbuf;
@@ -391,9 +410,11 @@ WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
BOOL free_buf = False;
BOOL free_prs = False;
- if ( !regkey )
+ if ( !info )
return WERR_BADFID;
+ regkey = info->key;
+
*value_length = *type = 0;
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;
}
else {
- /* HKPT calls can be handled out of reg_dynamic.c with the
- * hkpt_params handler */
-
- REGVAL_CTR *regvals;
+ REGISTRY_VALUE *val = NULL;
uint32 i;
- if (!(regvals = TALLOC_ZERO_P(p->mem_ctx, REGVAL_CTR))) {
- return WERR_NOMEM;
- }
-
- /*
- * Don't use fetch_reg_values_specific here, there is too much
- * memory copying around. I'll re-add the cache later. VL
- */
+ status = fill_value_cache(info);
- if (fetch_reg_values(regkey, regvals) == -1) {
- TALLOC_FREE(regvals);
- return WERR_BADFILE;
+ if (!(W_ERROR_IS_OK(status))) {
+ return status;
}
-
- for (i=0; i<regvals->num_values; i++) {
- if (strequal(regvals->values[i]->valuename,
+
+ for (i=0; i<info->value_cache->num_values; i++) {
+ if (strequal(info->value_cache->values[i]->valuename,
value_name.name)) {
+ val = info->value_cache->values[i];
break;
}
}
- if (i == regvals->num_values) {
- TALLOC_FREE(regvals);
+ if (val == NULL) {
+ if (data_size) {
+ *data_size = 0;
+ }
+ if (value_length) {
+ *value_length = 0;
+ }
return WERR_BADFILE;
}
- outbuf = regvals->values[i]->data_p;
- outbuf_size = regvals->values[i]->size;
- *type = regvals->values[i]->type;
+ outbuf = val->data_p;
+ outbuf_size = val->size;
+ *type = val->type;
}
*value_length = outbuf_size;
@@ -596,31 +612,40 @@ done:
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;
- REGISTRY_KEY *regkey = find_regkey_by_hnd( p, handle );
- REGISTRY_VALUE *val;
+ struct regkey_info *info = find_regkey_info_by_hnd( p, handle );
+ REGISTRY_KEY *regkey;
+ REGISTRY_VALUE *val = NULL;
- if ( !regkey )
- return WERR_BADFID;
+ if ( !info )
+ return WERR_BADFID;
if ( !name )
return WERR_INVALID_PARAM;
+
+ regkey = info->key;
- DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n", regkey->name));
+ DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
+ regkey->name));
- if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
- status = WERR_NO_MORE_ITEMS;
- goto done;
+ status = fill_value_cache(info);
+ if (!W_ERROR_IS_OK(status)) {
+ return status;
}
- DEBUG(10,("_winreg_EnumValue: retrieved value named [%s]\n", val->valuename));
-
- /* subkey has the string name now */
-
- if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
- status = WERR_NOMEM;
+ if (enum_index >= info->value_cache->num_values) {
+ return WERR_BADFILE;
+ }
+
+ val = info->value_cache->values[enum_index];
+
+ if (!(name->name = talloc_strdup(p->mem_ctx, val->valuename))) {
+ return WERR_NOMEM;
}
if (type != NULL) {
@@ -629,33 +654,26 @@ WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t
if (data != NULL) {
if ((data_size == NULL) || (value_length == NULL)) {
- status = WERR_INVALID_PARAM;
- goto done;
+ return WERR_INVALID_PARAM;
}
- if (regval_size(val) > *data_size) {
- status = WERR_MORE_DATA;
- goto done;
+ if (val->size > *data_size) {
+ return WERR_MORE_DATA;
}
- memcpy( data, regval_data_p(val), regval_size(val) );
- status = WERR_OK;
+ memcpy( data, val->data_p, val->size );
}
if (value_length != NULL) {
- *value_length = regval_size( val );
+ *value_length = val->size;
}
if (data_size != NULL) {
- *data_size = regval_size( val );
+ *data_size = val->size;
}
-done:
- free_registry_value( val );
-
- return status;
+ return WERR_OK;
}
-
/*******************************************************************
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)
{
- 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;
BOOL write_result;
- char *valuename;
- if ( !key )
+ if ( !info )
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 */
if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
return WERR_ACCESS_DENIED;
- /* verify the 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));
+ DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name,
+ name.name));
if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
return WERR_NOMEM;
@@ -1303,7 +1326,8 @@ WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct wi
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 */
@@ -1313,7 +1337,9 @@ WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct wi
if ( !write_result )
return WERR_REG_IO_FAILURE;
-
+
+ TALLOC_FREE(info->value_cache);
+
return WERR_OK;
}
@@ -1411,13 +1437,16 @@ done:
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;
BOOL write_result;
char *valuename;
- if ( !key )
+ if ( !info )
return WERR_BADFID;
+
+ key = info->key;
/* access checks first */
@@ -1447,7 +1476,9 @@ WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct
if ( !write_result )
return WERR_REG_IO_FAILURE;
-
+
+ TALLOC_FREE(info->value_cache);
+
return WERR_OK;
}