r128: Another registry update. Changes:
authorJelmer Vernooij <jelmer@samba.org>
Thu, 8 Apr 2004 22:39:47 +0000 (22:39 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:51:09 +0000 (12:51 -0500)
- Start with the LDB backend
- The API is now more windows-like, which should make it easier to use
  in rpc_server
- Added a GTK+ front-end
- Added some more IDL

More updates will follow, especially in the RPC field..
(This used to be commit 3adffa021779b26047a20f16a3c0b53d74751560)

19 files changed:
source4/Makefile.in
source4/include/doserr.h
source4/lib/ldb/include/proto.h
source4/lib/registry/TODO
source4/lib/registry/common/reg_interface.c
source4/lib/registry/common/reg_util.c
source4/lib/registry/common/registry.h
source4/lib/registry/config.m4
source4/lib/registry/reg_backend_dir/reg_backend_dir.c
source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c
source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c
source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
source4/lib/registry/reg_backend_wine/reg_backend_wine.c
source4/lib/registry/tools/gregedit.c [new file with mode: 0644]
source4/lib/registry/tools/regshell.c
source4/librpc/idl/winreg.idl
source4/rpc_server/winreg/rpc_winreg.c
source4/torture/rpc/winreg.c

index 8f9bad0da5c09ca07fbb0c323b67d582e426b2b1..d089bcbde9069683528913eadfc6fd88a116e061 100644 (file)
@@ -140,6 +140,7 @@ DCERPC_LIBS = @DCERPC_LIBS@
 
 REG_OBJS = @REG_OBJS@
 REG_LIBS = @REG_LIBS@
+GTK_LIBS = @GTK_LIBS@
 
 TORTURE_RAW_OBJS = @TORTURE_RAW_OBJS@
 
@@ -191,6 +192,7 @@ NDRDUMP_OBJS = utils/ndrdump.o utils/rewrite.o \
 NDRDUMP_LIBS = $(LIBSMB_LIBS) $(CONFIG_LIBS) $(LIBBASIC_LIBS)
 
 REGTREE_OBJ = $(REG_OBJS) lib/registry/tools/regtree.o $(LIBBASIC_OBJS) $(CONFIG_OBJS) $(LIBSMB_OBJS)
+GREGEDIT_OBJ = $(REG_OBJS) lib/registry/tools/gregedit.o $(LIBBASIC_OBJS) $(CONFIG_OBJS) $(LIBSMB_OBJS)
 REGSHELL_OBJ = $(REG_OBJS) lib/registry/tools/regshell.o $(LIBBASIC_OBJS) $(CONFIG_OBJS) $(LIBCMDLINE_OBJS) $(LIBSMB_OBJS)
 REGPATCH_OBJ = $(REG_OBJS) lib/registry/tools/regpatch.o $(LIBBASIC_OBJS) $(CONFIG_OBJS) $(LIBSMB_OBJS)
 REGDIFF_OBJ = $(REG_OBJS) lib/registry/tools/regdiff.o $(LIBBASIC_OBJS) $(CONFIG_OBJS) $(LIBSMB_OBJS)
@@ -350,6 +352,10 @@ bin/regtree@EXEEXT@: $(REGTREE_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(REGTREE_OBJ) $(LDFLAGS) $(LIBS) $(REG_LIBS)
 
+bin/gregedit@EXEEXT@: $(GREGEDIT_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLGS) -o $@ $(GREGEDIT_OBJ) $(LDFLAGS) $(LIBS) $(REG_LIBS) $(GTK_LIBS)
+
 bin/regpatch@EXEEXT@: $(REGPATCH_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(REGPATCH_OBJ) $(LDFLAGS) $(LIBS) $(REG_LIBS)
index 114366ff6e9e911b23d7d5e111def0ea5a0ee935..e3582889d8b80135995c35fe2b846503bfd91172 100644 (file)
 #define WERR_DFS_INTERNAL_ERROR         W_ERROR(NERR_BASE+590)
 #define WERR_DFS_CANT_CREATE_JUNCT      W_ERROR(NERR_BASE+569)
 
+
+#define WERR_FOOBAR WERR_GENERAL_FAILURE
+
 #endif /* _DOSERR_H */
index 8690d96fee547f0b084e0d37ec826bd4c7ae8271..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,126 +0,0 @@
-#ifndef _PROTO_H_
-#define _PROTO_H_
-
-/* This file is automatically generated with "make proto". DO NOT EDIT */
-
-
-/* The following definitions come from common/ldb.c  */
-
-struct ldb_context *ldb_connect(const char *url, unsigned int flags,
-                               const char *options[]);
-int ldb_close(struct ldb_context *ldb);
-int ldb_search(struct ldb_context *ldb, 
-              const char *base,
-              enum ldb_scope scope,
-              const char *expression,
-              const char *attrs[], struct ldb_message ***res);
-int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs);
-int ldb_add(struct ldb_context *ldb, 
-           const struct ldb_message *message);
-int ldb_modify(struct ldb_context *ldb, 
-              const struct ldb_message *message);
-int ldb_delete(struct ldb_context *ldb, const char *dn);
-const char *ldb_errstring(struct ldb_context *ldb);
-
-/* The following definitions come from common/ldb_ldif.c  */
-
-char *ldb_base64_encode(const char *buf, int len);
-int ldb_should_b64_encode(const struct ldb_val *val);
-int ldif_write(int (*fprintf_fn)(void *, const char *, ...), 
-              void *private,
-              const struct ldb_message *msg);
-void ldif_read_free(struct ldb_message *msg);
-struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private);
-struct ldb_message *ldif_read_file(FILE *f);
-struct ldb_message *ldif_read_string(const char *s);
-int ldif_write_file(FILE *f, const struct ldb_message *msg);
-
-/* The following definitions come from common/ldb_parse.c  */
-
-struct ldb_parse_tree *ldb_parse_tree(const char *s);
-void ldb_parse_tree_free(struct ldb_parse_tree *tree);
-
-/* The following definitions come from common/util.c  */
-
-void *realloc_array(void *ptr, size_t el_size, unsigned count);
-int list_find(const void *needle, 
-             const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn);
-
-/* The following definitions come from ldb_ldap/ldb_ldap.c  */
-
-struct ldb_context *lldb_connect(const char *url, 
-                                unsigned int flags, 
-                                const char *options[]);
-
-/* The following definitions come from ldb_tdb/ldb_index.c  */
-
-int ltdb_search_indexed(struct ldb_context *ldb, 
-                       const char *base,
-                       enum ldb_scope scope,
-                       struct ldb_parse_tree *tree,
-                       const char *attrs[], struct ldb_message ***res);
-int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg);
-int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg);
-
-/* The following definitions come from ldb_tdb/ldb_match.c  */
-
-int ldb_message_match(struct ldb_context *ldb, 
-                     struct ldb_message *msg,
-                     struct ldb_parse_tree *tree,
-                     const char *base,
-                     enum ldb_scope scope);
-
-/* The following definitions come from ldb_tdb/ldb_pack.c  */
-
-int ltdb_pack_data(struct ldb_context *ctx,
-                  const struct ldb_message *message,
-                  struct TDB_DATA *data);
-int ltdb_unpack_data(struct ldb_context *ctx,
-                    const struct TDB_DATA *data,
-                    struct ldb_message *message);
-
-/* The following definitions come from ldb_tdb/ldb_search.c  */
-
-int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr);
-int ltdb_has_wildcard(const struct ldb_val *val);
-void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg);
-int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg);
-int ltdb_search_dn(struct ldb_context *ldb, char *dn,
-                  const char *attrs[], struct ldb_message ***res);
-int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg,
-                         const char *attrs[], 
-                         unsigned int *count, 
-                         struct ldb_message ***res);
-int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs);
-int ltdb_search(struct ldb_context *ldb, const char *base,
-               enum ldb_scope scope, const char *expression,
-               const char *attrs[], struct ldb_message ***res);
-
-/* The following definitions come from ldb_tdb/ldb_tdb.c  */
-
-struct TDB_DATA ltdb_key(const char *dn);
-int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs);
-int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn);
-struct ldb_context *ltdb_connect(const char *url, 
-                                unsigned int flags, 
-                                const char *options[]);
-
-/* The following definitions come from ldb_tdb/ldbadd.c  */
-
-
-/* The following definitions come from ldb_tdb/ldbdel.c  */
-
-
-/* The following definitions come from ldb_tdb/ldbsearch.c  */
-
-
-/* The following definitions come from tools/ldbadd.c  */
-
-
-/* The following definitions come from tools/ldbdel.c  */
-
-
-/* The following definitions come from tools/ldbsearch.c  */
-
-
-#endif /*  _PROTO_H_  */
index ac467d00788fc5ee3c754450db13c2fbdcd9cf36..fc741cea40715588764671f59c2ea89da323a53d 100644 (file)
@@ -1,10 +1,6 @@
 - support subtrees
-- ../../, /bla/blie support in regshell
-- use memory pools?
-- get rid of all the nasty memory leaks..
-- security stuff
-- clean up code
-- rpc_server
+- ..\..\, \bla\blie support in regshell
+- finish rpc_server
 
 reg_backend_dir:
  - value support
@@ -15,9 +11,15 @@ reg_backend_nt4:
 reg_backend_rpc:
  - value enum support
  - write support
+ - rewrite
  
 reg_backend_ldb:
- - implement
+ - finish 
 
 reg_backend_wine.c:
- - implement
+ - finish 
+
+gregedit.c:
+ - support for editing values / adding values / deleting values
+ - support for adding/deleting keys
+ - support for security descriptors
index b6b38e9b62cc71002b0f9320e05bfe6f12a1813b..9c78ae55fb304d3835338985b540670d053a74da 100644 (file)
@@ -32,7 +32,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
 /* Register new backend */
 NTSTATUS registry_register(void *_function)  
 {
-       REG_OPS *functions = _function;
+       struct registry_ops *functions = _function;
        struct reg_init_function_entry *entry = backends;
 
        if (!functions || !functions->name) {
@@ -69,17 +69,19 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
 }
 
 /* Open a registry file/host/etc */
-REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_load)
+WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h)
 {
        struct reg_init_function_entry *entry;
        static BOOL reg_first_init = True;
        TALLOC_CTX *mem_ctx;
        REG_HANDLE *ret;
+       NTSTATUS status;
+       WERROR werr;
 
        if(reg_first_init) {
-               if (!NT_STATUS_IS_OK(register_subsystem("registry", registry_register))) {
-                       return False;
-               }
+               status = register_subsystem("registry", registry_register);
+               if (!NT_STATUS_IS_OK(status)) 
+                       return WERR_GENERAL_FAILURE;
 
                static_init_reg;
                reg_first_init = False;
@@ -89,7 +91,7 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo
        
        if (!entry) {
                DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
-               return NULL;
+               return WERR_GENERAL_FAILURE;
        }
        
        mem_ctx = talloc_init(backend);
@@ -99,31 +101,35 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo
        ret->functions = entry->functions;
        ret->backend_data = NULL;
        ret->mem_ctx = mem_ctx;
+       *h = ret;
 
        if(!entry->functions->open_registry) {
-               return ret;
+               return WERR_OK;
        }
        
-       if(entry->functions->open_registry(ret, location, try_full_load))
-               return ret;
+       werr = entry->functions->open_registry(ret, location, credentials);
+
+       if(W_ERROR_IS_OK(werr)) 
+               return WERR_OK;
 
        talloc_destroy(mem_ctx);
-       return NULL;
+       return werr;
 }
 
 /* Open a key 
  * First tries to use the open_key function from the backend
  * then falls back to get_subkey_by_name and later get_subkey_by_index 
  */
-REG_KEY *reg_open_key(REG_KEY *parent, const char *name)
+WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
 {
        char *fullname;
+       WERROR status;
        REG_KEY *ret = NULL;
        TALLOC_CTX *mem_ctx;
 
        if(!parent) {
                DEBUG(0, ("Invalid parent key specified"));
-               return NULL;
+               return WERR_INVALID_PARAM;
        }
 
        if(!parent->handle->functions->open_key && 
@@ -136,10 +142,10 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name)
 
                while(curbegin && *curbegin) {
                        if(curend)*curend = '\0';
-                       curkey = reg_key_get_subkey_by_name(curkey, curbegin);
-                       if(!curkey) {
+                       status = reg_key_get_subkey_by_name(curkey, curbegin, result);
+                       if(!NT_STATUS_IS_OK(status)) {
                                SAFE_FREE(orig);
-                               return NULL;
+                               return status;
                        }
                        if(!curend) break;
                        curbegin = curend + 1;
@@ -147,255 +153,287 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name)
                }
                SAFE_FREE(orig);
                
-               return curkey;
+               *result = curkey;
+               return WERR_OK;
        }
 
        mem_ctx = talloc_init("mem_ctx");
 
        fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name);
