r7908: * change REGISTRY_HOOK api to use const (fix compiler warning
authorGerald Carter <jerry@samba.org>
Sat, 25 Jun 2005 17:31:40 +0000 (17:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:58:03 +0000 (10:58 -0500)
  in init_registry_data()
* Add means of storing registry values in registry.tdb
* add builtin_registry_values[] array for REG_DWORD and REG_SZ
  values needed during startup
* Finish up RegDeleteValue() and RegSetValue()
* Finish up regdb_store_reg_values() and regdb_fetch_reg_values()

I can now create and retrieve values using regedit.exe on Win2k.

bin/net -S rain -U% rpc registry enumerate 'hklm\software\samba'
Valuename  = Version
Type       = REG_SZ
Data       = 3.0.20

Next is to do the virtual writes in reg_printing.c and I'll be
done with Print Migrator (yeah!  finally)

source/include/rpc_reg.h
source/registry/reg_db.c
source/registry/reg_eventlog.c
source/registry/reg_frontend.c
source/registry/reg_objects.c
source/registry/reg_printing.c
source/registry/reg_shares.c
source/rpc_parse/parse_reg.c
source/rpc_server/srv_reg_nt.c

index 7ef2696228218cbbd98f1317888e09e2f8710f4c..7d6469bc8e9a4d93a56694106d334e3f99827368 100644 (file)
  
 typedef struct {
        /* functions for enumerating subkeys and values */      
-       int     (*fetch_subkeys)( char *key, REGSUBKEY_CTR *subkeys);
-       int     (*fetch_values) ( char *key, REGVAL_CTR *val );
-       BOOL    (*store_subkeys)( char *key, REGSUBKEY_CTR *subkeys );
-       BOOL    (*store_values)( char *key, REGVAL_CTR *val );
+       int     (*fetch_subkeys)( const char *key, REGSUBKEY_CTR *subkeys);
+       int     (*fetch_values) ( const char *key, REGVAL_CTR *val );
+       BOOL    (*store_subkeys)( const char *key, REGSUBKEY_CTR *subkeys );
+       BOOL    (*store_values)( const char *key, REGVAL_CTR *val );
        BOOL    (*reg_access_check)( const char *keyname, uint32 requested, uint32 *granted, NT_USER_TOKEN *token );
 } REGISTRY_OPS;
 
@@ -252,7 +252,6 @@ typedef struct {
 } REG_Q_DELETE_VALUE;
 
 typedef struct {
-       POLICY_HND key_pol;
        WERROR status;
 } REG_R_DELETE_VALUE;
 
index af0a30b76c1dcb1f94cd698f26e1bcb62d0ad5ec..3f618fbba4d0f0d2dca9747fbc1a3be3b9b39de0 100644 (file)
 
 static TDB_CONTEXT *tdb_reg;
 
+#define VALUE_PREFIX   "SAMBA_REGVAL"
+
+static BOOL regdb_store_reg_keys( const char *keyname, REGSUBKEY_CTR *subkeys );
+static BOOL regdb_store_reg_values( const char *keyname, REGVAL_CTR *values);
+static int regdb_fetch_reg_keys( const char* key, REGSUBKEY_CTR *subkeys );
+static int regdb_fetch_reg_values( const char* key, REGVAL_CTR *values );
 
-static BOOL regdb_store_reg_keys( char *keyname, REGSUBKEY_CTR *ctr );
-static int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr );
 
 
 
@@ -56,7 +60,6 @@ static const char *builtin_registry_paths[] = {
        "HKCR",
         NULL };
 
-#if 0  /* not used yet */
 struct builtin_regkey_value {
        const char *path;
        const char *valuename;
@@ -67,10 +70,10 @@ struct builtin_regkey_value {
        } data;
 };
 
-static struct builtin_regkey_value builtin_values[] = {
+static struct builtin_regkey_value builtin_registry_values[] = {
        { "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",      "SystemRoot",   REG_SZ,         { "c:\\Windows" } },
+       { NULL, NULL, 0, { NULL } }
 };
-#endif
 
 #define REGVER_V1      1       /* first db version with write support */
        
@@ -83,8 +86,10 @@ static BOOL init_registry_data( void )
        pstring path, base, remaining;
        fstring keyname, subkeyname;
        REGSUBKEY_CTR   subkeys;
+       REGVAL_CTR values;
        int i;
        const char *p, *p2;
+       UNISTR2 data;
        
        /* loop over all of the predefined paths and add each component */
        
@@ -134,6 +139,39 @@ static BOOL init_registry_data( void )
                }
        }
 
