[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[gd/samba/.git] / source / utils / net_rpc_registry.c
index b439f50ee44d1b040d69b2870c0be5f26907dd8d..873cb7b4597e2ee1ae05bd1023d1af1d13089d0b 100644 (file)
@@ -1,8 +1,7 @@
 /* 
    Samba Unix/Linux SMB client library 
    Distributed SMB/CIFS Server Management Utility 
-
-   Copyright (C) Gerald (Jerry) Carter          2005-2006
+   Copyright (C) Gerald (Jerry) Carter          2005
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "regfio.h"
 #include "reg_objects.h"
 
-static BOOL reg_hive_key(const char *fullname, uint32 *reg_type,
-                        const char **key_name)
-{
-       const char *sep;
-       ptrdiff_t len;
-
-       sep = strchr_m(fullname, '\\');
-
-       if (sep != NULL) {
-               len = sep - fullname;
-               *key_name = sep+1;
-       }
-       else {
-               len = strlen(fullname);
-               *key_name = "";
-       }
-
-       if (strnequal(fullname, "HKLM", len) ||
-           strnequal(fullname, "HKEY_LOCAL_MACHINE", len))
-               (*reg_type) = HKEY_LOCAL_MACHINE;
-       else if (strnequal(fullname, "HKCR", len) ||
-                strnequal(fullname, "HKEY_CLASSES_ROOT", len))
-               (*reg_type) = HKEY_CLASSES_ROOT;
-       else if (strnequal(fullname, "HKU", len) ||
-                strnequal(fullname, "HKEY_USERS", len))
-               (*reg_type) = HKEY_USERS;
-       else if (strnequal(fullname, "HKPD", len) ||
-                strnequal(fullname, "HKEY_PERFORMANCE_DATA", len))
-               (*reg_type) = HKEY_PERFORMANCE_DATA;
-       else {
-               DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
-                         fullname));
-               return False;
-       }
-
-       return True;
-}
-
-static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
-                                struct rpc_pipe_client *pipe_hnd,
-                                const char *name, uint32 access_mask,
-                                struct policy_handle *hive_hnd,
-                                struct policy_handle *key_hnd)
-{
-       uint32 hive;
-       NTSTATUS status;
-       struct winreg_String key;
-
-       if (!reg_hive_key(name, &hive, &key.name)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
-                                      hive_hnd);
-       if (!(NT_STATUS_IS_OK(status))) {
-               return status;
-       }
-
-       status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
-                                      access_mask, key_hnd);
-       if (!(NT_STATUS_IS_OK(status))) {
-               rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd);
-               return status;
-       }
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
-                                 struct rpc_pipe_client *pipe_hnd,
-                                 struct policy_handle *key_hnd,
-                                 uint32 *pnum_keys, char ***pnames,
-                                 char ***pclasses, NTTIME ***pmodtimes)
-{
-       TALLOC_CTX *mem_ctx;
-       NTSTATUS status;
-       uint32 num_subkeys, max_subkeylen, max_classlen;
-       uint32 num_values, max_valnamelen, max_valbufsize;
-       uint32 i;
-       NTTIME last_changed_time;
-       uint32 secdescsize;
-       struct winreg_String classname;
-       char **names, **classes;
-       NTTIME **modtimes;
-
-       if (!(mem_ctx = talloc_new(ctx))) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ZERO_STRUCT(classname);
-       status = rpccli_winreg_QueryInfoKey(
-               pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
-               &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
-               &max_valbufsize, &secdescsize, &last_changed_time );
-
-       if (!NT_STATUS_IS_OK(status)) {
-               goto error;
-       }
-
-       if (num_subkeys == 0) {
-               *pnum_keys = 0;
-               TALLOC_FREE(mem_ctx);
-               return NT_STATUS_OK;
-       }
-
-       if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
-           (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
-           (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
-                                           num_subkeys)))) {
-               status = NT_STATUS_NO_MEMORY;
-               goto error;
-       }
-
-       for (i=0; i<num_subkeys; i++) {
-               char c, n;
-               struct winreg_StringBuf class_buf;
-               struct winreg_StringBuf name_buf;
-               NTTIME modtime;
-
-               c = '\0';
-               class_buf.name = &c;
-               class_buf.size = max_classlen+2;
-
-               n = '\0';
-               name_buf.name = &n;
-               name_buf.size = max_subkeylen+2;
-
-               ZERO_STRUCT(modtime);
-
-               status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
-                                              i, &name_buf, &class_buf,
-                                              &modtime);
-               
-               if (W_ERROR_EQUAL(ntstatus_to_werror(status),
-                                 WERR_NO_MORE_ITEMS) ) {
-                       status = NT_STATUS_OK;
-                       break;
-               }
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto error;
-               }
-
-               classes[i] = NULL;
-
-               if (class_buf.name &&
-                   (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto error;
-               }
-
-               if (!(names[i] = talloc_strdup(names, name_buf.name))) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto error;
-               }
-
-               if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
-                              modtimes, &modtime, sizeof(modtime))))) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto error;
-               }
-       }
-
-       *pnum_keys = num_subkeys;
-
-       if (pnames) {
-               *pnames = talloc_move(ctx, &names);
-       }
-       if (pclasses) {
-               *pclasses = talloc_move(ctx, &classes);
-       }
-       if (pmodtimes) {
-               *pmodtimes = talloc_move(ctx, &modtimes);
-       }
-
-       status = NT_STATUS_OK;
-
- error:
-       TALLOC_FREE(mem_ctx);
-       return status;
-}
-
-static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
-                                   struct rpc_pipe_client *pipe_hnd,
-                                   struct policy_handle *key_hnd,
-                                   uint32 *pnum_values, char ***pvalnames,
-                                   struct registry_value ***pvalues)
-{
-       TALLOC_CTX *mem_ctx;
-       NTSTATUS status;
-       uint32 num_subkeys, max_subkeylen, max_classlen;
-       uint32 num_values, max_valnamelen, max_valbufsize;
-       uint32 i;
-       NTTIME last_changed_time;
-       uint32 secdescsize;
-       struct winreg_String classname;
-       struct registry_value **values;
-       char **names;
-
-       if (!(mem_ctx = talloc_new(ctx))) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ZERO_STRUCT(classname);
-       status = rpccli_winreg_QueryInfoKey(
-               pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
-               &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
-               &max_valbufsize, &secdescsize, &last_changed_time );
-
-       if (!NT_STATUS_IS_OK(status)) {
-               goto error;
-       }
-
-       if (num_values == 0) {
-               *pnum_values = 0;
-               TALLOC_FREE(mem_ctx);
-               return NT_STATUS_OK;
-       }
-
-       if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
-           (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
-                                    num_values)))) {
-               status = NT_STATUS_NO_MEMORY;
-               goto error;
-       }
-
-       for (i=0; i<num_values; i++) {
-               enum winreg_Type type = REG_NONE;
-               uint8 *data = NULL;
-               uint32 data_size;
-               uint32 value_length;
-
-               char n;
-               struct winreg_ValNameBuf name_buf;
-               WERROR err;
-
-               n = '\0';
-               name_buf.name = &n;
-               name_buf.size = max_valnamelen + 2;
-
-               data_size = max_valbufsize;
-               data = (uint8 *)TALLOC(mem_ctx, data_size);
-               value_length = 0;
-
-               status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
-                                                i, &name_buf, &type,
-                                                data, &data_size,
-                                                &value_length );
-
-               if ( W_ERROR_EQUAL(ntstatus_to_werror(status),
-                                  WERR_NO_MORE_ITEMS) ) {
-                       status = NT_STATUS_OK;
-                       break;
-               }
-
-               if (!(NT_STATUS_IS_OK(status))) {
-                       goto error;
-               }
-
-               if (name_buf.name == NULL) {
-                       status = NT_STATUS_INVALID_PARAMETER;
-                       goto error;
-               }
-
-               if (!(names[i] = talloc_strdup(names, name_buf.name))) {
-                       status = NT_STATUS_NO_MEMORY;
-                       goto error;
-               }
-
-               err = registry_pull_value(values, &values[i], type, data,
-                                         data_size, value_length);
-               if (!W_ERROR_IS_OK(err)) {
-                       status = werror_to_ntstatus(err);
-                       goto error;
-               }
-       }
-
-       *pnum_values = num_values;
-
-       if (pvalnames) {
-               *pvalnames = talloc_move(ctx, &names);
-       }
-       if (pvalues) {
-               *pvalues = talloc_move(ctx, &values);
-       }
-
-       status = NT_STATUS_OK;
-
- error:
-       TALLOC_FREE(mem_ctx);
-       return status;
-}
-
-static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
-                                 struct rpc_pipe_client *pipe_hnd,
-                                 struct policy_handle *key_hnd,
-                                 const char *name,
-                                 const struct registry_value *value)
-{
-       struct winreg_String name_string;
-       DATA_BLOB blob;
-       NTSTATUS result;
-       WERROR err;
-
-       err = registry_push_value(mem_ctx, value, &blob);
-       if (!W_ERROR_IS_OK(err)) {
-               return werror_to_ntstatus(err);
-       }
-
-       name_string.name = name;
-       result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
-                                       name_string, value->type,
-                                       blob.data, blob.length);
-       TALLOC_FREE(blob.data);
-       return result;
-}
-
-static NTSTATUS rpc_registry_setvalue_internal(const DOM_SID *domain_sid,
-                                              const char *domain_name, 
-                                              struct cli_state *cli,
-                                              struct rpc_pipe_client *pipe_hnd,
-                                              TALLOC_CTX *mem_ctx, 
-                                              int argc,
-                                              const char **argv )
-{
-       struct policy_handle hive_hnd, key_hnd;
-       NTSTATUS status;
-       struct registry_value value;
-
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
-                                 &hive_hnd, &key_hnd);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_openkey failed: %s\n",
-                         nt_errstr(status));
-               return status;
-       }
-
-       if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
-               d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       if (strequal(argv[2], "dword")) {
-               value.type = REG_DWORD;
-               value.v.dword = strtoul(argv[3], NULL, 10);
-       }
-       else if (strequal(argv[2], "sz")) {
-               value.type = REG_SZ;
-               value.v.sz.len = strlen(argv[3])+1;
-               value.v.sz.str = CONST_DISCARD(char *, argv[3]);
-       }
-       else {
-               d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
-               status = NT_STATUS_NOT_IMPLEMENTED;
-               goto error;
-       }
-
-       status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
-                                  argv[1], &value);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_setvalue failed: %s\n",
-                         nt_errstr(status));
-       }
-
- error:
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
-
-       return NT_STATUS_OK;
-}
-
-static int rpc_registry_setvalue( int argc, const char **argv )
-{
-       if (argc < 4) {
-               d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
-                         "<valuename> <type> [<val>]+\n");
-               return -1;
-       }
-
-       return run_rpc_command( NULL, PI_WINREG, 0, 
-               rpc_registry_setvalue_internal, argc, argv );
-}
-
-static NTSTATUS rpc_registry_deletevalue_internal(const DOM_SID *domain_sid,
-                                                 const char *domain_name, 
-                                                 struct cli_state *cli,
-                                                 struct rpc_pipe_client *pipe_hnd,
-                                                 TALLOC_CTX *mem_ctx, 
-                                                 int argc,
-                                                 const char **argv )
-{
-       struct policy_handle hive_hnd, key_hnd;
-       NTSTATUS status;
-       struct winreg_String valuename;
-
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
-                                 &hive_hnd, &key_hnd);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_openkey failed: %s\n",
-                         nt_errstr(status));
-               return status;
-       }
-
-       valuename.name = argv[1];
-
-       status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
-                                          valuename);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_deletevalue failed: %s\n",
-                         nt_errstr(status));
-       }
-
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
-
-       return NT_STATUS_OK;
-}
-
-static int rpc_registry_deletevalue( int argc, const char **argv )
-{
-       if (argc != 2) {
-               d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
-                         "<valuename>\n");
-               return -1;
-       }
-
-       return run_rpc_command( NULL, PI_WINREG, 0, 
-               rpc_registry_deletevalue_internal, argc, argv );
-}
-
-static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
-                                               const char *domain_name, 
-                                               struct cli_state *cli,
-                                               struct rpc_pipe_client *pipe_hnd,
-                                               TALLOC_CTX *mem_ctx, 
-                                               int argc,
-                                               const char **argv )
-{
-       uint32 hive;
-       struct policy_handle hive_hnd, key_hnd;
-       struct winreg_String key, keyclass;
-       enum winreg_CreateAction action;
-       NTSTATUS status;
-
-       if (!reg_hive_key(argv[0], &hive, &key.name)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
-                                      REG_KEY_READ|REG_KEY_WRITE,
-                                      &hive_hnd);
-       if (!(NT_STATUS_IS_OK(status))) {
-               return status;
-       }
-
-       action = REG_ACTION_NONE;
-       keyclass.name = "";
-
-       status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
-                                        keyclass, 0, REG_KEY_READ, NULL,
-                                        &key_hnd, &action);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "createkey returned %s\n",
-                         nt_errstr(status));
-               rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
-               return status;
-       }
-
-       switch (action) {
-               case REG_ACTION_NONE:
-                       d_printf("createkey did nothing -- huh?\n");
-                       break;
-               case REG_CREATED_NEW_KEY:
-                       d_printf("createkey created %s\n", argv[0]);
-                       break;
-               case REG_OPENED_EXISTING_KEY:
-                       d_printf("createkey opened existing %s\n", argv[0]);
-                       break;
-       }
-
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
-
-       return status;
-}
-
-static int rpc_registry_createkey( int argc, const char **argv )
-{
-       if (argc != 1) {
-               d_fprintf(stderr, "usage: net rpc registry createkey <key>\n");
-               return -1;
-       }
-
-       return run_rpc_command( NULL, PI_WINREG, 0, 
-               rpc_registry_createkey_internal, argc, argv );
-}
+/********************************************************************
+********************************************************************/
 
-static NTSTATUS rpc_registry_deletekey_internal(const DOM_SID *domain_sid,
-                                               const char *domain_name, 
-                                               struct cli_state *cli,
-                                               struct rpc_pipe_client *pipe_hnd,
-                                               TALLOC_CTX *mem_ctx, 
-                                               int argc,
-                                               const char **argv )
+char* dump_regval_type( uint32 type )
 {
-       uint32 hive;
-       struct policy_handle hive_hnd;
-       struct winreg_String key;
-       NTSTATUS status;
-
-       if (!reg_hive_key(argv[0], &hive, &key.name)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, REG_KEY_WRITE,
-                                      &hive_hnd);
-       if (!(NT_STATUS_IS_OK(status))) {
-               return status;
-       }
-
-       status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key);
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "deletekey returned %s\n",
-                         nt_errstr(status));
+       static fstring string;
+       
+       switch (type) {
+       case REG_SZ:
+               fstrcpy( string, "REG_SZ" );
+               break;
+       case REG_MULTI_SZ:
+               fstrcpy( string, "REG_MULTI_SZ" );
+               break;
+       case REG_EXPAND_SZ:
+               fstrcpy( string, "REG_EXPAND_SZ" );
+               break;
+       case REG_DWORD:
+               fstrcpy( string, "REG_DWORD" );
+               break;
+       case REG_BINARY:
+               fstrcpy( string, "REG_BINARY" );
+               break;
+       default:
+               fstr_sprintf( string, "UNKNOWN [%d]", type );
        }