-
+\
 
        if(!parent->handle->functions->open_key) {
                DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
-               return NULL;
+               return WERR_NOT_SUPPORTED;
        }
 
-       ret = parent->handle->functions->open_key(parent->handle, fullname);
+       status = parent->handle->functions->open_key(parent->handle, fullname, result);
 
-       if(ret) {
-               ret->handle = parent->handle;
-               ret->path = fullname;
-               talloc_steal(mem_ctx, ret->mem_ctx, fullname);
+       if(!NT_STATUS_IS_OK(status)) {
+               talloc_destroy(mem_ctx);
+               return status;
        }
+               
+       ret->handle = parent->handle;
+       ret->path = fullname;
+       talloc_steal(mem_ctx, ret->mem_ctx, fullname);
 
        talloc_destroy(mem_ctx);
 
-       return ret;
+       *result = ret;
+
+       return WERR_OK;
 }
 
-REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx)
+WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
 {
-       REG_VAL *ret;
-
-       if(!key) return NULL;
+       if(!key) return WERR_INVALID_PARAM;
 
        if(!key->handle->functions->get_value_by_index) {
                if(!key->cache_values)
                        key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
                
                if(idx < key->cache_values_count && idx >= 0) {
-                       ret = reg_val_dup(key->cache_values[idx]);
+                       *val = reg_val_dup(key->cache_values[idx]);
                } else {
-                       return NULL;
+                       return WERR_NO_MORE_ITEMS;
                }
        } else {
-               ret = key->handle->functions->get_value_by_index(key, idx);
+               WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
+               if(!W_ERROR_IS_OK(status)) 
+                       return status;
        }
        
-       if(ret) {
-               ret->parent = key;
-               ret->handle = key->handle;
-       }
-
-       return ret;
+       (*val)->parent = key;
+       (*val)->handle = key->handle;
+       return WERR_OK;
 }
 
-int reg_key_num_subkeys(REG_KEY *key)
+WERROR reg_key_num_subkeys(REG_KEY *key, int *count)
 {
-       if(!key) return 0;
+       if(!key) return WERR_INVALID_PARAM;
        
        if(!key->handle->functions->num_subkeys) {
                if(!key->cache_subkeys) 
                        key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
 
-               return key->cache_subkeys_count;
+               *count = key->cache_subkeys_count;
+               return WERR_OK;
        }
 
-       return key->handle->functions->num_subkeys(key);
+       return key->handle->functions->num_subkeys(key, count);
 }
 
-int reg_key_num_values(REG_KEY *key)
+WERROR reg_key_num_values(REG_KEY *key, int *count)
 {
        
-       if(!key) return 0;
+       if(!key) return WERR_INVALID_PARAM;
        
        if(!key->handle->functions->num_values) {
                if(!key->handle->functions->fetch_values) {
                        DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name));
-                       return 0;
+                       return WERR_NOT_SUPPORTED;
                }
                
                if(!key->cache_values) 
                        key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
 
-               return key->cache_values_count;
+               *count = key->cache_values_count;
+               return WERR_OK;
        }
 
        
-       return key->handle->functions->num_values(key);
+       return key->handle->functions->num_values(key, count);
 }
 
-REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx)
+WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey)
 {
-       REG_KEY *ret = NULL;
-
-       if(!key) return NULL;
+       if(!key) return WERR_INVALID_PARAM;
 
        if(!key->handle->functions->get_subkey_by_index) {
                if(!key->cache_subkeys) 
                        key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
 
                if(idx < key->cache_subkeys_count) {
-                       ret = reg_key_dup(key->cache_subkeys[idx]);
+                       *subkey = reg_key_dup(key->cache_subkeys[idx]);
                } else {
-                       /* No such key ! */
-                       return NULL;
+                       return WERR_NO_MORE_ITEMS;
                }
        } else {
-               ret = key->handle->functions->get_subkey_by_index(key, idx);
+               WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey);
+               if(!NT_STATUS_IS_OK(status)) return status;
        }
 
-       if(ret && !ret->path) {
-               ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
-               ret->handle = key->handle;
-       }
+       (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
+       (*subkey)->handle = key->handle;
 
-       return ret;
+
+       return WERR_OK;;
 }
 
-REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name)
+WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey)
 {
-       int i, max;
+       int i;
        REG_KEY *ret = NULL;
+       WERROR error = WERR_OK;
 
-       if(!key) return NULL;
+       if(!key) return WERR_INVALID_PARAM;
 
        if(key->handle->functions->get_subkey_by_name) {
-               ret = key->handle->functions->get_subkey_by_name(key,name);
+               error = key->handle->functions->get_subkey_by_name(key,name,subkey);
        } else {
-               max = reg_key_num_subkeys(key);
-               for(i = 0; i < max; i++) {
-                       REG_KEY *v = reg_key_get_subkey_by_index(key, i);
-                       if(v && !strcmp(v->name, name)) {
-                               ret = v;
+               for(i = 0; W_ERROR_IS_OK(error); i++) {
+                       error = reg_key_get_subkey_by_index(key, i, subkey);
+                       if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
                                break;
                        }
-                       reg_key_free(v);
+                       reg_key_free(*subkey);
                }
-       }
 
-       if(ret && !ret->path) {
-               ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
-               ret->handle = key->handle;
        }
+
+       if(!W_ERROR_IS_OK(error) && W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
+               return error;
+
+       ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
+       ret->handle = key->handle;
+
+       *subkey = ret;
                
-       return ret
+       return WERR_OK
 }
 
-REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name)
+WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val)
 {
        int i, max;
        REG_VAL *ret = NULL;
+       WERROR error = WERR_OK;
 
-       if(!key) return NULL;
+       if(!key) return WERR_INVALID_PARAM;
 
        if(key->handle->functions->get_value_by_name) {
-               ret = key->handle->functions->get_value_by_name(key,name);
+               error = key->handle->functions->get_value_by_name(key,name, val);
        } else {
-               max = reg_key_num_values(key);
-               for(i = 0; i < max; i++) {
-                       REG_VAL *v = reg_key_get_value_by_index(key, i);
-                       if(v && StrCaseCmp(v->name, name)) {
-                               ret = v;
+               for(i = 0; W_ERROR_IS_OK(error); i++) {
+                       error = reg_key_get_value_by_index(key, i, val);
+                       if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
                                break;
                        }
-                       reg_val_free(v);
+                       reg_val_free(*val);
                }
        }
+
+       if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
+               return error;
        
-       if(ret) {
-               ret->parent = key;
-               ret->handle = key->handle;
-       }
+       (*val)->parent = key;
+       (*val)->handle = key->handle;
        
-       return ret;
+       return WERR_OK;
 }
 
-BOOL reg_key_del(REG_KEY *key)
+WERROR reg_key_del(REG_KEY *key)
 {
-       if(key->handle->functions->del_key) {
-               if(key->handle->functions->del_key(key)) {
-                       /* Invalidate cache */
-                       key->cache_subkeys = NULL;
-                       key->cache_subkeys_count = 0;
-                       return True;
-               }
-       }
+       WERROR error;
+       if(!key) return WERR_INVALID_PARAM;
+       
+       
+       if(!key->handle->functions->del_key)
+               return WERR_NOT_SUPPORTED;
+       
+       error = key->handle->functions->del_key(key);
+       if(!W_ERROR_IS_OK(error)) return error;
 
-       return False;
+       /* Invalidate cache */
+       key->cache_subkeys = NULL;
+       key->cache_subkeys_count = 0;
+       return WERR_OK;
 }
 
-BOOL reg_sync(REG_HANDLE *h, const char *location)
+WERROR reg_sync(REG_KEY *h, const char *location)
 {
-       if(!h->functions->sync)
-               return True;
+       if(!h->handle->functions->sync_key)
+               return WERR_OK;
 
-       return h->functions->sync(h, location);
+       return h->handle->functions->sync_key(h, location);
 }
 
-BOOL reg_key_del_recursive(REG_KEY *key)
+WERROR reg_key_del_recursive(REG_KEY *key)
 {
        BOOL succeed = True;
+       WERROR error = WERR_OK;
        int i;
        
        /* Delete all values for specified key */
-       for(i = 0; i < reg_key_num_values(key); i++) {
-               if(!reg_val_del(reg_key_get_value_by_index(key, i)))
-                       succeed = False;
+       for(i = 0; W_ERROR_IS_OK(error); i++) {
+               REG_VAL *val;
+               error = reg_key_get_value_by_index(key, i, &val);
+               if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
+                       return error;
+
+               if(W_ERROR_IS_OK(error)) {
+                       error = reg_val_del(val);
+                       if(!W_ERROR_IS_OK(error)) return error;
+               }
        }
 
+       error = WERR_OK;
+
        /* Delete all keys below this one */
-       for(i = 0; i < reg_key_num_subkeys(key); i++) {
-               if(!reg_key_del_recursive(reg_key_get_subkey_by_index(key, i)))
-                       succeed = False;
-       }
+       for(i = 0; W_ERROR_IS_OK(error); i++) {
+               REG_KEY *subkey;
+
+               error = reg_key_get_subkey_by_index(key, i, &subkey);
+               if(!W_ERROR_IS_OK(error)) return error;
 
-       if(succeed)reg_key_del(key);
+               error = reg_key_del_recursive(subkey);
+               if(!W_ERROR_IS_OK(error)) return error;
+       }
 
-       return succeed;
+       return reg_key_del(key);
 }
 
-BOOL reg_val_del(REG_VAL *val)
+WERROR reg_val_del(REG_VAL *val)
 {
+       WERROR error;
+       if (!val) return WERR_INVALID_PARAM;
+
        if (!val->handle->functions->del_value) {
                DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name));
-               return False;
+               return WERR_NOT_SUPPORTED;
        }
        
-       if(val->handle->functions->del_value(val)) {
-               val->parent->cache_values = NULL;
-               val->parent->cache_values_count = 0;
-               return True;
-       } 
-       return False;
+       error = val->handle->functions->del_value(val);
+
+       if(!W_ERROR_IS_OK(error)) return error;
+
+       val->parent->cache_values = NULL;
+       val->parent->cache_values_count = 0;
+
+       return WERR_OK;
 }
 
-BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path)
+WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path)
 {
        REG_KEY *cur, *prevcur = parent;
+       WERROR error;
        char *begin = (char *)path, *end;
 
        while(1) { 
                end = strchr(begin, '\\');
                if(end) *end = '\0';
-               cur = reg_key_get_subkey_by_name(prevcur, begin);
-               if(!cur) {
-                       if(!reg_key_add_name(prevcur, begin)) { printf("foo\n"); return False; }
-                       cur = reg_key_get_subkey_by_name(prevcur, begin);
-                       if(!cur) {
-                               DEBUG(0, ("Can't find key after adding it : %s\n", begin));
-                               return False;
-                       }
+               
+               error = reg_key_get_subkey_by_name(prevcur, begin, &cur);
+
+               /* Key is not there, add it */
+               if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
+                       error = reg_key_add_name(prevcur, begin, 0, NULL, &cur);
+                       if(!W_ERROR_IS_OK(error)) return error;
+               }
+
+               if(!W_ERROR_IS_OK(error)) {
+                       if(end) *end = '\\';
+                       return error;
                }
                
                if(!end) break;
@@ -403,28 +441,36 @@ BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path)
                begin = end+1;
                prevcur = cur;
        }
-       return True;
+       return WERR_OK;
 }
 
-BOOL reg_key_add_name(REG_KEY *parent, const char *name)
+WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **newkey)
 {
-       if (!parent) return False;
+       WERROR error;
+       
+       if (!parent) return WERR_INVALID_PARAM;
        
        if (!parent->handle->functions->add_key) {
                DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name));
-               return False;
+               return WERR_NOT_SUPPORTED;
        }
 
