summaryrefslogtreecommitdiff
path: root/source4/lib/registry/common
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-04-04 16:24:08 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:50:33 -0500
commitc424c2b857fe08587eb81a5c5e3625545119d1c2 (patch)
tree03505d09ccd72cdfd1218066d355e2d01d403bd0 /source4/lib/registry/common
parent3855ee0164d1c8ff3c3c4ba8a5556d8cfb6546b3 (diff)
downloadsamba-c424c2b857fe08587eb81a5c5e3625545119d1c2.tar.gz
samba-c424c2b857fe08587eb81a5c5e3625545119d1c2.tar.bz2
samba-c424c2b857fe08587eb81a5c5e3625545119d1c2.zip
r20: Add the registry library. Still needs a lot of work,
see source/lib/registry/TODO for details. (This used to be commit 7cab3a00d7b4b1d95a3bfa6b28f318b4aaa5d493)
Diffstat (limited to 'source4/lib/registry/common')
-rw-r--r--source4/lib/registry/common/reg_display.c60
-rw-r--r--source4/lib/registry/common/reg_interface.c423
-rw-r--r--source4/lib/registry/common/reg_objects.c202
-rw-r--r--source4/lib/registry/common/reg_util.c164
-rw-r--r--source4/lib/registry/common/registry.h121
5 files changed, 970 insertions, 0 deletions
diff --git a/source4/lib/registry/common/reg_display.c b/source4/lib/registry/common/reg_display.c
new file mode 100644
index 0000000000..e12f4ba20e
--- /dev/null
+++ b/source4/lib/registry/common/reg_display.c
@@ -0,0 +1,60 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Gerald Carter 2001
+ Copyright (C) Tim Potter 2000
+ 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.
+*/
+
+#include "includes.h"
+
+void display_reg_value(REG_VAL *value)
+{
+ pstring text;
+
+ switch(reg_val_type(value)) {
+ case REG_DWORD:
+ printf("%s: REG_DWORD: 0x%08x\n", reg_val_name(value),
+ *((uint32 *) reg_val_data_blk(value)));
+ break;
+ case REG_SZ:
+ rpcstr_pull(text, reg_val_data_blk(value), sizeof(text), reg_val_size(value),
+ STR_TERMINATE);
+ printf("%s: REG_SZ: %s\n", reg_val_name(value), text);
+ break;
+ case REG_BINARY:
+ printf("%s: REG_BINARY: unknown length value not displayed\n",
+ reg_val_name(value));
+ break;
+ case REG_MULTI_SZ: {
+ uint16 *curstr = (uint16 *) reg_val_data_blk(value);
+ uint8 *start = reg_val_data_blk(value);
+ printf("%s: REG_MULTI_SZ:\n", reg_val_name(value));
+ while ((*curstr != 0) &&
+ ((uint8 *) curstr < start + reg_val_size(value))) {
+ rpcstr_pull(text, curstr, sizeof(text), -1,
+ STR_TERMINATE);
+ printf(" %s\n", text);
+ curstr += strlen(text) + 1;
+ }
+ }
+ break;
+ default:
+ printf("%s: unknown type %d\n", reg_val_name(value), reg_val_type(value));
+ }
+
+}
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
new file mode 100644
index 0000000000..dc49dab4c1
--- /dev/null
+++ b/source4/lib/registry/common/reg_interface.c
@@ -0,0 +1,423 @@
+/*
+ Unix SMB/CIFS implementation.
+ Transparent registry backend handling
+ Copyright (C) Jelmer Vernooij 2003-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.
+*/
+
+#include "includes.h"
+#include "lib/registry/common/registry.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+/* List of available backends */
+static struct reg_init_function_entry *backends = NULL;
+
+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 reg_init_function_entry *entry = backends;
+
+ if (!functions || !functions->name) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
+
+ /* Check for duplicates */
+ if (reg_find_backend_entry(functions->name)) {
+ DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ entry = malloc(sizeof(struct reg_init_function_entry));
+ entry->functions = functions;
+
+ DLIST_ADD(backends, entry);
+ DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
+ return NT_STATUS_OK;
+}
+
+
+/* Find a backend in the list of available backends */
+static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
+{
+ struct reg_init_function_entry *entry = backends;
+
+ while(entry) {
+ if (strcmp(entry->functions->name, name)==0) return entry;
+ entry = entry->next;
+ }
+
+ return NULL;
+}
+
+/* Open a registry file/host/etc */
+REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_load)
+{
+ struct reg_init_function_entry *entry;
+ static BOOL reg_first_init = True;
+ REG_HANDLE *ret;
+
+ if(reg_first_init) {
+ if (!NT_STATUS_IS_OK(register_subsystem("registry", registry_register))) {
+ return False;
+ }
+
+ static_init_reg;
+ reg_first_init = False;
+ }
+
+ entry = reg_find_backend_entry(backend);
+
+ if (!entry) {
+ DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
+ return NULL;
+ }
+
+ ret = malloc(sizeof(REG_HANDLE));
+ ZERO_STRUCTP(ret);
+ ret->location = location?strdup(location):NULL;
+ ret->functions = entry->functions;
+ ret->backend_data = NULL;
+
+ if(!entry->functions->open_registry) {
+ return ret;
+ }
+
+ if(entry->functions->open_registry(ret, location, try_full_load))
+ return ret;
+
+ SAFE_FREE(ret);
+ return NULL;
+}
+
+/* Open a key */
+REG_KEY *reg_open_key(REG_KEY *parent, const char *name)
+{
+ char *fullname;
+ REG_KEY *ret = NULL;
+
+ if(!parent) {
+ DEBUG(0, ("Invalid parent key specified"));
+ return NULL;
+ }
+
+ if(!parent->handle->functions->open_key &&
+ (parent->handle->functions->get_subkey_by_name ||
+ parent->handle->functions->get_subkey_by_index)) {
+ char *orig = strdup(name),
+ *curbegin = orig,
+ *curend = strchr(orig, '\\');
+ REG_KEY *curkey = parent;
+
+ while(curbegin && *curbegin) {
+ if(curend)*curend = '\0';
+ curkey = reg_key_get_subkey_by_name(curkey, curbegin);
+ if(!curkey) return NULL;
+ if(!curend) break;
+ curbegin = curend + 1;
+ curend = strchr(curbegin, '\\');
+ }
+
+ return curkey;
+ }
+
+ asprintf(&fullname, "%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;
+ }
+
+ ret = parent->handle->functions->open_key(parent->handle, fullname);
+
+ if(ret) {
+ ret->handle = parent->handle;
+ ret->path = fullname;
+ } else
+ SAFE_FREE(fullname);
+
+ return ret;
+}
+
+REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx)
+{
+ REG_VAL *ret;
+
+ if(!key) return NULL;
+
+ 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]);
+ } else {
+ return NULL;
+ }
+ } else {
+ ret = key->handle->functions->get_value_by_index(key, idx);
+ }
+
+ if(ret) {
+ ret->parent = key;
+ ret->handle = key->handle;
+ }
+
+ return ret;
+}
+
+int reg_key_num_subkeys(REG_KEY *key)
+{
+ 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;
+ }
+
+ return key->handle->functions->num_subkeys(key);
+}
+
+int reg_key_num_values(REG_KEY *key)
+{
+
+ if(!key) return 0;
+
+ 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;
+ }
+
+ if(!key->cache_values)
+ key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
+
+ return key->cache_values_count;
+ }
+
+
+ return key->handle->functions->num_values(key);
+}
+
+REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx)
+{
+ REG_KEY *ret = NULL;
+
+ if(!key) return NULL;
+
+ 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]);
+ } else {
+ /* No such key ! */
+ return NULL;
+ }
+ } else {
+ ret = key->handle->functions->get_subkey_by_index(key, idx);
+ }
+
+ if(ret && !ret->path) {
+ asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
+ ret->handle = key->handle;
+ }
+
+ return ret;
+}
+
+REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name)
+{
+ int i, max;
+ REG_KEY *ret = NULL;
+
+ if(!key) return NULL;
+
+ if(key->handle->functions->get_subkey_by_name) {
+ ret = key->handle->functions->get_subkey_by_name(key,name);
+ } 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;
+ break;
+ }
+ reg_key_free(v);
+ }
+ }
+
+ if(ret && !ret->path) {
+ asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name);
+ ret->handle = key->handle;
+ }
+
+ return ret;
+}
+
+REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name)
+{
+ int i, max;
+ REG_VAL *ret = NULL;
+
+ if(!key) return NULL;
+
+ if(key->handle->functions->get_value_by_name) {
+ ret = key->handle->functions->get_value_by_name(key,name);
+ } 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;
+ break;
+ }
+ reg_val_free(v);
+ }
+ }
+
+ if(ret) {
+ ret->parent = key;
+ ret->handle = key->handle;
+ }
+
+ return ret;
+}
+
+BOOL reg_key_del(REG_KEY *key)
+{
+ if(key->handle->functions->del_key)
+ return key->handle->functions->del_key(key);
+
+ return False;
+}
+
+BOOL reg_sync(REG_HANDLE *h, const char *location)
+{
+ if(!h->functions->sync)
+ return True;
+
+ return h->functions->sync(h, location);
+}
+
+BOOL reg_key_del_recursive(REG_KEY *key)
+{
+ BOOL succeed = True;
+ 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;
+ }
+
+ /* 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;
+ }
+
+ if(succeed)reg_key_del(key);
+
+ return succeed;
+}
+
+BOOL reg_val_del(REG_VAL *val)
+{
+ if (!val->handle->functions->del_value) {
+ DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name));
+ return False;
+ }
+
+ return val->handle->functions->del_value(val);
+}
+
+BOOL reg_key_add_name(REG_KEY *parent, const char *name)
+{
+ if (!parent->handle->functions->add_key) {
+ DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name));
+ return False;
+ }
+
+ return parent->handle->functions->add_key(parent, name);
+}
+
+BOOL reg_val_update(REG_VAL *val, int type, void *data, int len)
+{
+ /* A 'real' update function has preference */
+ if (val->handle->functions->update_value)
+ return val->handle->functions->update_value(val, type, data, len);
+
+ /* Otherwise, just remove and add again */
+ if (val->handle->functions->add_value &&
+ val->handle->functions->del_value) {
+ REG_VAL *new;
+ if(!val->handle->functions->del_value(val))
+ return False;
+
+ new = val->handle->functions->add_value(val->parent, val->name, type, data, len);
+ memcpy(val, new, sizeof(REG_VAL));
+ return True;
+ }
+
+ DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name));
+ return False;
+}
+
+void reg_free(REG_HANDLE *h)
+{
+ if(!h->functions->close_registry) return;
+
+ h->functions->close_registry(h);
+}
+
+REG_KEY *reg_get_root(REG_HANDLE *h)
+{
+ REG_KEY *ret = NULL;
+ if(h->functions->open_root_key) {
+ ret = h->functions->open_root_key(h);
+ } else if(h->functions->open_key) {
+ ret = h->functions->open_key(h, "\\");
+ } else {
+ DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name));
+ }
+
+ if(ret) {
+ ret->handle = h;
+ ret->path = strdup("\\");
+ }
+
+ return ret;
+}
+
+REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen)
+{
+ REG_VAL *ret;
+ if(!key->handle->functions->add_value)
+ return NULL;
+
+ ret = key->handle->functions->add_value(key, name, type, value, vallen);
+ ret->parent = key;
+ ret->handle = key->handle;
+ return ret;
+}
diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c
new file mode 100644
index 0000000000..911dc15c8e
--- /dev/null
+++ b/source4/lib/registry/common/reg_objects.c
@@ -0,0 +1,202 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Gerald Carter 2002.
+ * Copyright (C) Jelmer Vernooij 2003-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.
+ */
+
+/* Implementation of registry frontend view functions. */
+
+#include "includes.h"
+#include "lib/registry/common/registry.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/***********************************************************************
+ allocate memory for and duplicate a REG_VAL.
+ This is malloc'd memory so the caller should free it when done
+ **********************************************************************/
+
+REG_VAL* reg_val_dup( REG_VAL *val )
+{
+ REG_VAL *copy = NULL;
+
+ if ( !val )
+ return NULL;
+
+ if ( !(copy = malloc( sizeof(REG_VAL) )) ) {
+ DEBUG(0,("dup_registry_value: malloc() failed!\n"));
+ return NULL;
+ }
+
+ /* copy all the non-pointer initial data */
+
+ memcpy( copy, val, sizeof(REG_VAL) );
+ if ( val->data_blk )
+ {
+ if ( !(copy->data_blk = memdup( val->data_blk, val->data_len )) ) {
+ DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
+ val->data_len));
+ SAFE_FREE( copy );
+ }
+ }
+
+ return copy;
+}
+
+/**********************************************************************
+ free the memory allocated to a REG_VAL
+ *********************************************************************/
+
+void reg_val_free( REG_VAL *val )
+{
+ if ( !val )
+ return;
+
+ if(val->handle->functions->free_val_backend_data)
+ val->handle->functions->free_val_backend_data(val);
+
+ SAFE_FREE( val->data_blk );
+ SAFE_FREE( val );
+
+ return;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+uint8* reg_val_data_blk( REG_VAL *val )
+{
+ return val->data_blk;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+int reg_val_size( REG_VAL *val )
+{
+ return val->data_len;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+char *reg_val_name( REG_VAL *val )
+{
+ return val->name;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+uint32 reg_val_type( REG_VAL *val )
+{
+ return val->data_type;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+char *reg_key_name( REG_KEY *key )
+{
+ return key->name;
+}
+
+REG_KEY *reg_key_dup(REG_KEY *key)
+{
+ key->ref++;
+ return key;
+}
+
+void reg_key_free(REG_KEY *key)
+{
+ if(!key)
+ return;
+
+ key->ref--;
+ if(key->ref) return;
+
+ if(key->handle->functions->free_key_backend_data)
+ key->handle->functions->free_key_backend_data(key);
+
+ if(key->cache_values) {
+ int i;
+ for(i = 0; i < key->cache_values_count; i++) {
+ reg_val_free(key->cache_values[i]);
+ }
+ SAFE_FREE(key->cache_values);
+ }
+
+ if(key->cache_subkeys) {
+ int i;
+ for(i = 0; i < key->cache_subkeys_count; i++) {
+ reg_key_free(key->cache_subkeys[i]);
+ }
+ SAFE_FREE(key->cache_subkeys);
+ }
+
+ SAFE_FREE(key->path);
+ SAFE_FREE(key->name);
+ SAFE_FREE(key);
+}
+
+char *reg_val_get_path(REG_VAL *v)
+{
+ /* FIXME */
+ return NULL;
+}
+
+char *reg_key_get_path(REG_KEY *k)
+{
+ SMB_REG_ASSERT(k);
+ return k->path;
+}
+
+/* For use by the backends _ONLY_ */
+REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data)
+{
+ REG_KEY *r = malloc(sizeof(REG_KEY));
+ ZERO_STRUCTP(r);
+ r->handle = h;
+ r->path = strdup(path);
+ r->name = strdup(strrchr(path, '\\')?strrchr(path,'\\')+1:path);
+ r->backend_data = data;
+ r->ref = 1;
+ return r;
+}
+
+REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data)
+{
+ REG_KEY *r = malloc(sizeof(REG_KEY));
+ ZERO_STRUCTP(r);
+ r->handle = k->handle;
+ r->name = strdup(name);
+ r->backend_data = data;
+ r->ref = 1;
+ return r;
+}
+
+REG_VAL *reg_val_new(REG_KEY *parent, void *data)
+{
+ REG_VAL *r = malloc(sizeof(REG_VAL));
+ ZERO_STRUCTP(r);
+ r->handle = parent->handle;
+ r->backend_data = data;
+ r->ref = 1;
+ return r;
+}
diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c
new file mode 100644
index 0000000000..2941c38cf4
--- /dev/null
+++ b/source4/lib/registry/common/reg_util.c
@@ -0,0 +1,164 @@
+/*
+ Unix SMB/CIFS implementation.
+ Transparent registry backend handling
+ Copyright (C) Jelmer Vernooij 2003-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.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+/* Return string description of registry value type */
+const char *str_regtype(int type)
+{
+ switch(type) {
+ case REG_SZ: return "STRING";
+ case REG_DWORD: return "DWORD";
+ case REG_BINARY: return "BINARY";
+ }
+ return "Unknown";
+}
+
+char *reg_val_data_string(REG_VAL *v)
+{
+ char *asciip;
+ char *ret = NULL;
+ int i;
+
+ if(reg_val_size(v) == 0) return strdup("");
+
+ switch (reg_val_type(v)) {
+ case REG_SZ:
+ /* FIXME: Convert to ascii */
+ return strdup(reg_val_data_blk(v));
+
+ case REG_EXPAND_SZ:
+ return strdup(reg_val_data_blk(v));
+
+ case REG_BINARY:
+ ret = malloc(reg_val_size(v) * 3 + 2);
+ asciip = ret;
+ for (i=0; i<reg_val_size(v); i++) {
+ int str_rem = reg_val_size(v) * 3 - (asciip - ret);
+ asciip += snprintf(asciip, str_rem, "%02x", *(unsigned char *)(reg_val_data_blk(v)+i));
+ if (i < reg_val_size(v) && str_rem > 0)
+ *asciip = ' '; asciip++;
+ }
+ *asciip = '\0';
+ return ret;
+ break;
+
+ case REG_DWORD:
+ if (*(int *)reg_val_data_blk(v) == 0)
+ ret = strdup("0");
+ else
+ asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v));
+ break;
+
+ case REG_MULTI_SZ:
+ /* FIXME */
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+
+ return ret;
+}
+
+const char *reg_val_description(REG_VAL *val)
+{
+ char *ret, *ds = reg_val_data_string(val);
+ asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"<No Name>", str_regtype(reg_val_type(val)), ds);
+ free(ds);
+ return ret;
+}
+
+BOOL reg_val_set_string(REG_VAL *val, char *str)
+{
+ /* FIXME */
+ return False;
+}
+
+REG_VAL *reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname)
+{
+ REG_KEY *k = reg_key_get_subkey_by_name(key, subname);
+ if(!k) return NULL;
+
+ return reg_key_get_value_by_name(k, valname);
+}
+
+BOOL 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_VAL *v;
+ if(!k) return False;
+
+ v = reg_key_get_value_by_name(k, valname);
+ if(!v) return False;
+
+ return reg_val_update(v, type, data, real_len);
+}
+
+/***********************************************************************
+ Utility function for splitting the base path of a registry path off
+ by setting base and new_path to the apprapriate offsets withing the
+ path.
+
+ WARNING!! Does modify the original string!
+ ***********************************************************************/
+
+BOOL reg_split_path( char *path, char **base, char **new_path )
+{
+ char *p;
+
+ *new_path = *base = NULL;
+
+ if ( !path)
+ return False;
+
+ *base = path;
+
+ p = strchr( path, '\\' );
+
+ if ( p ) {
+ *p = '\0';
+ *new_path = p+1;
+ }
+
+ return True;
+}
+
+char *reg_path_win2unix(char *path)
+{
+ int i;
+ for(i = 0; path[i]; i++) {
+ if(path[i] == '\\') path[i] = '/';
+ }
+ return path;
+}
+
+char *reg_path_unix2win(char *path)
+{
+ int i;
+ for(i = 0; path[i]; i++) {
+ if(path[i] == '/') path[i] = '\\';
+ }
+ return path;
+}
diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h
new file mode 100644
index 0000000000..4b29006217
--- /dev/null
+++ b/source4/lib/registry/common/registry.h
@@ -0,0 +1,121 @@
+/*
+ Unix SMB/CIFS implementation.
+ Registry interface
+ This file contains the _internal_ structs for the registry
+ subsystem. Backends and the subsystem itself are the only
+ files that need to include this file.
+ Copyright (C) Gerald Carter 2002.
+ Copyright (C) Jelmer Vernooij 2003-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.
+*/
+
+#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */
+#define _REGISTRY_REGISTRY_H
+
+#define REGISTRY_INTERFACE_VERSION 1
+
+/* structure to store the registry handles */
+struct reg_key_s {
+ char *name; /* Name of the key */
+ char *path; /* Full path to the key */
+ smb_ucs2_t *class_name; /* Name of key class */
+ NTTIME last_mod; /* Time last modified */
+ SEC_DESC *security;
+ REG_HANDLE *handle;
+ void *backend_data;
+ REG_VAL **cache_values;
+ int cache_values_count;
+ REG_KEY **cache_subkeys;
+ int cache_subkeys_count;
+ int ref;
+};
+
+struct reg_val_s {
+ char *name;
+ int has_name;
+ int data_type;
+ int data_len;
+ void *data_blk; /* Might want a separate block */
+ REG_HANDLE *handle;
+ REG_KEY *parent;
+ void *backend_data;
+ int ref;
+};
+
+/*
+ * Container for function pointers to enumeration routines
+ * for virtual registry view
+ */
+
+struct reg_ops_s {
+ 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 *);
+
+ /* 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);
+
+ /* 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 ***);
+
+ /* Key management */
+ BOOL (*add_key)(REG_KEY *, const char *name);
+ BOOL (*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 *);
+
+ /* 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);
+
+ void (*free_key_backend_data) (REG_KEY *);
+ void (*free_val_backend_data) (REG_VAL *);
+};
+
+typedef struct reg_sub_tree_s {
+ char *path;
+ REG_HANDLE *handle;
+ struct reg_sub_tree_s *prev, *next;
+} REG_SUBTREE;
+
+struct reg_handle_s {
+ REG_OPS *functions;
+ REG_SUBTREE *subtrees;
+ char *location;
+ void *backend_data;
+};
+
+struct reg_init_function_entry {
+ /* Function to create a member of the pdb_methods list */
+ REG_OPS *functions;
+ struct reg_init_function_entry *prev, *next;
+};
+
+/* Used internally */
+#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }}
+
+#endif /* _REGISTRY_H */