summaryrefslogtreecommitdiff
path: root/source4/lib/registry
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-04-08 22:39:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:51:09 -0500
commitaebfb3b9f415d3c1f6b2a39aee27b072d48893cb (patch)
tree4eebbcafdd559216ef8ad952f11ebe05f947b5f0 /source4/lib/registry
parentd907dcf383fcdf82add4fd7c397885eab5bb57af (diff)
downloadsamba-aebfb3b9f415d3c1f6b2a39aee27b072d48893cb.tar.gz
samba-aebfb3b9f415d3c1f6b2a39aee27b072d48893cb.tar.bz2
samba-aebfb3b9f415d3c1f6b2a39aee27b072d48893cb.zip
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)
Diffstat (limited to 'source4/lib/registry')
-rw-r--r--source4/lib/registry/TODO18
-rw-r--r--source4/lib/registry/common/reg_interface.c368
-rw-r--r--source4/lib/registry/common/reg_util.c22
-rw-r--r--source4/lib/registry/common/registry.h55
-rw-r--r--source4/lib/registry/config.m43
-rw-r--r--source4/lib/registry/reg_backend_dir/reg_backend_dir.c46
-rw-r--r--source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c54
-rw-r--r--source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c75
-rw-r--r--source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c106
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c85
-rw-r--r--source4/lib/registry/reg_backend_wine/reg_backend_wine.c1
-rw-r--r--source4/lib/registry/tools/gregedit.c758
-rw-r--r--source4/lib/registry/tools/regshell.c1
13 files changed, 1266 insertions, 326 deletions
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 <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,
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(&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,
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 <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;
+}
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
};