-       if(parent->handle->functions->add_key(parent, name)) {
-               parent->cache_subkeys = NULL;
-               parent->cache_subkeys_count = 0;
-               return True;
-       } 
-       return False;
+       error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey);
+
+       if(!W_ERROR_IS_OK(error)) return error;
+       
+       (*newkey)->handle = parent->handle;
+       (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name);
+
+       parent->cache_subkeys = NULL;
+       parent->cache_subkeys_count = 0;
+       return WERR_OK;
 }
 
-BOOL reg_val_update(REG_VAL *val, int type, void *data, int len)
+WERROR reg_val_update(REG_VAL *val, int type, void *data, int len)
 {
+       WERROR error;
+       
        /* A 'real' update function has preference */
        if (val->handle->functions->update_value) 
                return val->handle->functions->update_value(val, type, data, len);
@@ -433,18 +479,19 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len)
        if (val->handle->functions->add_value && 
                val->handle->functions->del_value) {
                REG_VAL *new;
-               if(!val->handle->functions->del_value(val)) 
-                       return False;
+               if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) 
+                       return error;
                
-               new = val->handle->functions->add_value(val->parent, val->name, type, data, len);
+               error = val->handle->functions->add_value(val->parent, val->name, type, data, len);
+               if(!W_ERROR_IS_OK(error)) return error;
                memcpy(val, new, sizeof(REG_VAL));
                val->parent->cache_values = NULL;
                val->parent->cache_values_count = 0;
-               return True;
+               return WERR_OK;
        }
                
        DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name));
-       return False;
+       return WERR_NOT_SUPPORTED;
 }
 
 void reg_free(REG_HANDLE *h)
@@ -454,37 +501,44 @@ void reg_free(REG_HANDLE *h)
        h->functions->close_registry(h);
 }
 
-REG_KEY *reg_get_root(REG_HANDLE *h
+WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key
 {
-       REG_KEY *ret = NULL;
+       WERROR ret;
        if(h->functions->open_root_key) {
-               ret = h->functions->open_root_key(h);
+               ret = h->functions->open_root_key(h, key);
        } else if(h->functions->open_key) {
-               ret = h->functions->open_key(h, "\\");
+               ret = h->functions->open_key(h, "\\", key);
        } else {
                DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name));
+               ret = WERR_NOT_SUPPORTED;
        }
 
-       if(ret) {
-               ret->handle = h;
-               ret->path = talloc_strdup(ret->mem_ctx, "\\");
+       if(W_ERROR_IS_OK(ret)) {
+               (*key)->handle = h;
+               (*key)->path = talloc_strdup((*key)->mem_ctx, "\\");
        }
 
        return ret;
 }
 
-REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen)
+WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen)
 {
-       REG_VAL *ret;
+       WERROR ret = WERR_OK;
        if(!key->handle->functions->add_value)
-               return NULL;
+               return WERR_NOT_SUPPORTED;
 
        ret = key->handle->functions->add_value(key, name, type, value, vallen);
-       ret->parent = key;
-       ret->handle = key->handle;
+
+       if(!W_ERROR_IS_OK(ret)) return ret;
 
        /* Invalidate the cache */
        key->cache_values = NULL;
        key->cache_values_count = 0;
        return ret;
 }
+
+WERROR reg_save(REG_HANDLE *h, const char *location)
+{
+       /* FIXME */     
+       return WERR_NOT_SUPPORTED;
+}
index 060d053fc27aeacaae4670de61295585f9924a0c..5ca104fc2ef8c19dafb9a1e4ea0d4f0820225cdb 100644 (file)
@@ -96,22 +96,26 @@ BOOL reg_val_set_string(REG_VAL *val, char *str)
        return False;
 }
 
-REG_VAL *reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname)
+WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname, REG_VAL **val)
 {
-       REG_KEY *k = reg_key_get_subkey_by_name(key, subname);
-       if(!k) return NULL;
+       REG_KEY *k;
+       WERROR error = reg_key_get_subkey_by_name(key, subname, &k);
+       if(!W_ERROR_IS_OK(error)) return error;
        
-       return reg_key_get_value_by_name(k, valname);
+       return reg_key_get_value_by_name(k, valname, val);
 }
 
-BOOL reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len)
+WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len)
 {
-       REG_KEY *k = reg_key_get_subkey_by_name(key, subname);
+       REG_KEY *k;
        REG_VAL *v;
-       if(!k) return False;
+       WERROR error;
 
-       v = reg_key_get_value_by_name(k, valname);
-       if(!v) return False;
+       error = reg_key_get_subkey_by_name(key, subname, &k);
+       if(!W_ERROR_IS_OK(error)) return error;
+
+       error = reg_key_get_value_by_name(k, valname, &v);
+       if(!W_ERROR_IS_OK(error)) return error;
        
        return reg_val_update(v, type, data, real_len);
 }
index 3565a7a5851e08749b5df2ffb80d1c8ad4aa1bf3..6e12de258de408b999ea7b9adceec4685f5d7465 100644 (file)
@@ -57,42 +57,55 @@ struct reg_val_s {
   int ref;
 };
 
+/* FIXME */
+typedef void (*key_notification_function) ();
+typedef void (*value_notification_function) ();
+
+
 /* 
  * Container for function pointers to enumeration routines
  * for virtual registry view 
  */ 
  
-struct reg_ops_s {
+struct registry_ops {
        const char *name;
-       BOOL (*open_registry) (REG_HANDLE *, const char *location, BOOL try_complete_load);
-       BOOL (*sync)(REG_HANDLE *, const char *location);
-       BOOL (*close_registry) (REG_HANDLE *);
+       WERROR (*open_registry) (REG_HANDLE *, const char *location, const char *credentials);
+       WERROR (*sync_key)(REG_KEY *, const char *location);
+       WERROR (*close_registry) (REG_HANDLE *);
 
        /* Either implement these */
-       REG_KEY *(*open_root_key) (REG_HANDLE *);
-       int (*num_subkeys) (REG_KEY *);
-       int (*num_values) (REG_KEY *);
-       REG_KEY *(*get_subkey_by_index) (REG_KEY *, int idx);
-       REG_KEY *(*get_subkey_by_name) (REG_KEY *, const char *name);
-       REG_VAL *(*get_value_by_index) (REG_KEY *, int idx);
-       REG_VAL *(*get_value_by_name) (REG_KEY *, const char *name);
+       WERROR (*open_root_key) (REG_HANDLE *, REG_KEY **);
+       WERROR (*num_subkeys) (REG_KEY *, int *count);
+       WERROR (*num_values) (REG_KEY *, int *count);
+       WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **);
+       WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **);
+       WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **);
+       WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **);
 
        /* Or these */
-       REG_KEY *(*open_key) (REG_HANDLE *, const char *name);
-       BOOL (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***);
-       BOOL (*fetch_values) (REG_KEY *, int *count, REG_VAL ***);
+       WERROR (*open_key) (REG_HANDLE *, const char *name, REG_KEY **);
+       WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***);
+       WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***);
+
+       /* Security control */
+       WERROR (*key_get_sec_desc) (REG_KEY *, SEC_DESC **);
+       WERROR (*key_set_sec_desc) (REG_KEY *, SEC_DESC *);
+
+       /* Notification */
+       WERROR (*request_key_change_notify) (REG_KEY *, key_notification_function);
+       WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function);
 
        /* Key management */
-       BOOL (*add_key)(REG_KEY *, const char *name);
-       BOOL (*del_key)(REG_KEY *);
+       WERROR (*add_key)(REG_KEY *, const char *name, uint32 access_mask, SEC_DESC *, REG_KEY **);
+       WERROR (*del_key)(REG_KEY *);
 
        /* Value management */
-       REG_VAL *(*add_value)(REG_KEY *, const char *name, int type, void *data, int len);
-       BOOL (*del_value)(REG_VAL *);
+       WERROR (*add_value)(REG_KEY *, const char *name, int type, void *data, int len);
+       WERROR (*del_value)(REG_VAL *);
        
        /* If update is not available, value will first be deleted and then added 
         * again */
-       BOOL (*update_value)(REG_VAL *, int type, void *data, int len); 
+       WERROR (*update_value)(REG_VAL *, int type, void *data, int len); 
 
        void (*free_key_backend_data) (REG_KEY *);
        void (*free_val_backend_data) (REG_VAL *);
@@ -105,7 +118,7 @@ typedef struct reg_sub_tree_s {
 } REG_SUBTREE;
 
 struct reg_handle_s {
-       REG_OPS *functions;
+       struct registry_ops *functions;
        REG_SUBTREE *subtrees;
        char *location;
        void *backend_data;
@@ -114,7 +127,7 @@ struct reg_handle_s {
 
 struct reg_init_function_entry {
        /* Function to create a member of the pdb_methods list */
-       REG_OPS *functions;
+       struct registry_ops *functions;
        struct reg_init_function_entry *prev, *next;
 };
 
index 146ef92b95d8b0df68cb0608497efc9554c8a390..90dc50728ba036aa425073f6dd361e120a9d1031 100644 (file)
@@ -8,9 +8,12 @@ LIBWINREG=libwinregistry
 PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC)
                                  CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building reg_gconf])])
 
+PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])])
+
 SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o)
 SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o)
 SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o)
 SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS])
+SMB_MODULE(reg_ldb, REG, STATIC, lib/registry/reg_backend_ldb/reg_backend_ldb.o)
 SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[])
 AC_CONFIG_FILES(lib/registry/winregistry.pc)
index 9cb15cd28581d72ad47bbf064f4f793b9858476e..4daaf3d628e6d513dca5a7169f4582747901796d 100644 (file)
@@ -21,7 +21,7 @@
 #include "includes.h"
 #include "lib/registry/common/registry.h"
 
-static BOOL reg_dir_add_key(REG_KEY *parent, const char *name)
+static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc)
 {
        char *path;
        int ret;
@@ -29,15 +29,16 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name)
        path = reg_path_win2unix(path);
        ret = mkdir(path, 0700);
        SAFE_FREE(path);
-       return (ret == 0);
+       if(ret == 0)return WERR_OK;
+       return WERR_INVALID_PARAM;
 }
 
-static BOOL reg_dir_del_key(REG_KEY *k)
+static WERROR reg_dir_del_key(REG_KEY *k)
 {
-       return (rmdir((char *)k->backend_data) == 0);
+       return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE;
 }
 
-static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name)
+static WERROR reg_dir_open_key(REG_HANDLE *h, const char *name, REG_KEY **subkey)
 {
        DIR *d;
        char *fullpath;
@@ -45,7 +46,7 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name)
        TALLOC_CTX *mem_ctx = talloc_init("tmp");
        if(!name) {
                DEBUG(0, ("NULL pointer passed as directory name!"));
-               return NULL;
+               return WERR_INVALID_PARAM;
        }
        fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name);
        fullpath = reg_path_win2unix(fullpath);
@@ -54,16 +55,17 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name)
        if(!d) {
                DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno)));
                talloc_destroy(mem_ctx);
-               return NULL;
+               return WERR_BADFILE;
        }
        closedir(d);
        ret = reg_key_new_abs(name, h, fullpath);
        talloc_steal(mem_ctx, ret->mem_ctx, fullpath);
        talloc_destroy(mem_ctx);
-       return ret;
+       *subkey = ret;
+       return WERR_OK;
 }
 
-static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
+static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
 {
        struct dirent *e;
        int max = 200;
@@ -75,7 +77,7 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
 
        d = opendir(fullpath);
 
-       if(!d) return False;
+       if(!d) return WERR_INVALID_PARAM;
        
        while((e = readdir(d))) {
                if(e->d_type == DT_DIR && 
@@ -96,35 +98,35 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
        closedir(d);
        
        *r = ar;
-       return True;
+       return WERR_OK;
 }
 
-static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) {
-       if(!loc) return False;
-       return True;
+static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentials) {
+       if(!loc) return WERR_INVALID_PARAM;
+       return WERR_OK;
 }
 
-static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len)
+static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len, REG_VAL **value)
 {
-       REG_VAL *ret = reg_val_new(p, NULL);
        char *fullpath;
        FILE *fd;
-       ret->name = name?talloc_strdup(ret->mem_ctx, name):NULL;
-       fullpath = reg_path_win2unix(strdup(reg_val_get_path(ret)));
+       *value = reg_val_new(p, NULL);
+       (*value)->name = name?talloc_strdup((*value)->mem_ctx, name):NULL;
+       fullpath = reg_path_win2unix(strdup(reg_val_get_path(*value)));
        
        fd = fopen(fullpath, "w+");
        
        /* FIXME */
-       return NULL;
+       return WERR_NOT_SUPPORTED;
 }
 