-
-       return status;
+       
+       return string;
 }
+/********************************************************************
+********************************************************************/
 
-static int rpc_registry_deletekey( int argc, const char **argv )
+void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
 {
-       if (argc != 1) {
-               d_fprintf(stderr, "usage: net rpc registry deletekey <key>\n");
-               return -1;
+       pstring string;
+       uint32 value;
+       
+       switch (type) {
+       case REG_SZ:
+               rpcstr_pull( string, buffer->buffer, sizeof(string), -1, STR_TERMINATE );
+               d_printf("%s\n", string);
+               break;
+       case REG_MULTI_SZ:
+               d_printf("\n");
+               break;
+       case REG_DWORD:
+               value = IVAL( buffer->buffer, 0 );
+               d_printf( "0x%x\n", value );
+               break;
+       case REG_BINARY:
+               d_printf("\n");
+               break;
+       
+       
+       default:
+               d_printf( "\tUnknown type [%d]\n", type );
        }
-
-       return run_rpc_command( NULL, PI_WINREG, 0, 
-               rpc_registry_deletekey_internal, argc, argv );
 }
 
 /********************************************************************
@@ -577,90 +92,104 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
                                                int argc,
                                                const char **argv )
 {
+       WERROR result = WERR_GENERAL_FAILURE;
+       uint32 hive;
+       pstring subpath;
        POLICY_HND pol_hive, pol_key; 
-       NTSTATUS status;
-       uint32 num_subkeys = 0;
-       uint32 num_values = 0;
-       char **names = NULL, **classes = NULL;
-       NTTIME **modtimes = NULL;
-       uint32 i;
-       struct registry_value **values = NULL;
+       uint32 idx;
        
        if (argc != 1 ) {
                d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
                d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
                return NT_STATUS_OK;
        }
-
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
-                                 &pol_hive, &pol_key);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_openkey failed: %s\n",
-                         nt_errstr(status));
-               return status;
+       
+       if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
+               d_fprintf(stderr, "invalid registry path\n");
+               return NT_STATUS_OK;
        }
-
-       status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
-                                  &names, &classes, &modtimes);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "enumerating keys failed: %s\n",
-                         nt_errstr(status));
-               return status;
+       
+       /* open the top level hive and then the registry key */
+       
+       result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
+       if ( !W_ERROR_IS_OK(result) ) {
+               d_fprintf(stderr, "Unable to connect to remote registry\n");
+               return werror_to_ntstatus(result);
        }
-
-       for (i=0; i<num_subkeys; i++) {
-               d_printf("Keyname   = %s\n", names[i]);
-               d_printf("Modtime   = %s\n", modtimes[i]
-                        ? http_timestring(nt_time_to_unix(*modtimes[i]))
-                        : "None");
-               d_printf("\n" );
+       
+       if ( strlen( subpath ) != 0 ) {
+               result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
+               if ( !W_ERROR_IS_OK(result) ) {
+                       d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
+                       return werror_to_ntstatus(result);
+               }
        }
+       
+       /* get the subkeys */
+       
+       result = WERR_OK;
+       idx = 0;
+       while ( W_ERROR_IS_OK(result) ) {
+               time_t modtime;
+               fstring keyname, classname;
+               
+               result = rpccli_reg_enum_key(pipe_hnd, mem_ctx, &pol_key, idx, 
+                       keyname, classname, &modtime );
+                       
+               if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
+                       result = WERR_OK;
+                       break;
+               }
+                       
+               d_printf("Keyname   = %s\n", keyname );
+               d_printf("Classname = %s\n", classname );
+               d_printf("Modtime   = %s\n", http_timestring(modtime) );
+               d_printf("\n" );
 
-       status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
-                                    &names, &values);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "enumerating values failed: %s\n",
-                         nt_errstr(status));
-               return status;
+               idx++;
        }
 