+       /* loop over all of the predefined values and add each component */
+       
+       for ( i=0; builtin_registry_values[i].path != NULL; i++ ) {
+               regval_ctr_init( &values );
+               
+               regdb_fetch_reg_values( builtin_registry_values[i].path, &values );
+               switch( builtin_registry_values[i].type ) {
+                       case REG_DWORD:
+                               regval_ctr_addvalue( &values, 
+                                                    builtin_registry_values[i].valuename,
+                                                    REG_DWORD,
+                                                    (char*)&builtin_registry_values[i].data.dw_value,
+                                                    sizeof(uint32) );
+                               break;
+                               
+                       case REG_SZ:
+                               init_unistr2( &data, builtin_registry_values[i].data.string, UNI_STR_TERMINATE);
+                               regval_ctr_addvalue( &values, 
+                                                    builtin_registry_values[i].valuename,
+                                                    REG_SZ,
+                                                    (char*)data.buffer,
+                                                    data.uni_str_len*sizeof(uint16) );
+                               break;
+                       
+                       default:
+                               DEBUG(0,("init_registry_data: invalid value type in builtin_registry_values [%d]\n",
+                                       builtin_registry_values[i].type));
+               }
+               regdb_store_reg_values( builtin_registry_values[i].path, &values );
+               
+               regval_ctr_destroy( &values );
+       }
+       
        return True;
 }
 
@@ -197,7 +235,7 @@ static void normalize_reg_path( pstring keyname )
  fstrings
  ***********************************************************************/
  
-static BOOL regdb_store_reg_keys_internal( char *key, REGSUBKEY_CTR *ctr )
+static BOOL regdb_store_reg_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
 {
        TDB_DATA kbuf, dbuf;
        char *buffer, *tmpbuf;
@@ -263,7 +301,7 @@ done:
  do not currently exist
  ***********************************************************************/
 
-static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
+static BOOL regdb_store_reg_keys( const char *key, REGSUBKEY_CTR *ctr )
 {
        int num_subkeys, i;
        pstring path;
@@ -317,11 +355,10 @@ static BOOL regdb_store_reg_keys( char *key, REGSUBKEY_CTR *ctr )
 
 /***********************************************************************
  Retrieve an array of strings containing subkeys.  Memory should be 
- released by the caller.  The subkeys are stored in a catenated string
- of null terminated character strings
+ released by the caller.  
  ***********************************************************************/
 
-static int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr )
+static int regdb_fetch_reg_keys( const char* key, REGSUBKEY_CTR *ctr )
 {
        pstring path;
        uint32 num_items;
@@ -363,20 +400,105 @@ static int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr )
        return num_items;
 }
 