-static BOOL reg_dir_del_value(REG_VAL *v)
+static WERROR reg_dir_del_value(REG_VAL *v)
 {
        /* FIXME*/
-       return False;
+       return WERR_NOT_SUPPORTED;
 }
 
-static REG_OPS reg_backend_dir = {
+static struct registry_ops reg_backend_dir = {
        .name = "dir",
        .open_registry = reg_dir_open,
        .open_key = reg_dir_open_key,
index 71d3361ce26cfd5d03266cb10e09bada79dc50dd..1acb3cbcec7fbc934af6c01a177dd7f845ea99a7 100644 (file)
 #include "lib/registry/common/registry.h"
 #include <gconf/gconf-client.h>
 
-static BOOL reg_open_gconf(REG_HANDLE *h, const char *location, BOOL try_complete_load) 
+static WERROR gerror_to_werror(GError *error)
+{
+       if(error == NULL) return WERR_OK;
+       /* FIXME */
+       return WERR_FOOBAR;
+}
+
+static WERROR reg_open_gconf(REG_HANDLE *h, const char *location, const char *credentials) 
 {
        h->backend_data = (void *)gconf_client_get_default();
-       return True;
+       if(!h->backend_data) return WERR_FOOBAR;
+       return WERR_OK;
 }
 
-static BOOL reg_close_gconf(REG_HANDLE *h) 
+static WERROR reg_close_gconf(REG_HANDLE *h) 
 {
-       return True;
+       return WERR_OK;
 }
 
-static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name
+static WERROR gconf_open_key (REG_HANDLE *h, const char *name, REG_KEY **key
 {
        REG_KEY *ret;
        char *fullpath = reg_path_win2unix(strdup(name));
@@ -41,16 +49,17 @@ static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name)
        /* Check if key exists */
        if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) {
                SAFE_FREE(fullpath);
-               return NULL;
+               return WERR_DEST_NOT_FOUND;
        }
        ret = reg_key_new_abs(name, h, NULL);
        ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath);
        SAFE_FREE(fullpath);
 
-       return ret;
+       *key = ret;
+       return WERR_OK;
 }
 
-static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals)
+static WERROR gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals)
 {
        GSList *entries;
        GSList *cur;
@@ -113,22 +122,24 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals)
 
        g_slist_free(entries);
        *vals = ar;
-       return True;
+       return WERR_OK;
 }
 
-static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) 
+static WERROR gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) 
 {
        GSList *dirs;
        GSList *cur;
-       REG_KEY **ar = malloc(sizeof(REG_KEY *));
+       REG_KEY **ar = talloc_array_p(p->mem_ctx, REG_KEY *, 1);
        char *fullpath = p->backend_data;
        cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL);
 
        (*count) = 0;
        while(cur) {
-               ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle,NULL);
-               ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, cur->data);
-               ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+2));
+               char *winpath = reg_path_unix2win(strdup((char *)cur->data));
+               ar[(*count)] = reg_key_new_abs(winpath, p->handle,NULL);
+               free(winpath);
+               ar[(*count)]->backend_data = reg_path_win2unix(talloc_strdup(ar[*count]->mem_ctx, cur->data));
+               ar = talloc_realloc_p(p->mem_ctx, ar, REG_KEY *, (*count)+2);
                (*count)++;
                g_free(cur->data);
                cur = cur->next;
@@ -136,10 +147,10 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs)
 
        g_slist_free(dirs);
        *subs = ar;
-       return True;
+       return WERR_OK;
 }
 
-static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len)
+static WERROR gconf_update_value(REG_VAL *val, int type, void *data, int len)
 {
        GError *error = NULL;
        char *keypath = val->backend_data;
@@ -152,22 +163,23 @@ static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len)
        case REG_EXPAND_SZ:
                gconf_client_set_string((GConfClient *)val->handle->backend_data, valpath, data, &error);
                free(valpath);
-               return (error == NULL);
+               return gerror_to_werror(error);
 
        case REG_DWORD:
                gconf_client_set_int((GConfClient *)val->handle->backend_data, valpath, 
  *((int *)data), &error);
                free(valpath);
-               return (error == NULL);
+               return gerror_to_werror(error);
        default:
                DEBUG(0, ("Unsupported type: %d\n", type));
                free(valpath);
-               return False;
+               return WERR_NOT_SUPPORTED;
        }
-       return False;
+
+       return WERR_NOT_SUPPORTED;
 }
 
-static REG_OPS reg_backend_gconf = {
+static struct registry_ops reg_backend_gconf = {
        .name = "gconf",
        .open_registry = reg_open_gconf,
        .close_registry = reg_close_gconf,
index afa60c5c4a1769234b223d151608c0d288fa2c06..3cc165151929c1d4106cff7d6a16e0613cdf4428 100644 (file)
 
 #include "includes.h"
 #include "lib/registry/common/registry.h"
+#include "lib/ldb/include/ldb.h"
+
+char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path)
+{
+       char *ret = talloc_strdup(mem_ctx, "(dn=");
+       char *begin = (char *)path;
+       char *end = NULL;
+
+       while(begin) {
+               end = strchr(begin, '\\');
+               if(end)end = '\0';
+               if(end - begin != 0) ret = talloc_asprintf_append(mem_ctx, ret, "key=%s,", begin);
+                       
+               if(end) {
+                       *end = '\\';
+                       begin = end+1;
+               } else begin = NULL;
+       }
+
+       ret[strlen(ret)-1] = ')';
+       return ret;
+}
 
 /* 
  * Saves the dn as private_data for every key/val
  */
 
-static BOOL ldb_open_registry(REG_HANDLE *handle, const char *location, BOOL try_full_load)
+static WERROR ldb_open_registry(REG_HANDLE *handle, const char *location, const char *credentials)
 {
        struct ldb_context *c;
        c = ldb_connect(location, 0, NULL);
 
-       if(!c) return False;
+       if(!c) return WERR_FOOBAR;
 
        handle->backend_data = c;
        
-       return True;
+       return WERR_OK;
 }
 
-static BOOL ldb_close_registry(REG_HANDLE *h) 
+static WERROR ldb_close_registry(REG_HANDLE *h) 
 {
-       ldb_close(h);
-       return True;
+       ldb_close((struct ldb_context *)h->backend_data);
+       return WERR_OK;
 }
 
-static BOOL ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys)
+static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys)
 {
-       ldb_search();
+       struct ldb_context *c = k->handle->backend_data;
+       char *path;
+       struct ldb_message **msg;
+       char *ldap_path;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_path");
+       REG_KEY *key = NULL;
+       ldap_path = reg_path_to_ldb(mem_ctx, reg_key_get_path(k));
+       
+       if(ldb_search(c, NULL, LDB_SCOPE_ONELEVEL, ldap_path, NULL,&msg) > 0) {
+               key = reg_key_new_abs(reg_key_get_path(k), k->handle, ldap_path);
+               talloc_steal(mem_ctx, key->mem_ctx, ldap_path);
+               /* FIXME */
+       }
+
+       ldap_search_free(c, msg);
+       talloc_destroy(mem_ctx);
+       return WERR_OK;
 }
 
-static REG_KEY *ldb_open_key(REG_HANDLE *h, const char *name)
+
+
+static WERROR ldb_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
 {
        struct ldb_context *c = h->backend_data;
        char *path;
        struct ldb_message **msg;
-       REG_KEY *key = NULL;
-       (dn=key=Systems,
-       if(ldb_search(c, NULL, LDP_SCOPE_BASE, "", NULL,&msg) > 0) {
-               key = reg_key_new_abs(name, h, base);
+       char *ldap_path;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_path");
+       ldap_path = reg_path_to_ldb(mem_ctx, name);
+       
+       if(ldb_search(c, NULL, LDB_SCOPE_BASE, ldap_path, NULL,&msg) > 0) {
+               *key = reg_key_new_abs(name, h, ldap_path);
+               talloc_steal(mem_ctx, (*key)->mem_ctx, ldap_path);
+               /* FIXME */
        }
 
        ldap_search_free(c, msg);
+       talloc_destroy(mem_ctx);
 
-       return key;
+       return WERR_OK;;
 }
 
-static REG_OPS reg_backend_ldb = {
+static struct registry_ops reg_backend_ldb = {
        .name = "ldb",
        .open_registry = ldb_open_registry,
        .close_registry = ldb_close_registry,
index ef2565bda85f7e74facea590f8e54dfdbf521eb5..9d90523a75c1670352ff7c1e8cc6357b09c7ee85 100644 (file)
@@ -881,7 +881,7 @@ static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, in
 /*
  * Process a VK header and return a value
  */
-static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size)
+static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **value)
 {
        char val_name[1024];
        REGF *regf = parent->handle->backend_data;
@@ -889,12 +889,12 @@ static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size)
        const char *val_type;
        REG_VAL *tmp = NULL; 
 
-       if (!vk_hdr) return NULL;
+       if (!vk_hdr) return WERR_INVALID_PARAM;
 
        if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) {
                DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n",
                                  vk_id, (int)vk_hdr, parent->handle->location));
-               return NULL;
+               return WERR_GENERAL_FAILURE;
        }
 
        nam_len = SVAL(&vk_hdr->nam_len,0);
@@ -943,7 +943,8 @@ static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size)
                tmp->data_len = dat_len;
        }
 
-       return tmp;
+       *value = tmp;
+       return WERR_OK;
 }
 
 static BOOL vl_verify(VL_TYPE vl, int count, int size)
@@ -956,63 +957,67 @@ static BOOL vl_verify(VL_TYPE vl, int count, int size)
        return True;
 }
 
-static BOOL lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size)
+static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size)
 {
        int lf_id;
        if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) {
                DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n",
                                  lf_id, (int)lf_hdr, h->location));
-               return False;
+               return WERR_INVALID_PARAM;
        }
-       return True;
+       return WERR_OK;
 }
 
-static int lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size)
+static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count)
 {
-       int count;
+       WERROR error;
 
-       if(!lf_verify(h, lf_hdr, size)) return 0;
+       error = lf_verify(h, lf_hdr, size);
+       if(!W_ERROR_IS_OK(error)) return error;
 
        SMB_REG_ASSERT(size < 0);
 
-       count = SVAL(&lf_hdr->key_count,0);
-       DEBUG(2, ("Key Count: %u\n", count));
-       if (count <= 0) return 0;
+       *count = SVAL(&lf_hdr->key_count,0);
+       DEBUG(2, ("Key Count: %u\n", *count));
+       if (*count <= 0) return WERR_INVALID_PARAM;
 
-       return count;
+       return WERR_OK;
 }
 
 
-static REG_KEY *nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent);
+static WERROR nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **);
 
 
 
 /*
  * Process an LF Header and return a list of sub-keys
  */
-static REG_KEY *lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n)
+static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG_KEY **key)
 {
        REGF *regf = parent->handle->backend_data;
        int count, nk_off;
        NK_HDR *nk_hdr;
+       WERROR error;
 
-       if (!lf_hdr) return NULL;
+       if (!lf_hdr) return WERR_INVALID_PARAM;
 
-       if(!lf_verify(parent->handle, lf_hdr, size)) return NULL;
+       error = lf_verify(parent->handle, lf_hdr, size);
+       if(!W_ERROR_IS_OK(error)) return error;
 
        SMB_REG_ASSERT(size < 0);
 
        count = SVAL(&lf_hdr->key_count,0);
        DEBUG(2, ("Key Count: %u\n", count));
-       if (count <= 0 || n > count) return NULL;
+       if (count <= 0) return WERR_GENERAL_FAILURE;
+       if (n >= count) return WERR_NO_MORE_ITEMS;
 
        nk_off = IVAL(&lf_hdr->hr[n].nk_off,0);
        DEBUG(2, ("NK Offset: %0X\n", nk_off));
        nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off);
-       return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent);
+       return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent, key);
 }
 
-static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent)
+static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **key)
 {
        REGF *regf = h->backend_data;
        REG_KEY *tmp = NULL, *own;
@@ -1022,12 +1027,12 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare
        int type;
        char key_name[1024], cls_name[1024];
 
-       if (!nk_hdr) return NULL;
+       if (!nk_hdr) return WERR_INVALID_PARAM;
 
        if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) {
                DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", 
                                  nk_id, (int)nk_hdr, parent->handle->location));