-       for (i=0; i<num_values; i++) {
-               struct registry_value *v = values[i];
-               d_printf("Valuename  = %s\n", names[i]);
-               d_printf("Type       = %s\n",
-                        reg_type_lookup(v->type));
-               switch(v->type) {
-               case REG_DWORD:
-                       d_printf("Value      = %d\n", v->v.dword);
-                       break;
-               case REG_SZ:
-               case REG_EXPAND_SZ:
-                       d_printf("Value      = \"%s\"\n", v->v.sz.str);
-                       break;
-               case REG_MULTI_SZ: {
-                       uint32 j;
-                       for (j = 0; j < v->v.multi_sz.num_strings; j++) {
-                               d_printf("Value[%3.3d] = \"%s\"\n", j,
-                                        v->v.multi_sz.strings[j]);
-                       }
-                       break;
-               }
-               case REG_BINARY:
-                       d_printf("Value      = %d bytes\n",
-                                (int)v->v.binary.length);
-                       break;
-               default:
-                       d_printf("Value      = <unprintable>\n");
+       if ( !W_ERROR_IS_OK(result) )
+               goto out;
+       
+       /* get the values */
+       
+       result = WERR_OK;
+       idx = 0;
+       while ( W_ERROR_IS_OK(result) ) {
+               uint32 type;
+               fstring name;
+               REGVAL_BUFFER value;
+               
+               fstrcpy( name, "" );
+               ZERO_STRUCT( value );
+               
+               result = rpccli_reg_enum_val(pipe_hnd, mem_ctx, &pol_key, idx, 
+                       name, &type, &value );
+                       
+               if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
+                       result = WERR_OK;
                        break;
                }
                        
-               d_printf("\n");
-       }
+               d_printf("Valuename  = %s\n", name );
+               d_printf("Type       = %s\n", dump_regval_type(type) );
+               d_printf("Data       = " );
+               dump_regval_buffer( type, &value );
+               d_printf("\n" );
 
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
+               idx++;
+       }
+       
+       
+out:
+       /* cleanup */
+       
+       if ( strlen( subpath ) != 0 )
+               rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
 