+/****************************************************************************
+ Unpack a list of registry values frem the TDB
+ ***************************************************************************/
+static int regdb_unpack_values(REGVAL_CTR *values, char *buf, int buflen)
+{
+       int             len = 0;
+       uint32          type;
+       pstring         valuename;
+       int             size;
+       uint8           *data_p;
+       uint32          num_values = 0;
+       int             i;
+       
+       
+       
+       /* loop and unpack the rest of the registry values */
+       
+       len += tdb_unpack(buf+len, buflen-len, "d", &num_values);
+       
+       for ( i=0; i<num_values; i++ ) {
+               /* unpack the next regval */
+               
+               len += tdb_unpack(buf+len, buflen-len, "fdB",
+                                 valuename,
+                                 &type,
+                                 &size,
+                                 &data_p);
+                               
+               /* add the new value */
+               
+               regval_ctr_addvalue( values, valuename, type, (const char *)data_p, size );
+
+               SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
+
+               DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
+       }
+
+       return len;
+}
+
+/****************************************************************************
+ Pack all values in all printer keys
+ ***************************************************************************/
+static int regdb_pack_values(REGVAL_CTR *values, char *buf, int buflen)
+{
+       int             len = 0;
+       int             i;
+       REGISTRY_VALUE  *val;
+       int             num_values = regval_ctr_numvals( values );
+
+       if ( !values )
+               return 0;
+
+       /* pack the number of values first */
+       
+       len += tdb_pack( buf+len, buflen-len, "d", num_values );
+       
+       /* loop over all values */
+               
+       for ( i=0; i<num_values; i++ ) {                        
+               val = regval_ctr_specific_value( values, i );
+               len += tdb_pack(buf+len, buflen-len, "fdB",
+                               regval_name(val),
+                               regval_type(val),
+                               regval_size(val),
+                               regval_data_p(val) );
+       }
+
+       return len;
+}
 
 /***********************************************************************
  Retrieve an array of strings containing subkeys.  Memory should be 
- released by the caller.  The subkeys are stored in a catenated string
- of null terminated character strings
+ released by the caller.
  ***********************************************************************/
 
-static int regdb_fetch_reg_values( char* key, REGVAL_CTR *val )
+static int regdb_fetch_reg_values( const char* key, REGVAL_CTR *values )
 {
-       int    num_vals = 0;
+       TDB_DATA data;
+       pstring keystr;
+       int len;
 
        DEBUG(10,("regdb_fetch_reg_values: Looking for value of key [%s] \n", key));
-
-       return num_vals;
+       
+       pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key );
+       normalize_reg_path( keystr );
+       
+       data = tdb_fetch_bystring( tdb_reg, keystr );
+       
+       if ( !data.dptr ) 
+               return 0;
+       
+       len = regdb_unpack_values( values, data.dptr, data.dsize );
+       
+       SAFE_FREE( data.dptr );
+       
+       return regval_ctr_numvals(values);
 }
 
 /***********************************************************************
@@ -384,9 +506,37 @@ static int regdb_fetch_reg_values( char* key, REGVAL_CTR *val )
  values in the registry.tdb
  ***********************************************************************/
 
-static BOOL regdb_store_reg_values( char *key, REGVAL_CTR *val )
+static BOOL regdb_store_reg_values( const char *key, REGVAL_CTR *values )
 {
-       return False;
+       TDB_DATA data;
+       pstring keystr;
+       int len, ret;
+       
+       DEBUG(10,("regdb_store_reg_values: Looking for value of key [%s] \n", key));
+       
+       ZERO_STRUCT( data );
+       
+       len = regdb_pack_values( values, data.dptr, data.dsize );
+       if ( len <= 0 ) {
+               DEBUG(0,("regdb_store_reg_values: unable to pack values. len <= 0\n"));
+               return False;
+       }
+       
+       data.dptr = SMB_MALLOC_ARRAY( char, len );
+       data.dsize = len;
+       
+       len = regdb_pack_values( values, data.dptr, data.dsize );
+       
+       SMB_ASSERT( len == data.dsize );
+       
+       pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key );
+       normalize_reg_path( keystr );
+       
+       ret = tdb_store_bystring(tdb_reg, keystr, data, TDB_REPLACE);
+       
+       SAFE_FREE( data.dptr );
+       
+       return ret != -1 ;
 }
 
 
index 4c3f144980e45724fdfb9c5077fd0b3702a2cbad..b20eb046db8034428140b31044b2458e92187c4d 100644 (file)
@@ -154,9 +154,9 @@ static int eventlog_subkey_values( char *key, REGVAL_CTR *val )
  the memory allocated here.
  **********************************************************************/
 