-               return NULL;
+               return WERR_INVALID_PARAM;
        }
 
        SMB_REG_ASSERT(size < 0);
@@ -1047,7 +1052,7 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare
                DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr));
                DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n",
                                  sizeof(NK_HDR), name_len, clsname_len));
-               /*return NULL;*/
+               return WERR_GENERAL_FAILURE;
        }
 
        DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", name_len, clsname_len));
@@ -1062,7 +1067,7 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare
        type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY);
        if(type == REG_ROOT_KEY && parent) {
                DEBUG(0,("Root key encountered below root level!\n"));
-               return NULL;
+               return WERR_GENERAL_FAILURE;
        }
 
        if(type == REG_ROOT_KEY) tmp = reg_key_new_abs(key_name, h, nk_hdr);
@@ -1121,7 +1126,8 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare
 
        } 
 
-       return tmp;
+       *key = tmp;
+       return WERR_OK;
 }
 
 /*
@@ -1559,7 +1565,7 @@ error:
        return NULL;
 }
 
-static BOOL nt_close_registry (REG_HANDLE *h) 
+static WERROR nt_close_registry (REG_HANDLE *h) 
 {
        REGF *regf = h->backend_data;
        if (regf->base) munmap(regf->base, regf->sbuf.st_size);
@@ -1570,10 +1576,10 @@ static BOOL nt_close_registry (REG_HANDLE *h)
        regf->sk_count = regf->sk_map_size = 0;
 
        free(regf);
-       return False;
+       return WERR_OK;
 }
 
-static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
+static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials
 {
        REGF *regf = (REGF *)malloc(sizeof(REGF));
        REGF_HDR *regf_hdr;
@@ -1582,7 +1588,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
 
        memset(regf, 0, sizeof(REGF));
        regf->mem_ctx = talloc_init("regf");
-       regf->owner_sid_str = def_owner_sid_str;
+       regf->owner_sid_str = credentials;
        h->backend_data = regf;
 
        DEBUG(5, ("Attempting to load registry file\n"));
@@ -1591,7 +1597,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
 
        if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) {
                DEBUG(0, ("Unable to get header\n"));
-               return False;
+               return WERR_GENERAL_FAILURE;
        }
 
        /* Now process that header and start to read the rest in */
@@ -1599,7 +1605,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
        if ((regf_id = IVAL(&regf_hdr->REGF_ID,0)) != str_to_dword("regf")) {
                DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n",
                                  regf_id, h->location));
-               return False;
+               return WERR_GENERAL_FAILURE;
        }
 
        /*
@@ -1608,7 +1614,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
        if (!valid_regf_hdr(regf_hdr)) {
                DEBUG(0, ("Registry file header does not validate: %s\n",
                                  h->location));
-               return False;
+               return WERR_GENERAL_FAILURE;
        }
 
        /* Update the last mod date, and then go get the first NK record and on */
@@ -1625,7 +1631,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
        if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) {
                DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", 
                                  hbin_id, h->location));
-               return False;
+               return WERR_GENERAL_FAILURE;
        } 
 
        /*
@@ -1655,15 +1661,15 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load
 
        h->backend_data = regf;
 
-       return True;
+       return WERR_OK;
 }
 
-static REG_KEY *nt_get_root_key(REG_HANDLE *h
+static WERROR nt_get_root_key(REG_HANDLE *h, REG_KEY **key
 { 
-       return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL);
+       return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key);
 }
 
-static int nt_num_subkeys(REG_KEY *k
+static WERROR nt_num_subkeys(REG_KEY *k, int *num
 {
        REGF *regf = k->handle->backend_data;
        LF_HDR *lf_hdr;
@@ -1671,19 +1677,23 @@ static int nt_num_subkeys(REG_KEY *k)
        NK_HDR *nk_hdr = k->backend_data;
        lf_off = IVAL(&nk_hdr->lf_off,0);
        DEBUG(2, ("SubKey list offset: %0X\n", lf_off));
-       if(lf_off == -1) return 0;
+       if(lf_off == -1) {
+               *num = 0;
+               return WERR_OK;
+       }
        lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off);
 
-       return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr));
+       return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr), num);
 }
 
-static int nt_num_values(REG_KEY *k)
+static WERROR nt_num_values(REG_KEY *k, int *count)
 {
        NK_HDR *nk_hdr = k->backend_data;
-       return IVAL(&nk_hdr->val_cnt,0);
+       *count = IVAL(&nk_hdr->val_cnt,0);
+       return WERR_OK;
 }
 
-static REG_VAL *nt_value_by_index(REG_KEY *k, int n)
+static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value)
 {
        VL_TYPE *vl;
        int val_off, vk_off;
@@ -1696,10 +1706,10 @@ static REG_VAL *nt_value_by_index(REG_KEY *k, int n)
 
        vk_off = IVAL(&vl[n],0);
        vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off);
-       return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr));
+       return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr), value);
 }
 
-static REG_KEY *nt_key_by_index(REG_KEY *k, int n)
+static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey)
 {
        REGF *regf = k->handle->backend_data;
        int lf_off;
@@ -1714,13 +1724,13 @@ static REG_KEY *nt_key_by_index(REG_KEY *k, int n)
 
        if (lf_off != -1) {
                lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off);
-               return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n);
+               return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey);
        }
 
-       return NULL;
+       return WERR_NO_MORE_ITEMS;
 }
 
-static REG_OPS reg_backend_nt4 = {
+static struct registry_ops reg_backend_nt4 = {
        .name = "nt4",
        .open_registry = nt_open_registry,
        .close_registry = nt_close_registry,
index ad4d537f9b1456d437ac21a1be53b8951fb55aa9..e61301d6f214332093c6aa71c0fd9b01b4081f07 100644 (file)
@@ -77,12 +77,18 @@ struct {
 { NULL, NULL }
 };
 
-static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full)
+static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
 {
-       BOOL res = True;
        struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
        char *binding = strdup(location);
        NTSTATUS status;
+       char *user, *pass;
+
+       if(!credentials || !location) return WERR_INVALID_PARAM;
+
+       user = talloc_strdup(h->mem_ctx, credentials);
+       pass = strchr(user, '%');
+       *pass = '\0'; pass++;
        
        ZERO_STRUCTP(mydata);
        
@@ -90,26 +96,26 @@ static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full
                     DCERPC_WINREG_UUID,
                     DCERPC_WINREG_VERSION,
                      lp_workgroup(),
-                     "tridge", "samba");
+                     user, pass);
 
-       if(!NT_STATUS_IS_OK(status)) return False;
 
        h->backend_data = mydata;
        
-       return True;
+       return ntstatus_to_werror(status);
 }
 
-static REG_KEY *rpc_open_root(REG_HANDLE *h)
+static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
 {
        /* There's not really a 'root' key here */
-       return reg_key_new_abs("\\", h, h->backend_data);
+       *k = reg_key_new_abs("\\", h, h->backend_data);
+       return WERR_OK;
 }
 
-static BOOL rpc_close_registry(REG_HANDLE *h)
+static WERROR rpc_close_registry(REG_HANDLE *h)
 {
        dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
        free(h->backend_data);
-       return True;
+       return WERR_OK;
 }
 
 static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
@@ -161,12 +167,15 @@ static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
        return key_handle;
 }
 
-static REG_KEY *rpc_open_key(REG_HANDLE *h, const char *name)
+static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
 {
-       return reg_key_new_abs(name, h, rpc_get_key_handle(h, name));
+       struct policy_handle *pol = rpc_get_key_handle(h, name);
+       if(!pol) return WERR_DEST_NOT_FOUND;
+       *key = reg_key_new_abs(name, h, pol);
+       return WERR_OK;
 }
 
-static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) 
+static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) 
 {
        struct winreg_EnumKey r;
        struct winreg_EnumKeyNameRequest keyname;
@@ -188,12 +197,12 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
 
                *subkeys = ar;
 
-               return True;
+               return WERR_OK;
        }
 
        if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
 
-       if(!parent->backend_data) return False;
+       if(!parent->backend_data) return WERR_GENERAL_FAILURE;
 
        (*count) = 0;
        r.in.handle = parent->backend_data;
@@ -219,10 +228,10 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
        }
 
        *subkeys = ar;
-       return True;
+       return r.out.result;
 }
 
-static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) 
+static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) 
 {
        struct winreg_EnumValue r;
        struct winreg_Uint8buf value;
@@ -238,12 +247,12 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
        /* Root */
        if(parent->backend_data == parent->handle->backend_data) {
                *values = ar;
-               return True;
+               return WERR_OK;
        }
        
        if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
 
-       if(!parent->backend_data) return False;
+       if(!parent->backend_data) return WERR_GENERAL_FAILURE;
 
        r.in.handle = parent->backend_data;
        r.in.enum_index = 0;
@@ -283,22 +292,48 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
        
        *values = ar;
 
-       return True;
+       return r.out.result;
 }
 
-static BOOL rpc_add_key(REG_KEY *parent, const char *name)
+static WERROR rpc_add_key(REG_KEY *parent, const char *name)
 {
        /* FIXME */
-       return False;   
+       return WERR_NOT_SUPPORTED;
 }
 
-static BOOL rpc_del_key(REG_KEY *k)
+static struct policy_handle*get_hive(REG_KEY *k)
 {
-       /* FIXME */
-       return False;
+       int i;
+       struct rpc_data *mydata = k->handle->backend_data;
+       for(i = 0; known_hives[i].name; i++) {
+               if(!strncmp(known_hives[i].name, reg_key_get_path(k)+1, strlen(known_hives[i].name))) 
+               return mydata->hives[i];
+       }
+       return NULL;
+}
+
+static WERROR rpc_del_key(REG_KEY *k)
+{
+       NTSTATUS status;
+       struct rpc_data *mydata = k->handle->backend_data;
+       struct winreg_DeleteKey r;
+       char *hivepath;
+       struct policy_handle *hive = get_hive(k);
+
+       printf("first: %s\n", reg_key_get_path(k));
+       hivepath = strchr(reg_key_get_path(k), '\\');
+       hivepath = strchr(hivepath+1, '\\');
+       printf("asfter: %s\n", hivepath+1);
+       
+    r.in.handle = hive;
+    init_winreg_String(&r.in.key, hivepath+1);
+    status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
+
+       return r.out.result;
 }
 
