r19872: Move the value cache to srv_winreg_nt.c. Fix some minor issues found while
authorVolker Lendecke <vlendec@samba.org>
Thu, 23 Nov 2006 22:58:50 +0000 (22:58 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:16:03 +0000 (12:16 -0500)
playing with regedit.exe.

Volker
(This used to be commit 81bd816fa2afe89261aff2f395e8d056b73e515c)

source3/registry/reg_frontend.c
source3/rpc_server/srv_winreg_nt.c

index 1c8859982def265da51b9748fb30cc3539532da5..b3613599859330adf3fadfa997cd0ad63e8f567c 100644 (file)
@@ -320,60 +320,6 @@ NTSTATUS registry_fetch_values(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
        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 
  underlying registry backend
index 5342a9512c8cbfff9b5a68153532a540937b3fa1..ffce49cd9c339668b5f70ed42478f15233e5e78a 100644 (file)
@@ -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;
 }