-static char* trim_eventlog_reg_path( char *path )
+static char* trim_eventlog_reg_path( const char *path )
 {
-       char *p;
+       const char *p;
        uint16 key_len = strlen(KEY_EVENTLOG);
        
        /* 
@@ -186,7 +186,7 @@ static char* trim_eventlog_reg_path( char *path )
  Enumerate registry subkey names given a registry path.  
  Caller is responsible for freeing memory to **subkeys
  *********************************************************************/
-static int eventlog_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
+static int eventlog_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
 {
     char       *path;
     BOOL               top_level = False;
@@ -251,7 +251,7 @@ static int eventlog_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
  Caller is responsible for freeing memory 
  *********************************************************************/
 
-static int eventlog_value_info( char *key, REGVAL_CTR *val )
+static int eventlog_value_info( const char *key, REGVAL_CTR *val )
 {
        char            *path;
        BOOL            top_level = False;
@@ -280,7 +280,7 @@ static int eventlog_value_info( char *key, REGVAL_CTR *val )
  people storing eventlog information directly via registry calls
  (for now at least)
  *********************************************************************/
-static BOOL eventlog_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
+static BOOL eventlog_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
 {
        return False;
 }
@@ -290,7 +290,7 @@ static BOOL eventlog_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
  people storing eventlog information directly via registry calls
  (for now at least)
  *********************************************************************/
-static BOOL eventlog_store_value( char *key, REGVAL_CTR *val )
+static BOOL eventlog_store_value( const char *key, REGVAL_CTR *val )
 {
        return False;
 }
index 9c7420ef8634537f18ecb55247b959b073a9b1a4..8b722ba1f57246961b70c7897fd06017532c19ee 100644 (file)
@@ -70,9 +70,6 @@ BOOL init_registry( void )
        return True;
 }
 
-
-
-
 /***********************************************************************
  High level wrapper function for storing registry subkeys
  ***********************************************************************/
@@ -81,8 +78,8 @@ BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
 {
        if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys )
                return key->hook->ops->store_subkeys( key->name, subkeys );
-       else
-               return False;
+               
+       return False;
 
 }
 
@@ -94,8 +91,8 @@ BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
 {
        if ( key->hook && key->hook->ops && key->hook->ops->store_values )
                return key->hook->ops->store_values( key->name, val );
-       else
-               return False;
+
+       return False;
 }
 
 
index 582a696529f1341bd2214e85cc5ed02ee59c87cd..7ee2cd841415aa59c89e40cace6aeed412ef4564 100644 (file)
@@ -114,7 +114,6 @@ BOOL regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname )
        }
        
        return False;
-
 }
 
 /***********************************************************************
@@ -276,9 +275,23 @@ TALLOC_CTX* regval_ctr_getctx( REGVAL_CTR *val )
        if ( !val )
                return NULL;
 
-       return val->ctx;
-}
+       return val->ctx; }
 
+/***********************************************************************
+ Check for the existance of a value
+ **********************************************************************/
+
+BOOL regval_ctr_key_exists( REGVAL_CTR *ctr, const char *value )
+{
+       int     i;
+       
+       for ( i=0; i<ctr->num_values; i++ ) {
+               if ( strequal( ctr->values[i]->valuename, value) )
+                       return True;
+       }
+       
+       return False;
+}
 /***********************************************************************
  Add a new registry value to the array
  **********************************************************************/
@@ -291,6 +304,10 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type,
        if ( !name )
                return ctr->num_values;
 
+       /* Delete the current value (if it exists) and add the new one */
+
+       regval_ctr_delvalue( ctr, name );
+
        /* allocate a slot in the array of pointers */
                
        if (  ctr->num_values == 0 )