-static REG_OPS reg_backend_rpc = {
+static struct registry_ops reg_backend_rpc = {
        .name = "rpc",
        .open_registry = rpc_open_registry,
        .close_registry = rpc_close_registry,
index 6c8d7885cb0c8ee0b42e321bacd85e6d8b831150..fd7d04bcf03af3481536a50bffb5df5c201c29a3 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "includes.h"
 #include "lib/registry/common/registry.h"
+#include "windows/registry.h"
 
 static REG_OPS reg_backend_wine = {
        .name = "wine",
diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c
new file mode 100644 (file)
index 0000000..b62fd7e
--- /dev/null
@@ -0,0 +1,758 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Gtk registry frontend
+   
+   Copyright (C) Jelmer Vernooij 2004
+
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include "includes.h"
+
+GtkWidget *openfilewin;
+GtkWidget *savefilewin;
+GtkTreeStore *store_keys;
+GtkListStore *store_vals;
+GtkWidget *tree_keys;
+GtkWidget *aboutwin;
+GtkWidget *mainwin;
+
+GtkWidget *rpcwin;
+GtkWidget *rpcwin_host;
+GtkWidget *rpcwin_user;
+GtkWidget *rpcwin_password;
+GtkWidget *save;
+GtkWidget *save_as;
+GtkWidget* create_openfilewin (void);
+GtkWidget* create_savefilewin (void);
+static GtkWidget* create_aboutwin (void);
+REG_HANDLE *registry = NULL;
+
+static void gtk_show_werror(WERROR err) 
+{
+       GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(mainwin), 
+                GTK_DIALOG_DESTROY_WITH_PARENT,
+         GTK_MESSAGE_ERROR,
+         GTK_BUTTONS_CLOSE,
+                "Registry error: %s\n", win_errstr(err));
+       gtk_dialog_run (GTK_DIALOG (dialog));
+       gtk_widget_destroy (dialog);
+}
+
+static void treeview_add_val(REG_VAL *val)
+{
+       GtkTreeIter iter;
+       gtk_list_store_append(store_vals, &iter);
+       gtk_list_store_set (store_vals,
+                                           &iter, 
+                                               0,
+                                               reg_val_name(val),
+                                               1,
+                                               str_regtype(reg_val_type(val)),
+                                               2,
+                                               reg_val_data_string(val),
+                                               3, 
+                                               val,
+                                               -1);
+}
+
+static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2)
+{
+       GtkTreeIter iter, tmpiter;
+       REG_KEY *k, *sub;
+       char *name;
+       GValue value;
+       WERROR error;
+       int i;
+
+    /* See if this row has ever had a name gtk_tree_store_set()'ed to it.
+       If not, read the directory contents */
+    gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent,
+                       0, &name, -1);
+
+       if(!name) return;
+
+       gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, 1, &k, -1);
+
+       g_assert(k);
+       
+       for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(k, i, &sub)); i++) {
+               /* Replace the blank child with the first directory entry
+           You may be tempted to remove the blank child node and then 
+           append a new one.  Don't.  If you remove the blank child 
+           node GTK gets confused and won't expand the parent row. */
+
+               if(i == 0) {
+                   gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), 
+                                     &iter, parent);
+               } else {
+                       gtk_tree_store_append(store_keys, &iter, parent);
+               }
+               gtk_tree_store_set (store_keys,
+                                           &iter, 
+                                               0,
+                                               reg_key_name(sub),
+                                               1, 
+                                               sub,
+                                               -1);
+               
+               gtk_tree_store_append(store_keys, &tmpiter, &iter);
+       }
+
+       /* Remove placeholder child */
+       if(i == 0) {
+           gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), 
+                                     &iter, parent);
+               gtk_tree_store_remove(store_keys, &iter);
+       }
+
+       if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error);
+}
+
+static void registry_load_root() 
+{
+       REG_KEY *root;
+       GtkTreeIter iter, tmpiter;
+       WERROR error;
+       if(!registry) return;
+
+       error = reg_get_root(registry, &root);
+       if(!W_ERROR_IS_OK(error)) {
+               gtk_show_werror(error);
+               return;
+       }
+
+       gtk_tree_store_clear(store_keys);
+
+       /* Add the root */
+       gtk_tree_store_append(store_keys, &iter, NULL);
+       gtk_tree_store_set (store_keys,
+                                           &iter, 
+                                               0,
+                                               reg_key_name(root),
+                                               1,
+                                               root,
+                                               -1);
+
+       gtk_tree_store_append(store_keys, &tmpiter, &iter);
+
+       gtk_widget_set_sensitive( save, True );
+       gtk_widget_set_sensitive( save_as, True );
+}
+
+GtkWidget* create_rpcwin (void)
+{
+  GtkWidget *dialog_vbox1;
+  GtkWidget *table1;
+  GtkWidget *label1;
+  GtkWidget *label2;
+  GtkWidget *label3;
+  GtkWidget *dialog_action_area1;
+  GtkWidget *cancelbutton1;
+  GtkWidget *okbutton1;
+
+  rpcwin = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (rpcwin), "Connect to remote server");
+
+  dialog_vbox1 = GTK_DIALOG (rpcwin)->vbox;
+  gtk_widget_show (dialog_vbox1);
+
+  table1 = gtk_table_new (3, 2, FALSE);
+  gtk_widget_show (table1);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0);
+
+  label1 = gtk_label_new ("Host:");
+  gtk_widget_show (label1);
+  gtk_table_attach (GTK_TABLE (table1), label1, 0, 1, 0, 1,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_misc_set_alignment (GTK_MISC (label1), 0, 0.5);
+
+  label2 = gtk_label_new ("User:");
+  gtk_widget_show (label2);
+  gtk_table_attach (GTK_TABLE (table1), label2, 0, 1, 1, 2,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5);
+
+  label3 = gtk_label_new ("Password:");
+  gtk_widget_show (label3);
+  gtk_table_attach (GTK_TABLE (table1), label3, 0, 1, 2, 3,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5);
+
+  rpcwin_host = gtk_entry_new ();
+  gtk_widget_show (rpcwin_host);
+  gtk_table_attach (GTK_TABLE (table1), rpcwin_host, 1, 2, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  rpcwin_user = gtk_entry_new ();
+  gtk_widget_show (rpcwin_user);
+  gtk_table_attach (GTK_TABLE (table1), rpcwin_user, 1, 2, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+
+  rpcwin_password = gtk_entry_new ();
+  gtk_widget_show (rpcwin_password);
+  gtk_table_attach (GTK_TABLE (table1), rpcwin_password, 1, 2, 2, 3,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_entry_set_visibility (GTK_ENTRY (rpcwin_password), FALSE);
+
+  dialog_action_area1 = GTK_DIALOG (rpcwin)->action_area;
+  gtk_widget_show (dialog_action_area1);
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+
+  cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel");
+  gtk_widget_show (cancelbutton1);
+  gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), cancelbutton1, GTK_RESPONSE_CANCEL);
+  GTK_WIDGET_SET_FLAGS (cancelbutton1, GTK_CAN_DEFAULT);
+
+  okbutton1 = gtk_button_new_from_stock ("gtk-ok");
+  gtk_widget_show (okbutton1);
+  gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), okbutton1, GTK_RESPONSE_OK);
+  GTK_WIDGET_SET_FLAGS (okbutton1, GTK_CAN_DEFAULT);
+
+  return rpcwin;
+}
+
+
+static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data)
+{
+       gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin()));
+       char *filename;
+       WERROR error;
+       switch(result) {
+       case GTK_RESPONSE_OK:
+               filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin)));
+               error = reg_open("nt4", filename, NULL, &registry);
+               if(!W_ERROR_IS_OK(error)) {
+                       gtk_show_werror(error);
+                       return;
+               }
+               registry_load_root();
+               break;
+       default:
+               break;
+       }
+
+       gtk_widget_destroy(openfilewin);
+}
+
+void on_open_gconf_activate                       (GtkMenuItem     *menuitem,
+                                                     gpointer         user_data)
+{
+       WERROR error = reg_open("gconf", NULL, NULL, &registry);
+       if(!W_ERROR_IS_OK(error)) {
+               gtk_show_werror(error);
+               return;
+       }
+
+       registry_load_root();
+}
+
+void
+on_open_remote_activate                (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       char *location, *credentials;
+       gint result = gtk_dialog_run(GTK_DIALOG(create_rpcwin()));
+       WERROR error;
+       switch(result) {
+       case GTK_RESPONSE_OK:
+               asprintf(&location, "ncacn_np:%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_host)));
+               asprintf(&credentials, "%s%%%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_user)), gtk_entry_get_text(GTK_ENTRY(rpcwin_password)));
+               error = reg_open("rpc", location, credentials, &registry);
+               if(!W_ERROR_IS_OK(error)) {
+                       gtk_show_werror(error);
+                       return;
+               }
+               free(location); free(credentials);
+               registry_load_root();
+               break;
+       default:
+               break;
+       }
+
+       gtk_widget_destroy(rpcwin);
+}
+
+
+void
+on_save_activate                       (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       WERROR error = reg_save(registry, NULL);
+       if(!W_ERROR_IS_OK(error)) {
+               gtk_show_werror(error);
+       }
+}
+
+
+void
+on_save_as_activate                    (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       gint result;
+       WERROR error;
+       create_savefilewin();
+       result = gtk_dialog_run(GTK_DIALOG(savefilewin));
+       switch(result) {
+       case GTK_RESPONSE_OK:
+               error = reg_save(registry, gtk_file_selection_get_filename(GTK_FILE_SELECTION(savefilewin)));
+               if(!W_ERROR_IS_OK(error)) {
+                       gtk_show_werror(error);
+               }
+               break;
+
+       default:
+               break;
+
+       }
+       gtk_widget_destroy(savefilewin);
+}
+
+
+void
+on_quit_activate                       (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       gtk_main_quit();
+}
+
+
+void
+on_cut_activate                        (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       /* FIXME */
+}
+
+
+void
+on_copy_activate                       (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       /* FIXME */
+}
+
+
+void
+on_paste_activate                      (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       /* FIXME */
+}
+
+
+void
+on_delete_activate                     (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       /* FIXME */
+}
+
+
+void
+on_about_activate                      (GtkMenuItem     *menuitem,
+                                                                               gpointer         user_data)
+{
+       gtk_dialog_run(GTK_DIALOG(create_aboutwin()));
+       gtk_widget_destroy(aboutwin);
+}
+
+void on_key_activate (GtkTreeView *treeview,
+                                         GtkTreePath *path,
+                                         gpointer user_data)
+{
+       int i;
+       REG_KEY *k;
+       REG_VAL *val;
+       WERROR error;
+
+//FIXME        gtk_tree_model_get(GTK_TREE_MODEL(store_keys), iter, 1, &k, -1);
+
+       gtk_list_store_clear(store_vals);
+
+       for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(k, i, &val)); i++) {
+               treeview_add_val(val);
+       }
+
+       if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error);
+
+       return;
+}
+
+GtkWidget* create_mainwin (void)
+{
+       GtkWidget *vbox1;
+       GtkWidget *menubar;
+       GtkWidget *menu_file;
+       GtkWidget *menu_file_menu;
+       GtkWidget *open_nt4;
+       GtkWidget *open_gconf;
+       GtkWidget *open_remote;
+       GtkWidget *separatormenuitem1;
+       GtkWidget *quit;
+       GtkWidget *men_edit;
+       GtkWidget *men_edit_menu;
+       GtkWidget *cut;
+       GtkWidget *copy;
+       GtkWidget *paste;
+       GtkWidget *delete;
+       GtkCellRenderer *renderer;
+       GtkTreeViewColumn *curcol;
+       GtkWidget *help;
+       GtkWidget *help_menu;
+       GtkWidget *about;
+       GtkWidget *hbox1;
+       GtkWidget *scrolledwindow1;
+       GtkWidget *scrolledwindow2;
+       GtkWidget *tree_vals;
+       GtkWidget *statusbar;
+       GtkAccelGroup *accel_group;
+       GtkTreeIter iter, child;
+
+       accel_group = gtk_accel_group_new ();
+
+       mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_title (GTK_WINDOW (mainwin), "Registry editor");
+       gtk_window_set_default_size (GTK_WINDOW (mainwin), 642, 562);
+
+       vbox1 = gtk_vbox_new (FALSE, 0);
+       gtk_widget_show (vbox1);
+       gtk_container_add (GTK_CONTAINER (mainwin), vbox1);
+
+       menubar = gtk_menu_bar_new ();
+       gtk_widget_show (menubar);
+       gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, FALSE, 0);
+
+       menu_file = gtk_menu_item_new_with_mnemonic ("_File");
+       gtk_widget_show (menu_file);
+       gtk_container_add (GTK_CONTAINER (menubar), menu_file);
+
+       menu_file_menu = gtk_menu_new ();
+       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_file), menu_file_menu);
+
+       open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file");
+       gtk_widget_show (open_nt4);
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4);
+
+       open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf");
+       gtk_widget_show (open_gconf);
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf);
+
+       open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote");
+       gtk_widget_show (open_remote);
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote);
+
+       save = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group);
+       gtk_widget_show (save);
+       gtk_widget_set_sensitive( save, False );
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), save);
+
+       save_as = gtk_image_menu_item_new_from_stock ("gtk-save-as", accel_group);
+       gtk_widget_show (save_as);
+       gtk_widget_set_sensitive( save_as, False );
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), save_as);
+
+       separatormenuitem1 = gtk_menu_item_new ();
+       gtk_widget_show (separatormenuitem1);
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), separatormenuitem1);
+       gtk_widget_set_sensitive (separatormenuitem1, FALSE);
+
+       quit = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group);
+       gtk_widget_show (quit);
+       gtk_container_add (GTK_CONTAINER (menu_file_menu), quit);
+
+       men_edit = gtk_menu_item_new_with_mnemonic ("_Edit");
+       gtk_widget_show (men_edit);
+       gtk_container_add (GTK_CONTAINER (menubar), men_edit);
+
+  men_edit_menu = gtk_menu_new ();
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (men_edit), men_edit_menu);
+
+  cut = gtk_image_menu_item_new_from_stock ("gtk-cut", accel_group);
+  gtk_widget_show (cut);
+  gtk_widget_set_sensitive(cut, False);
+  gtk_container_add (GTK_CONTAINER (men_edit_menu), cut);
+
+  copy = gtk_image_menu_item_new_from_stock ("gtk-copy", accel_group);
+  gtk_widget_show (copy);
+  gtk_widget_set_sensitive(copy, False);
+  gtk_container_add (GTK_CONTAINER (men_edit_menu), copy);
+
+  paste = gtk_image_menu_item_new_from_stock ("gtk-paste", accel_group);
+  gtk_widget_show (paste);
+  gtk_widget_set_sensitive(paste, False);
+  gtk_container_add (GTK_CONTAINER (men_edit_menu), paste);
+
+  delete = gtk_image_menu_item_new_from_stock ("gtk-delete", accel_group);
+  gtk_widget_show (delete);
+  gtk_widget_set_sensitive(delete, False);
+  gtk_container_add (GTK_CONTAINER (men_edit_menu), delete);
+
+  help = gtk_menu_item_new_with_mnemonic ("_Help");
+  gtk_widget_show (help);
+  gtk_container_add (GTK_CONTAINER (menubar), help);
+
+  help_menu = gtk_menu_new ();
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), help_menu);
+
+  about = gtk_menu_item_new_with_mnemonic ("_About");
+  gtk_widget_show (about);
+  gtk_container_add (GTK_CONTAINER (help_menu), about);
+
+  hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_show (hbox1);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
+
+  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_show (scrolledwindow1);
+  gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow1, TRUE, TRUE, 0);
+
+  tree_keys = gtk_tree_view_new ();
+
+  /* Column names */
+  curcol = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title(curcol, "Name");
+  renderer = gtk_cell_renderer_text_new();
+  gtk_tree_view_column_pack_start(curcol, renderer, True);
+
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_keys), curcol);
+
+  gtk_tree_view_column_add_attribute(curcol, renderer, "text", 0);
+  gtk_widget_show (tree_keys);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow1), tree_keys);
+  store_keys = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
+  gtk_tree_view_set_model(GTK_TREE_VIEW(tree_keys), GTK_TREE_MODEL(store_keys));
+  g_object_unref(store_keys);
+
+  g_signal_connect ((gpointer) tree_keys, "row-activated",
+                    G_CALLBACK (on_key_activate),
+                    NULL);
+
+  g_signal_connect ((gpointer) tree_keys, "row-expanded",
+                    G_CALLBACK (expand_key),
+                    NULL);
+
+  scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_show (scrolledwindow2);
+  gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow2, TRUE, TRUE, 0);
+
+  tree_vals = gtk_tree_view_new ();
+    /* Column names */
+  curcol = gtk_tree_view_column_new_with_attributes ("Name", gtk_cell_renderer_text_new(), NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol);
+
+  
+  curcol = gtk_tree_view_column_new_with_attributes ("Type", gtk_cell_renderer_text_new(), NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol);
+                                                                                
+  curcol = gtk_tree_view_column_new_with_attributes ("Value", gtk_cell_renderer_text_new(), NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol);
+  gtk_widget_show (tree_vals);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow2), tree_vals);
+
+  store_vals = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
+  gtk_tree_view_set_model(GTK_TREE_VIEW(tree_vals), GTK_TREE_MODEL(store_vals));
+  g_object_unref(store_vals);
+
+  statusbar = gtk_statusbar_new ();
+  gtk_widget_show (statusbar);
+  gtk_box_pack_start (GTK_BOX (vbox1), statusbar, FALSE, FALSE, 0);
+  gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE);
+
+  g_signal_connect ((gpointer) open_nt4, "activate",
+                    G_CALLBACK (on_open_nt4_activate),
+                    NULL);
+  g_signal_connect ((gpointer) open_gconf, "activate",
+                    G_CALLBACK (on_open_gconf_activate),
+                    NULL);
+  g_signal_connect ((gpointer) open_remote, "activate",
+                    G_CALLBACK (on_open_remote_activate),
+                    NULL);
+  g_signal_connect ((gpointer) save, "activate",
+                    G_CALLBACK (on_save_activate),
+                    NULL);
+  g_signal_connect ((gpointer) save_as, "activate",
+                    G_CALLBACK (on_save_as_activate),
+                    NULL);
+  g_signal_connect ((gpointer) quit, "activate",
+                    G_CALLBACK (on_quit_activate),
+                    NULL);
+  g_signal_connect ((gpointer) cut, "activate",
+                    G_CALLBACK (on_cut_activate),
+                    NULL);
+  g_signal_connect ((gpointer) copy, "activate",
+                    G_CALLBACK (on_copy_activate),
+                    NULL);
+  g_signal_connect ((gpointer) paste, "activate",
+                    G_CALLBACK (on_paste_activate),
+                    NULL);
+  g_signal_connect ((gpointer) delete, "activate",
+                    G_CALLBACK (on_delete_activate),
+                    NULL);
+  g_signal_connect ((gpointer) about, "activate",
+                    G_CALLBACK (on_about_activate),
+                    NULL);
+
+  gtk_window_add_accel_group (GTK_WINDOW (mainwin), accel_group);
+
+  return mainwin;
+}
+
+static GtkWidget* create_aboutwin (void)
+{
+  GtkWidget *dialog_vbox1;
+  GtkWidget *image1;
+  GtkWidget *label1;
+  GtkWidget *label2;
+  GtkWidget *dialog_action_area1;
+  GtkWidget *closebutton1;
+
+  aboutwin = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (aboutwin), "About GRegEdit");
+  gtk_window_set_resizable (GTK_WINDOW (aboutwin), FALSE);
+
+  dialog_vbox1 = GTK_DIALOG (aboutwin)->vbox;
+  gtk_widget_show (dialog_vbox1);
+
+  /* FIXME: Samba logo ? 
+  image1 = create_pixmap (aboutwin, "samba.png");
+  gtk_widget_show (image1);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox1), image1, FALSE, TRUE, 0); */
+
+  label1 = gtk_label_new ("GRegEdit 0.1");
+  gtk_widget_show (label1);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox1), label1, FALSE, FALSE, 0);
+  gtk_label_set_use_markup (GTK_LABEL (label1), TRUE);
+
+  label2 = gtk_label_new_with_mnemonic ("(C) 2004 Jelmer Vernooij <jelmer@samba.org>\nPart of Samba\nhttp://www.samba.org/\n");
+  gtk_widget_show (label2);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox1), label2, TRUE, FALSE, 0);
+  gtk_label_set_use_markup (GTK_LABEL (label2), TRUE);
+
+  dialog_action_area1 = GTK_DIALOG (aboutwin)->action_area;
+  gtk_widget_show (dialog_action_area1);
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+
+  closebutton1 = gtk_button_new_from_stock ("gtk-close");
+  gtk_widget_show (closebutton1);
+  gtk_dialog_add_action_widget (GTK_DIALOG (aboutwin), closebutton1, GTK_RESPONSE_CLOSE);
+  GTK_WIDGET_SET_FLAGS (closebutton1, GTK_CAN_DEFAULT);
+
+  return aboutwin;
+}
+
+
+GtkWidget* create_openfilewin (void)
+{
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+
+  openfilewin = gtk_file_selection_new ("Select File");
+  gtk_container_set_border_width (GTK_CONTAINER (openfilewin), 10);
+
+  ok_button = GTK_FILE_SELECTION (openfilewin)->ok_button;
+  gtk_widget_show (ok_button);
+  GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
+
+  cancel_button = GTK_FILE_SELECTION (openfilewin)->cancel_button;
+  gtk_widget_show (cancel_button);
+  GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT);
+
+  return openfilewin;
+}
+
+GtkWidget* create_savefilewin (void)
+{
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+
+  savefilewin = gtk_file_selection_new ("Select File");
+  gtk_container_set_border_width (GTK_CONTAINER (savefilewin), 10);
+
+  ok_button = GTK_FILE_SELECTION (savefilewin)->ok_button;
+  gtk_widget_show (ok_button);
+  GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
+
+  cancel_button = GTK_FILE_SELECTION (savefilewin)->cancel_button;
+  gtk_widget_show (cancel_button);
+  GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT);
+
+  return savefilewin;
+}
+
+int main (int argc, char *argv[])
+{
+  poptContext pc;
+  const char *backend = NULL, *credentials = NULL, *location;
+  int opt;
+  struct poptOption long_options[] = {
+       POPT_AUTOHELP
+       {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
+          {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%%password)", NULL},
+       POPT_TABLEEND
+    };
+                                                                              
+    gtk_init (&argc, &argv);
+
+    pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
+                                                                              
+    while((opt = poptGetNextOpt(pc)) != -1) {
+    }
+
+       location = poptGetArg(pc);
+
+       if(location) {
+               WERROR error;
+
+               if(!backend) {
+                       if(credentials)backend = "rpc";
+                       else backend = "nt4";
+               }
+               
+               error = reg_open(backend, location, credentials, &registry);
+               if(!W_ERROR_IS_OK(error)) {
+                       gtk_show_werror(error);
+                       return -1;
+               }
+               mainwin = create_mainwin ();
+               registry_load_root();
+       } else 
+               mainwin = create_mainwin ();
+
+       gtk_widget_show (mainwin);
+
+       gtk_main ();
+
+       if(registry)reg_free(registry);
+       return 0;
+}
index 9074d1c71609203099fc15a65da4e629931512cb..e6b5fa51ee59d56e98ec050e7d4525f0cf03b799 100644 (file)
@@ -201,6 +201,7 @@ int main (int argc, char **argv)
        REG_HANDLE *h;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
+               POPT_COMMON_SAMBA
                {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
                POPT_TABLEEND
        };
index 56c7ba6ddefe6da09796aee09a2d34702117f493..39e46c0761da580ac4b657db88104a4a66ad44e9 100644 (file)
                [in,out,ref] policy_handle *handle,
                [in] winreg_String key,
                [in] winreg_String class,
-               [in,out] uint32 reserved,
+               [in] uint32 reserved,
+               [out] uint32 *unknown,
                [in] uint32 access_mask,
-               [in] uint32 sec_info,
-               [in] sec_desc_buf *sec_desc,
-               [in] uint32 reserved2
+               [in,ref] uint32 *sec_info,
+               [in] sec_desc_buf *sec_desc
        );
 
        /******************/
        /******************/
        /* Function: 0x0c */
        WERROR winreg_GetKeySecurity(
+               [in,ref] policy_handle *handle,
+               [in] uint32 sec_info,
+               [in] uint32 *len1,
+               [in] uint32 empty,
+               [in] uint32 len2,
+               [in] uint32 unknown1,
+               [in] uint32 unknown2,
+               [out] sec_desc_buf *data
        );
 
        /******************/
        /******************/
        /* Function: 0x15 */
        WERROR winreg_SetKeySecurity(
+               [in,ref] policy_handle *handle,
+               [in] uint32 sec_info,
+               [in] sec_desc_buf *sec_desc
        );
 