-       return status;
+       return werror_to_ntstatus(result);
 }
 
 /********************************************************************
@@ -684,35 +213,46 @@ static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
                                        const char **argv )
 {
        WERROR result = WERR_GENERAL_FAILURE;
+       uint32 hive;
+       pstring subpath;
        POLICY_HND pol_hive, pol_key; 
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-       struct winreg_String filename;
        
        if (argc != 2 ) {
                d_printf("Usage:    net rpc backup <path> <file> \n");
                return NT_STATUS_OK;
        }
        
-       status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
-                                 &pol_hive, &pol_key);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_fprintf(stderr, "registry_openkey failed: %s\n",
-                         nt_errstr(status));
-               return status;
+       if ( !reg_split_hive( argv[0], &hive, subpath ) ) {
+               d_fprintf(stderr, "invalid registry path\n");
+               return NT_STATUS_OK;
        }
-
-       filename.name = argv[1];
-       status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL  );
+       
+       /* open the top level hive and then the registry key */
+       
+       result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
+       if ( !W_ERROR_IS_OK(result) ) {
+               d_fprintf(stderr, "Unable to connect to remote registry\n");
+               return werror_to_ntstatus(result);
+       }
+       
+       result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
+       if ( !W_ERROR_IS_OK(result) ) {
+               d_fprintf(stderr, "Unable to open [%s]\n", argv[0]);
+               return werror_to_ntstatus(result);
+       }
+       
+       result = rpccli_reg_save_key(pipe_hnd, mem_ctx, &pol_key, argv[1] );
        if ( !W_ERROR_IS_OK(result) ) {
                d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
        }
        