@@ -366,7 +383,7 @@ int regval_ctr_delvalue( REGVAL_CTR *ctr, const char *name )
                return 0;
        
        for ( i=0; i<ctr->num_values; i++ ) {
-               if ( strcmp( ctr->values[i]->valuename, name ) == 0)
+               if ( strequal( ctr->values[i]->valuename, name ) )
                        break;
        }
        
@@ -376,15 +393,9 @@ int regval_ctr_delvalue( REGVAL_CTR *ctr, const char *name )
                return ctr->num_values;
        
        /* just shift everything down one */
-       
-       for ( /* use previous i */; i<(ctr->num_values-1); i++ )
-               memcpy( ctr->values[i], ctr->values[i+1], sizeof(REGISTRY_VALUE) );
-               
-       /* paranoia */
-       
-       ZERO_STRUCTP( ctr->values[i] );
-       
        ctr->num_values--;
+       if ( ctr->num_values )
+               memmove( ctr->values[i], ctr->values[i+1], sizeof(REGISTRY_VALUE)*(ctr->num_values-i) );
        
        return ctr->num_values;
 }
index 1ac91f4b90c15d0fda6ad8c3f6dd61e31fa0cc2d..30f2d746600dc6b9cb1e49626105cb0a6e5281cf 100644 (file)
@@ -49,9 +49,9 @@ static const char *top_level_keys[MAX_TOP_LEVEL_KEYS] = {
  the memory allocated here.
  **********************************************************************/
 
-static char* trim_reg_path( char *path )
+static char* trim_reg_path( const char *path )
 {
-       char *p;
+       const char *p;
        uint16 key_len = strlen(path);
        uint16 base_key_len;
 
@@ -837,7 +837,7 @@ static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CT
  Caller is responsible for freeing memory to **subkeys
  *********************************************************************/
  
-static int printing_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
+static int printing_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
 {
        char            *path;
        BOOL            top_level = False;
@@ -876,7 +876,7 @@ static int printing_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
  Caller is responsible for freeing memory 
  *********************************************************************/
 
-static int printing_value_info( char *key, REGVAL_CTR *val )
+static int printing_value_info( const char *key, REGVAL_CTR *val )
 {
        char            *path;
        BOOL            top_level = False;
@@ -908,7 +908,7 @@ static int printing_value_info( char *key, REGVAL_CTR *val )
  (for now at least)
  *********************************************************************/
 
-static BOOL printing_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
+static BOOL printing_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
 {
        return True;
 }
@@ -919,7 +919,7 @@ static BOOL printing_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
  (for now at least)
  *********************************************************************/
 
-static BOOL printing_store_value( char *key, REGVAL_CTR *val )
+static BOOL printing_store_value( const char *key, REGVAL_CTR *val )
 {
        return True;
 }
index 4531327d948a0e4f827fbc323e64b81df5c84e8a..85ac812101a282c02c3ab3ce20c01dbf848cd910 100644 (file)
@@ -34,9 +34,9 @@
  the memory allocated here.
  **********************************************************************/
 
-static char* trim_reg_path( char *path )
+static char* trim_reg_path( const char *path )
 {
-       char *p;
+       const char *p;
        uint16 key_len = strlen(KEY_SHARES);
        
        /* 
@@ -67,7 +67,7 @@ static char* trim_reg_path( char *path )
  Caller is responsible for freeing memory to **subkeys
  *********************************************************************/
  
-static int shares_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
+static int shares_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
 {
        char            *path;
        BOOL            top_level = False;
@@ -101,7 +101,7 @@ static int shares_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
  Caller is responsible for freeing memory 
  *********************************************************************/
 
-static int shares_value_info( char *key, REGVAL_CTR *val )
+static int shares_value_info( const char *key, REGVAL_CTR *val )
 {
        char            *path;
        BOOL            top_level = False;
@@ -134,7 +134,7 @@ static int shares_value_info( char *key, REGVAL_CTR *val )
  (for now at least)
  *********************************************************************/
 
-static BOOL shares_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
+static BOOL shares_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
 {
        return False;
 }
@@ -145,7 +145,7 @@ static BOOL shares_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
  (for now at least)
  *********************************************************************/
 
-static BOOL shares_store_value( char *key, REGVAL_CTR *val )
+static BOOL shares_store_value( const char *key, REGVAL_CTR *val )
 {
        return False;
 }
index 190f39eb79a5329adccc6c20985a2a9674696646..9048f0f58f507e32d7275837ae71261522495b38 100644 (file)
@@ -343,8 +343,6 @@ BOOL reg_io_q_delete_value(const char *desc, REG_Q_DELETE_VALUE *q_u,
 
        if(!prs_unistr4("name", ps, depth, &q_u->name))
                return False;
-       if(!prs_align(ps))
-               return False;
 
        return True;
 }
@@ -464,9 +462,6 @@ BOOL reg_io_q_query_key(const char *desc,  REG_Q_QUERY_KEY *q_u, prs_struct *ps,
        if(!prs_unistr4("key_class", ps, depth, &q_u->key_class))
                return False;
 
-       if(!prs_align(ps))
-               return False;
-
        return True;
 }
 
index 3b25f11359ec2b9b62a724fad5e2b7f84ab89141..0e4c49aa48c3b30a9999923464b2357398cfd7f5 100644 (file)
@@ -464,6 +464,7 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL
 
        regval_ctr_init( &regvals );
 
+       /* FIXME!!! Move these to a dynmanic lookup in the reg_fetch_values() */
        /* couple of hard coded registry values */
        
        if ( strequal(name, "RefusePasswordChange") ) {
@@ -544,20 +545,6 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL
                goto out;
        }
        
-       /* "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" */
-       
-       if ( strequal( name, "SystemRoot") ) {
-               value_length = push_ucs2( value, value, "c:\\windows", sizeof(value), STR_TERMINATE|STR_NOALIGN);               
-               regval_ctr_addvalue( &regvals, "SystemRoot", REG_SZ, value, value_length );
-
-               val = dup_registry_value( regval_ctr_specific_value( &regvals, 0 ) );
-       
-               status = WERR_OK;
-       
-               goto out;
-       }
-       
-       
        /* else fall back to actually looking up the value */
        
        for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
@@ -1311,6 +1298,7 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE  *q_u, REG_R_SET_VALUE *r
        REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
        REGVAL_CTR values;
        BOOL write_result;
+       fstring valuename;
 
        if ( !key )
                return WERR_BADFID;
@@ -1320,12 +1308,16 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE  *q_u, REG_R_SET_VALUE *r
        if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
                return WERR_ACCESS_DENIED;
                
+       rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
+
+               
        regval_ctr_init( &values );
        
        /* lookup the current values and add the new one */
        
        fetch_reg_values( key, &values );
-       /* FIXME!!!! regval_ctr_addvalue( &values, .... ); */
+       
+       regval_ctr_addvalue( &values, valuename, q_u->type, q_u->value.buffer, q_u->value.buf_len );
        
        /* now write to the registry backend */
        
@@ -1440,7 +1432,8 @@ WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE  *q_u, REG_R_DELETE
        REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->handle);
        REGVAL_CTR values;
        BOOL write_result;
-
+       fstring valuename;
+       
        if ( !key )
                return WERR_BADFID;
                
@@ -1448,13 +1441,16 @@ WERROR _reg_delete_value(pipes_struct *p, REG_Q_DELETE_VALUE  *q_u, REG_R_DELETE
        
        if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
                return WERR_ACCESS_DENIED;
-               
+
+       rpcstr_pull( valuename, q_u->name.string->buffer, sizeof(valuename), q_u->name.string->uni_str_len*2, 0 );
+
        regval_ctr_init( &values );
        
        /* lookup the current values and add the new one */
        
        fetch_reg_values( key, &values );
-       /* FIXME!!!! regval_ctr_delval( &values, .... ); */
+       
+       regval_ctr_delvalue( &values, valuename );
        
        /* now write to the registry backend */