+       typedef struct {
+               uint32 max_len;
+               [length_is(buf_max_len)] uint8 *buffer;
+               uint32 len;
+       } winreg_Value;
+
        /******************/
        /* Function: 0x16 */
        WERROR winreg_SetValue(
+               [in,ref] policy_handle *handle,
+               [in] winreg_String name,
+               [in] uint32 type,
+               [in] winreg_Value value
        );
 
        /******************/
        /******************/
        /* Function: 0x18 */
        WERROR winreg_InitiateSystemShutdown(
+               [in]    winreg_String message,
+               [in]    uint32 timeout,
+               [in]    uint16 flags
        );
 
        /******************/
        /* Function: 0x19 */
        WERROR winreg_AbortSystemShutdown(
+               [in,ref]        uint16 *server
        );
 
        /******************/
        /******************/
        /* Function: 0x1e */
        WERROR winreg_InitiateSystemShutdownEx(
-       );
+               );
 
        /******************/
        /* Function: 0x1f */
index c1d6d6ad69206294007b73258a1108de482b18ee..d9e8b49765ecf89a0f77a03b760f68a86f1c6948 100644 (file)
 
 #include "includes.h"
 
+/**
+ * General notes for the current implementation:
+ * 
+ * - All hives are currently openened as subkeys of one single registry file 
+ *   (e.g. HKCR from \HKEY_CURRENT_USER, etc). This might be changed in 
+ *   the future and we might want to make it possible to configure 
+ *   what registries are behind which hives (e.g. 
+ *     \HKEY_CURRENT_USER -> gconf,
+ *     \HKEY_LOCAL_MACHINE -> tdb,
+ *     etc
+ */
+
 enum handle_types { HTYPE_REGKEY, HTYPE_REGVAL };
 
 struct _privatedata {
@@ -39,9 +51,10 @@ static void winreg_unbind(struct dcesrv_connection *dc, const struct dcesrv_inte
 static NTSTATUS winreg_bind(struct dcesrv_call_state *dc, const struct dcesrv_interface *di) 
 {
        struct _privatedata *data;
-       data = talloc(dc->mem_ctx, sizeof(struct _privatedata));
-       data->registry = reg_open(lp_parm_string(-1,"winreg","subsystem"),lp_parm_string(-1,"winreg", "file"), False);
-       if(!data->registry) return NT_STATUS_UNSUCCESSFUL;
+       WERROR error;
+       data = talloc(dc->conn->mem_ctx, sizeof(struct _privatedata));
+       error = reg_open("dir", "/tmp/reg", "", &data->registry);
+       if(!W_ERROR_IS_OK(error)) return werror_to_ntstatus(error);
        dc->conn->private = data;
        return NT_STATUS_OK;
 }
@@ -49,88 +62,78 @@ static NTSTATUS winreg_bind(struct dcesrv_call_state *dc, const struct dcesrv_in
 #define DCESRV_INTERFACE_WINREG_BIND winreg_bind
 #define DCESRV_INTERFACE_WINREG_UNBIND winreg_unbind
 
-/* 
-  winreg_OpenHKCR 
-*/
-static NTSTATUS winreg_OpenHKCR(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKCR *r)
-{
-       
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
+#define func_winreg_OpenHive(k,n) static NTSTATUS winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
+{ \
+       struct _privatedata *data = dce_call->conn->private; \
+       REG_KEY *root/* = reg_get_root(data->registry)*/; \
+       REG_KEY *k/* = reg_open_key(root, n)*/; \
+\
+       if(!k) { \
+               r->out.result = WERR_BADFILE; \
+       } else { \
+               struct dcesrv_handle *h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY); \
+               h->data = k; \
+               r->out.handle = &h->wire_handle; \
+       } \
+\
+       r->out.result = WERR_OK; \
+\
+       return NT_STATUS_OK; \
+}
+
+func_winreg_OpenHive(HKCR,"\\HKEY_CLASSES_ROOT")
+func_winreg_OpenHive(HKCU,"\\HKEY_CURRENT_USER")
+func_winreg_OpenHive(HKLM,"\\HKEY_LOCAL_MACHINE")
+func_winreg_OpenHive(HKPD,"\\HKEY_PERFORMANCE_DATA")
+func_winreg_OpenHive(HKU,"\\HKEY_USERS")
+func_winreg_OpenHive(HKCC,"\\HKEY_CC")
+func_winreg_OpenHive(HKDD,"\\HKEY_DD")
+func_winreg_OpenHive(HKPT,"\\HKEY_PT")
+func_winreg_OpenHive(HKPN,"\\HKEY_PN")
 
 /* 
-  winreg_OpenHKCU 
+  winreg_CloseKey 
 */
-static NTSTATUS winreg_OpenHKCU(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKCU *r)
+static NTSTATUS winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct winreg_CloseKey *r)
 {
-       struct _privatedata *data = dce_call->conn->private;
-       REG_KEY *root = reg_get_root(data->registry);
-       REG_KEY *k = reg_open_key(root, "\\HKEY_CURRENT_USER");
-
-       if(!k) {
-               r->out.result = WERR_BADFILE;
-       } else {
-               struct dcesrv_handle *h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY);
-               h->data = k;
-               r->out.handle = &h->wire_handle;
+       struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
+       if(!h) {
+               return NT_STATUS_INVALID_HANDLE;
        }
 
-       r->out.result = WERR_OK;
+       reg_key_free((REG_KEY *)h->data);
+       dcesrv_handle_destroy(dce_call->conn, h);
 
        return NT_STATUS_OK;
 }
 
 
-/* 
-  winreg_OpenHKLM 
-*/
-static NTSTATUS winreg_OpenHKLM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKLM *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* 
-  winreg_OpenHKPD 
-*/
-static NTSTATUS winreg_OpenHKPD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKPD *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* 
-  winreg_OpenHKU 
-*/
-static NTSTATUS winreg_OpenHKU(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKU *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* 
-  winreg_CloseKey 
-*/
-static NTSTATUS winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_CloseKey *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
 /* 
   winreg_CreateKey 
 */
 static NTSTATUS winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct winreg_CreateKey *r)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
+       WERROR error;
+       REG_KEY *parent;
+       if(!h) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       parent = h->data;
+       error = reg_key_add_name_recursive(parent, r->in.key.name);
+       if(W_ERROR_IS_OK(error)) {
+               struct dcesrv_handle *newh = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY);
+               error = reg_open_key(parent, r->in.key.name, (REG_KEY **)&newh->data);
+               if(W_ERROR_IS_OK(error)) r->out.handle = &newh->wire_handle;
+               else dcesrv_handle_destroy(dce_call->conn, newh);
+       }
+
+       r->out.result = error;
+
+       return NT_STATUS_OK;
 }
 
 