+       
        /* cleanup */
        
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
-       rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
 
-       return status;
+       return werror_to_ntstatus(result);
 }
 
 /********************************************************************
@@ -739,7 +279,7 @@ static void dump_values( REGF_NK_REC *nk )
 
        for ( i=0; i<nk->num_values; i++ ) {
                d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
-               d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
+               d_printf( "(%s) ", dump_regval_type( nk->values[i].type ) );
 
                data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
                switch ( nk->values[i].type ) {
@@ -949,27 +489,30 @@ out:
 /********************************************************************
 ********************************************************************/
 
+static int net_help_registry( int argc, const char **argv )
+{
+       d_printf("net rpc registry enumerate <path> [recurse]  Enumerate the subkeya and values for a given registry path\n");
+       d_printf("net rpc registry save <path> <file>          Backup a registry tree to a file on the server\n");
+       d_printf("net rpc registry dump <file>                 Dump the contents of a registry file to stdout\n");
+       
+       return -1;
+}
+
+/********************************************************************
+********************************************************************/
+
 int net_rpc_registry(int argc, const char **argv) 
 {
-       struct functable2 func[] = {
-               { "enumerate", rpc_registry_enumerate,
-                 "Enumerate registry keys and values" },
-               { "createkey",  rpc_registry_createkey,
-                 "Create a new registry key" },
-               { "deletekey",  rpc_registry_deletekey,
-                 "Delete a registry key" },
-               { "setvalue",  rpc_registry_setvalue,
-                 "Set a new registry value" },
-               { "deletevalue",  rpc_registry_deletevalue,
-                 "Delete a registry value" },
-               { "save", rpc_registry_save,
-                 "Save a registry file" },
-               { "dump", rpc_registry_dump,
-                 "Dump a registry file" },
-               { "copy", rpc_registry_copy,
-                 "Copy a registry file" },
-               {NULL, NULL, NULL}
+       struct functable func[] = {
+               {"enumerate", rpc_registry_enumerate},
+               {"save",      rpc_registry_save},
+               {"dump",      rpc_registry_dump},
+               {"copy",      rpc_registry_copy},
+               {NULL, NULL}
        };
        
-       return net_run_function2(argc, argv, "net rpc registry", func);
+       if ( argc )
+               return net_run_function( argc, argv, func, net_help_registry );
+               
+       return net_help_registry( argc, argv );
 }