From aebfb3b9f415d3c1f6b2a39aee27b072d48893cb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 8 Apr 2004 22:39:47 +0000 Subject: r128: Another registry update. Changes: - 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) --- source4/lib/registry/TODO | 18 +- source4/lib/registry/common/reg_interface.c | 368 +++++----- source4/lib/registry/common/reg_util.c | 22 +- source4/lib/registry/common/registry.h | 55 +- source4/lib/registry/config.m4 | 3 + .../lib/registry/reg_backend_dir/reg_backend_dir.c | 46 +- .../registry/reg_backend_gconf/reg_backend_gconf.c | 54 +- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 75 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 106 +-- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 85 ++- .../registry/reg_backend_wine/reg_backend_wine.c | 1 + source4/lib/registry/tools/gregedit.c | 758 +++++++++++++++++++++ source4/lib/registry/tools/regshell.c | 1 + 13 files changed, 1266 insertions(+), 326 deletions(-) create mode 100644 source4/lib/registry/tools/gregedit.c (limited to 'source4/lib/registry') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index ac467d0078..fc741cea40 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -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 diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index b6b38e9b62..9c78ae55fb 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -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; +} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 060d053fc2..5ca104fc2e 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -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); } diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 3565a7a585..6e12de258d 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -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; }; diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 146ef92b95..90dc50728b 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -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) diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 9cb15cd285..4daaf3d628 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -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, diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 71d3361ce2..1acb3cbcec 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -22,18 +22,26 @@ #include "lib/registry/common/registry.h" #include -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, diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index afa60c5c4a..3cc1651519 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -20,51 +20,96 @@ #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, diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index ef2565bda8..9d90523a75 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -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(®f_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, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index ad4d537f9b..e61301d6f2 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -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, diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c index 6c8d7885cb..fd7d04bcf0 100644 --- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c +++ b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c @@ -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 index 0000000000..b62fd7ec04 --- /dev/null +++ b/source4/lib/registry/tools/gregedit.c @@ -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 +#endif + +#include +#include +#include +#include +#include + +#include +#include +#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, ®istry); + 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, ®istry); + 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, ®istry); + 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 \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, ®istry); + 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; +} diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 9074d1c716..e6b5fa51ee 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -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 }; -- cgit