@@ -140,7 +143,19 @@ static NTSTATUS winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX
 static NTSTATUS winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct winreg_DeleteKey *r)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
+       REG_KEY *parent, *key;
+       WERROR error;
+       if(!h) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       parent = h->data;
+       r->out.result = reg_open_key(parent, r->in.key.name, &key);
+       if(W_ERROR_IS_OK(r->out.result)) {
+               r->out.result = reg_key_del(key);
+       }
+       return NT_STATUS_OK;
 }
 
 
@@ -160,6 +175,14 @@ static NTSTATUS winreg_DeleteValue(struct dcesrv_call_state *dce_call, TALLOC_CT
 static NTSTATUS winreg_EnumKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct winreg_EnumKey *r)
 {
+       struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
+       REG_KEY *key;
+       if(!h) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       key = h->data;
+       
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -221,11 +244,22 @@ static NTSTATUS winreg_OpenKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
                       struct winreg_OpenKey *r)
 {
        struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY);
+       REG_KEY *k, *subkey;
        if(!h) {
                return NT_STATUS_INVALID_HANDLE;
        }
+
+       k = h->data;
+
+
+       r->out.result = reg_open_key(k, r->in.keyname.name, &subkey);
+       if(W_ERROR_IS_OK(r->out.result)) {
+               struct dcesrv_handle *newh = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY); 
+               h->data = subkey; 
+               r->out.handle = &h->wire_handle; 
+       }
        
-       return NT_STATUS_NOT_IMPLEMENTED;
+       return NT_STATUS_OK;
 }
 
 
@@ -339,26 +373,6 @@ static NTSTATUS winreg_GetVersion(struct dcesrv_call_state *dce_call, TALLOC_CTX
 }
 
 
-/* 
-  winreg_OpenHKCC 
-*/
-static NTSTATUS winreg_OpenHKCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKCC *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* 
-  winreg_OpenHKDD 
-*/
-static NTSTATUS winreg_OpenHKDD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKDD *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
 /* 
   winreg_QueryMultipleValues 
 */
@@ -389,26 +403,6 @@ static NTSTATUS winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX
 }
 
 
-/* 
-  winreg_OpenHKPT 
-*/
-static NTSTATUS winreg_OpenHKPT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKPT *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* 
-  winreg_OpenHKPN 
-*/
-static NTSTATUS winreg_OpenHKPN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct winreg_OpenHKPN *r)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
 /* 
   winreg_QueryMultipleValues2 
 */
index 72fdc96c11fbad2354f827b0bb9196575b8454fb..68466f0084b0f8c652553a79220e0f55aa3ff493 100644 (file)
@@ -54,27 +54,24 @@ static BOOL test_GetVersion(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_CreateKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                         struct policy_handle *handle, const char *name, const char *class)
+                         struct policy_handle *handle, char *name, const char *class)
 {
        struct winreg_CreateKey r;
        struct policy_handle newhandle;
        NTSTATUS status;
        struct sec_desc_buf sec_desc;
+       uint32 sec_info = 0;
 
        printf("\ntesting CreateKey\n");
 
        r.in.handle = handle;
        r.out.handle = &newhandle;
        init_winreg_String(&r.in.key, name);    
-       init_winreg_String(&r.in.class, class); 
+       init_winreg_String(&r.in.class, class);
        r.in.reserved = 0x0;
-       r.in.reserved2 = 0x0;
        r.in.access_mask = 0x02000000;
-       r.out.reserved = 0x0;
-       r.in.sec_info = 0x0;
-       sec_desc.size = 0;
-       sec_desc.sd = NULL;
-       r.in.sec_desc = &sec_desc;
+       r.in.sec_info = &sec_info;
+       r.in.sec_desc = NULL;
 
        status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
 
@@ -148,6 +145,11 @@ static BOOL test_OpenKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        status = dcerpc_winreg_OpenKey(p, mem_ctx, &r);
 
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OpenKey failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
        if (!W_ERROR_IS_OK(r.out.result)) {
                printf("OpenKey failed - %s\n", win_errstr(r.out.result));
                return False;
@@ -195,6 +197,11 @@ static BOOL test_QueryInfoKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        
        status = dcerpc_winreg_QueryInfoKey(p, mem_ctx, &r);
 
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("QueryInfoKey failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
        if (!W_ERROR_IS_OK(r.out.result)) {
                printf("QueryInfoKey failed - %s\n", win_errstr(r.out.result));
                return False;
@@ -371,6 +378,53 @@ static BOOL test_OpenHKCR(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                       const char *msg, uint32 timeout)
+{
+       struct winreg_InitiateSystemShutdown r;
+       NTSTATUS status;
+       
+       init_winreg_String(&r.in.message, msg);
+       r.in.flags = 0;
+       r.in.timeout = timeout;
+
+       status = dcerpc_winreg_InitiateSystemShutdown(p, mem_ctx, &r);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("InitiateSystemShutdown failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("InitiateSystemShutdown failed - %s\n", win_errstr(r.out.result));
+               return False;
+       }
+
+       return True;
+}
+
+static BOOL test_AbortSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       struct winreg_AbortSystemShutdown r;
+       NTSTATUS status;
+
+       r.in.server = 0x0;
+       
+       status = dcerpc_winreg_AbortSystemShutdown(p, mem_ctx, &r);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("AbortSystemShutdown failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("AbortSystemShutdown failed - %s\n", win_errstr(r.out.result));
+               return False;
+       }
+
+       return True;
+}
+
 static BOOL test_OpenHKCU(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                          struct policy_handle *handle)
 {
@@ -433,17 +487,7 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn)
        if (!open_fn(p, mem_ctx, &handle))
                return False;
 
-       if (!test_GetVersion(p, mem_ctx, &handle)) {
-               printf("GetVersion failed\n");
-               ret = False;
-       }
-
-       if (!test_FlushKey(p, mem_ctx, &handle)) {
-               printf("FlushKey failed\n");
-               ret = False;
-       }
-
-       if (!test_CreateKey(p, mem_ctx, &handle, "spottyfoot", "foo")) {
+       if (!test_CreateKey(p, mem_ctx, &handle, "spottyfoot", NULL)) {
                printf("CreateKey failed\n");
                ret = False;
        }
@@ -463,6 +507,16 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn)
                ret = False;
        }
 
+       if (!test_GetVersion(p, mem_ctx, &handle)) {
+               printf("GetVersion failed\n");
+               ret = False;
+       }
+
+       if (!test_FlushKey(p, mem_ctx, &handle)) {
+               printf("FlushKey failed\n");
+               ret = False;
+       }
+
 
        /* The HKCR hive has a very large fanout */
 
@@ -482,7 +536,7 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn)
 BOOL torture_rpc_winreg(int dummy)
 {
         NTSTATUS status;
-        struct dcerpc_pipe *p;
+       struct dcerpc_pipe *p;
        TALLOC_CTX *mem_ctx;
        BOOL ret = True;
        winreg_open_fn *open_fns[] = { test_OpenHKLM, test_OpenHKU,
@@ -500,6 +554,9 @@ BOOL torture_rpc_winreg(int dummy)
                return False;
        }
 
+       if(!test_InitiateSystemShutdown(p, mem_ctx, "spottyfood", 30))
+               ret = False;
+
        for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
                if (!test_Open(p, mem_ctx, open_fns[i]))
                        ret = False;