summaryrefslogtreecommitdiff
path: root/source4/lib/registry
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-05-22 18:49:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:53:53 -0500
commitbf52e242f53aeaac33eea69fbdfb3477634b90fb (patch)
tree76b04dc95e3e7befd45180a661cd7f55d085701e /source4/lib/registry
parent4e9d01c2a7cd044ac4b466a1039c9a7e3978d6ef (diff)
downloadsamba-bf52e242f53aeaac33eea69fbdfb3477634b90fb.tar.gz
samba-bf52e242f53aeaac33eea69fbdfb3477634b90fb.tar.bz2
samba-bf52e242f53aeaac33eea69fbdfb3477634b90fb.zip
r825: - Introduce support for multiple roots (or 'hives')
- Clean up rpc backend (possible now that multiple hives are supported) (This used to be commit 8cd1b6bc70510fe576135a66351e9e3ea895c9ff)
Diffstat (limited to 'source4/lib/registry')
-rw-r--r--source4/lib/registry/common/reg_interface.c62
-rw-r--r--source4/lib/registry/common/reg_objects.c7
-rw-r--r--source4/lib/registry/common/registry.h24
-rw-r--r--source4/lib/registry/reg_backend_dir/reg_backend_dir.c10
-rw-r--r--source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c5
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c168
-rw-r--r--source4/lib/registry/reg_backend_w95/reg_backend_w95.c8
-rw-r--r--source4/lib/registry/tools/gregedit.c31
-rw-r--r--source4/lib/registry/tools/regdiff.c32
-rw-r--r--source4/lib/registry/tools/regpatch.c19
-rw-r--r--source4/lib/registry/tools/regshell.c3
-rw-r--r--source4/lib/registry/tools/regtree.c12
12 files changed, 213 insertions, 168 deletions
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index 4d1726c542..3e5a545f9a 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -117,6 +117,25 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia
return werr;
}
+WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result)
+{
+ REG_KEY *hive;
+ WERROR error;
+ int i, hivelength;
+
+ if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
+ else hivelength = strlen(name);
+
+ for(i = 0; W_ERROR_IS_OK(error); i++) {
+ error = reg_get_hive(handle, i, &hive);
+ if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
+ return reg_open_key(hive, name, result);
+ }
+ }
+
+ return error;
+}
+
/* 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
@@ -166,7 +185,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
return WERR_NOT_SUPPORTED;
}
- error = parent->handle->functions->open_key(parent->handle, fullname, result);
+ error = parent->handle->functions->open_key(parent->handle, parent->hive, fullname, result);
if(!W_ERROR_IS_OK(error)) {
talloc_destroy(mem_ctx);
@@ -175,6 +194,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result)
(*result)->handle = parent->handle;
(*result)->path = fullname;
+ (*result)->hive = parent->hive;
talloc_steal(mem_ctx, (*result)->mem_ctx, fullname);
talloc_destroy(mem_ctx);
@@ -285,6 +305,7 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey)
(*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
(*subkey)->handle = key->handle;
+ (*subkey)->hive = key->hive;
return WERR_OK;;
@@ -315,6 +336,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk
(*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name);
(*subkey)->handle = key->handle;
+ (*subkey)->hive = key->hive;
return WERR_OK;
}
@@ -427,6 +449,25 @@ WERROR reg_val_del(REG_VAL *val)
return WERR_OK;
}
+WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name)
+{
+ REG_KEY *hive;
+ WERROR error;
+ int i, hivelength;
+
+ if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
+ else hivelength = strlen(name);
+
+ for(i = 0; W_ERROR_IS_OK(error); i++) {
+ error = reg_get_hive(handle, i, &hive);
+ if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) {
+ return reg_key_add_name_recursive(hive, name);
+ }
+ }
+
+ return error;
+}
+
WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path)
{
REG_KEY *cur, *prevcur = parent;
@@ -516,21 +557,26 @@ void reg_free(REG_HANDLE *h)
h->functions->close_registry(h);
}
-WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key)
+WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key)
{
WERROR ret;
- if(h->functions->open_root_key) {
- ret = h->functions->open_root_key(h, key);
+
+ if(h->functions->get_hive) {
+ ret = h->functions->get_hive(h, hivenum, key);
} else if(h->functions->open_key) {
- ret = h->functions->open_key(h, "\\", key);
+ if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key);
+ else ret = WERR_NO_MORE_ITEMS;
} else {
- DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name));
+ DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name));
ret = WERR_NOT_SUPPORTED;
}
if(W_ERROR_IS_OK(ret)) {
(*key)->handle = h;
- (*key)->path = talloc_strdup((*key)->mem_ctx, "\\");
+ if(!(*key)->path) {
+ (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name);
+ }
+ (*key)->hive = hivenum;
}
return ret;
@@ -565,7 +611,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent)
REG_KEY *root;
WERROR error;
- error = reg_get_root(key->handle, &root);
+ error = reg_get_hive(key->handle, key->hive, &root);
if(!W_ERROR_IS_OK(error)) return error;
parent_name = strdup(reg_key_get_path(key));
diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c
index 787ec52127..7a92f413ff 100644
--- a/source4/lib/registry/common/reg_objects.c
+++ b/source4/lib/registry/common/reg_objects.c
@@ -141,6 +141,12 @@ char *reg_val_get_path(REG_VAL *v)
const char *reg_key_get_path(REG_KEY *k)
{
SMB_REG_ASSERT(k);
+ return strchr(k->path, '\\')?strchr(k->path, '\\')+1:k->path;
+}
+
+const char *reg_key_get_path_abs(REG_KEY *k)
+{
+ SMB_REG_ASSERT(k);
return k->path;
}
@@ -168,6 +174,7 @@ REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data)
r = talloc(mem_ctx, sizeof(REG_KEY));
ZERO_STRUCTP(r);
r->handle = k->handle;
+ r->hive = k->hive;
r->name = talloc_strdup(mem_ctx, name);
r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name);
diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h
index 208bcae1e1..d4e8cccade 100644
--- a/source4/lib/registry/common/registry.h
+++ b/source4/lib/registry/common/registry.h
@@ -40,6 +40,7 @@ struct reg_key_s {
int cache_values_count;
REG_KEY **cache_subkeys;
int cache_subkeys_count;
+ int hive;
TALLOC_CTX *mem_ctx;
int ref;
};
@@ -61,10 +62,14 @@ struct reg_val_s {
typedef void (*key_notification_function) (void);
typedef void (*value_notification_function) (void);
-
/*
* Container for function pointers to enumeration routines
* for virtual registry view
+ *
+ * Backends can provide :
+ * - just one hive (example: nt4, w95)
+ * - several hives (example: rpc)
+ *
*/
struct registry_ops {
@@ -73,17 +78,23 @@ struct registry_ops {
WERROR (*sync_key)(REG_KEY *, const char *location);
WERROR (*close_registry) (REG_HANDLE *);
+ /* Implement this one */
+ WERROR (*get_hive) (REG_HANDLE *, int , REG_KEY **);
+
+ /* Or this one */
+ WERROR (*open_key) (REG_HANDLE *, int hive, const char *name, REG_KEY **);
+
/* Either implement these */
- 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 **);
+ /* Can not contain more then one level */
WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **);
WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **);
+ /* Can not contain more then one level */
WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **);
/* Or these */
- 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 ***);
@@ -111,15 +122,8 @@ struct registry_ops {
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 {
struct registry_ops *functions;
- REG_SUBTREE *subtrees;
char *location;
char *credentials;
void *backend_data;
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 517324fdd2..cb61864d0c 100644
--- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
+++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
@@ -38,16 +38,22 @@ static WERROR reg_dir_del_key(REG_KEY *k)
return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE;
}
-static WERROR reg_dir_open_key(REG_HANDLE *h, const char *name, REG_KEY **subkey)
+static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **subkey)
{
DIR *d;
char *fullpath;
REG_KEY *ret;
- TALLOC_CTX *mem_ctx = talloc_init("tmp");
+ TALLOC_CTX *mem_ctx;
+
+ if(hive != 0) return WERR_NO_MORE_ITEMS;
+
if(!name) {
DEBUG(0, ("NULL pointer passed as directory name!"));
return WERR_INVALID_PARAM;
}
+
+
+ mem_ctx = talloc_init("tmp");
fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name);
fullpath = reg_path_win2unix(fullpath);
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 cb3c284811..255389624e 100644
--- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
+++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
@@ -1663,8 +1663,9 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char
return WERR_OK;
}
-static WERROR nt_get_root_key(REG_HANDLE *h, REG_KEY **key)
+static WERROR nt_get_root_key(REG_HANDLE *h, int hive, REG_KEY **key)
{
+ if(hive != 0) return WERR_NO_MORE_ITEMS;
return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key);
}
@@ -1737,7 +1738,7 @@ static struct registry_ops reg_backend_nt4 = {
.name = "nt4",
.open_registry = nt_open_registry,
.close_registry = nt_close_registry,
- .open_root_key = nt_get_root_key,
+ .get_hive = nt_get_root_key,
.num_subkeys = nt_num_subkeys,
.num_values = nt_num_values,
.get_subkey_by_index = nt_key_by_index,
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 74b25884d6..d863568c17 100644
--- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
@@ -22,9 +22,6 @@
/**
* This is the RPC backend for the registry library.
- *
- * This backend is a little special. The root key is 'virtual'. All
- * of its subkeys are the hives available on the remote server.
*/
static void init_winreg_String(struct winreg_String *name, const char *s)
@@ -40,11 +37,11 @@ static void init_winreg_String(struct winreg_String *name, const char *s)
}
-#define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \
+#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \
{ \
struct winreg_Open ## u r; \
struct winreg_OpenUnknown unknown; \
- struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
+ NTSTATUS status; \
\
unknown.unknown0 = 0x84e0; \
unknown.unknown1 = 0x0000; \
@@ -52,12 +49,13 @@ static void init_winreg_String(struct winreg_String *name, const char *s)
r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \
r.out.handle = hnd;\
\
- if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\
+ status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \
+ if (NT_STATUS_IS_ERR(status)) {\
DEBUG(0,("Error executing open\n"));\
- return NULL;\
+ return ntstatus_to_werror(status);\
}\
\
- return hnd;\
+ return r.out.result;\
}
openhive(HKLM)
@@ -66,11 +64,6 @@ openhive(HKPD)
openhive(HKU)
openhive(HKCR)
-struct rpc_data {
- struct dcerpc_pipe *pipe;
- struct policy_handle *hives[10];
-};
-
struct rpc_key_data {
struct policy_handle pol;
int num_subkeys;
@@ -81,7 +74,7 @@ struct rpc_key_data {
struct {
const char *name;
- struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
+ WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h);
} known_hives[] = {
{ "HKEY_LOCAL_MACHINE", open_HKLM },
{ "HKEY_CURRENT_USER", open_HKCU },
@@ -95,7 +88,6 @@ static WERROR rpc_query_key(REG_KEY *k);
static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials)
{
- struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data));
char *binding = strdup(location);
NTSTATUS status;
char *user, *pass;
@@ -106,40 +98,42 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char
pass = strchr(user, '%');
*pass = '\0'; pass++;
- ZERO_STRUCTP(mydata);
-
- status = dcerpc_pipe_connect(&mydata->pipe, binding,
+ status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding,
DCERPC_WINREG_UUID,
DCERPC_WINREG_VERSION,
lp_workgroup(),
user, pass);
-
- h->backend_data = mydata;
return ntstatus_to_werror(status);
}
-static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
+static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k)
{
- /* There's not really a 'root' key here */
- *k = reg_key_new_abs("\\", h, h->backend_data);
- return WERR_OK;
+ struct rpc_key_data *mykeydata;
+ WERROR error;
+ if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
+ *k = reg_key_new_abs(known_hives[n].name, h, NULL);
+ (*k)->backend_data = mykeydata = talloc_p((*k)->mem_ctx, struct rpc_key_data);
+ mykeydata->num_values = -1;
+ mykeydata->num_subkeys = -1;
+ error = known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &mykeydata->pol);
+ return error;
}
static WERROR rpc_close_registry(REG_HANDLE *h)
{
- dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
+ dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data);
return WERR_OK;
}
static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
{
- struct policy_handle *hive = NULL;
struct winreg_OpenKey r;
int i;
struct rpc_data *mydata = k->handle->backend_data;
+ WERROR error;
+ REG_KEY *hivekey;
struct rpc_key_data *mykeydata;
- char *realkeyname, *hivename;
if(k->backend_data) {
*data = k->backend_data;
@@ -151,57 +145,55 @@ static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
mykeydata->num_values = -1;
mykeydata->num_subkeys = -1;
- /* First, ensure the handle to the hive is opened */
- realkeyname = strchr(k->path+1, '\\');
- if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1);
- else hivename = strdup(k->path+1);
-
- for(i = 0; known_hives[i].name; i++) {
- if(!strcmp(hivename, known_hives[i].name)) {
- if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, k->handle);
- hive = mydata->hives[i];
- break;
- }
- }
-
- if(!hive) {
- DEBUG(0, ("No such hive: %s\n", hivename));
- return WERR_FOOBAR;
- }
-
- if(realkeyname && realkeyname[0] == '\\')realkeyname++;
-
- if(!realkeyname || !(*realkeyname)) {
- mykeydata->pol = *hive;
- return WERR_OK;
- }
-
/* Then, open the handle using the hive */
memset(&r, 0, sizeof(struct winreg_OpenKey));
- r.in.handle = hive;
- init_winreg_String(&r.in.keyname, realkeyname);
+ error = rpc_get_hive(k->handle, k->hive, &hivekey);
+ if(!W_ERROR_IS_OK(error))return error;
+ r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
+ init_winreg_String(&r.in.keyname, reg_key_get_path(k));
r.in.unknown = 0x00000000;
r.in.access_mask = 0x02000000;
r.out.handle = &mykeydata->pol;
- dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
+ dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
return r.out.result;
}
-static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
+static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key)
{
struct rpc_key_data *mykeydata;
+ struct winreg_OpenKey r;
+ REG_KEY *hivekey;
+ WERROR error;
+
*key = reg_key_new_abs(name, h, NULL);
- return rpc_key_put_rpc_data(*key, &mykeydata);
+
+ (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data);
+ mykeydata->num_values = -1;
+ mykeydata->num_subkeys = -1;
+
+ /* Then, open the handle using the hive */
+
+ memset(&r, 0, sizeof(struct winreg_OpenKey));
+ error = rpc_get_hive(h, hive, &hivekey);
+ if(!W_ERROR_IS_OK(error))return error;
+ r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol);
+ init_winreg_String(&r.in.keyname, name);
+ r.in.unknown = 0x00000000;
+ r.in.access_mask = 0x02000000;
+ r.out.handle = &mykeydata->pol;
+
+ dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r);
+
+ return r.out.result;
}
static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
{
struct winreg_EnumValue r;
struct winreg_Uint8buf vb;
- struct rpc_data *mydata = parent->handle->backend_data;
struct winreg_EnumValueName vn;
NTSTATUS status;
struct rpc_key_data *mykeydata;
@@ -211,11 +203,6 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
error = rpc_key_put_rpc_data(parent, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
- /* Root is a special case */
- if(parent->backend_data == parent->handle->backend_data) {
- return WERR_NO_MORE_ITEMS;
- }
-
if(mykeydata->num_values == -1) {
error = rpc_query_key(parent);
if(!W_ERROR_IS_OK(error)) return error;
@@ -244,7 +231,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value)
vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen);
r.in.value = r.out.value = &vb;
- status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
+ status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
if(NT_STATUS_IS_ERR(status)) {
DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
}
@@ -273,13 +260,6 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
WERROR error;
NTSTATUS status;
- /* If parent is the root key, list the hives */
- if(parent->backend_data == mydata) {
- if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
- *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL);
- return rpc_key_put_rpc_data(*subkey, &mykeydata);
- }
-
error = rpc_key_put_rpc_data(parent, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
@@ -295,7 +275,7 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
r.in.enum_index = n;
r.in.unknown = r.out.unknown = 0x0414;
r.in.key_name_len = r.out.key_name_len = 0;
- status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r);
+ status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r);
if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
*subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL);
}
@@ -306,7 +286,9 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key)
{
struct rpc_key_data *mykeydata;
- WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
+ WERROR error;
+
+ error = rpc_key_put_rpc_data(parent, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
/* FIXME */
@@ -318,16 +300,15 @@ static WERROR rpc_query_key(REG_KEY *k)
NTSTATUS status;
WERROR error;
struct winreg_QueryInfoKey r;
- struct rpc_data *mydata = k->handle->backend_data;
struct rpc_key_data *mykeydata;
- init_winreg_String(&r.in.class, NULL);
-
error = rpc_key_put_rpc_data(k, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
+
+ init_winreg_String(&r.in.class, NULL);
r.in.handle = &mykeydata->pol;
- status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
+ status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("QueryInfoKey failed - %s\n", nt_errstr(status));
@@ -347,22 +328,21 @@ static WERROR rpc_query_key(REG_KEY *k)
static WERROR rpc_del_key(REG_KEY *k)
{
NTSTATUS status;
- struct rpc_data *mydata = k->handle->backend_data;
- struct rpc_key_data *mykeydata;
+ struct rpc_key_data *mykeydata = k->backend_data;
struct winreg_DeleteKey r;
REG_KEY *parent;
WERROR error;
error = reg_key_get_parent(k, &parent);
if(!W_ERROR_IS_OK(error)) return error;
-
+
error = rpc_key_put_rpc_data(parent, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
-
+
r.in.handle = &mykeydata->pol;
init_winreg_String(&r.in.key, k->name);
- status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
+ status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r);
return r.out.result;
}
@@ -373,15 +353,9 @@ static void rpc_close_key(REG_KEY *k)
}
static WERROR rpc_num_values(REG_KEY *key, int *count) {
- struct rpc_key_data *mykeydata;
+ struct rpc_key_data *mykeydata = key->backend_data;
WERROR error;
- /* Root is a special case */
- if(key->backend_data == key->handle->backend_data) {
- *count = 0;
- return WERR_OK;
- }
-
error = rpc_key_put_rpc_data(key, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
@@ -395,20 +369,12 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) {
}
static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
- struct rpc_key_data *mykeydata;
+ struct rpc_key_data *mykeydata = key->backend_data;
WERROR error;
-
- /* Root is a special case */
- if(key->backend_data == key->handle->backend_data) {
- int i;
- for(i = 0; known_hives[i].name; i++);
- *count = i;
- return WERR_OK;
- }
-
+
error = rpc_key_put_rpc_data(key, &mykeydata);
if(!W_ERROR_IS_OK(error)) return error;
-
+
if(mykeydata->num_subkeys == -1) {
error = rpc_query_key(key);
if(!W_ERROR_IS_OK(error)) return error;
@@ -422,7 +388,7 @@ static struct registry_ops reg_backend_rpc = {
.name = "rpc",
.open_registry = rpc_open_registry,
.close_registry = rpc_close_registry,
- .open_root_key = rpc_open_root,
+ .get_hive = rpc_get_hive,
.open_key = rpc_open_key,
.get_subkey_by_index = rpc_get_subkey_by_index,
.get_value_by_index = rpc_get_value_by_index,
diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
index c5d2e24103..b014f4da66 100644
--- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
+++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
@@ -179,12 +179,14 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr)
}
}
-static WERROR w95_open_root (REG_HANDLE *h, REG_KEY **key)
+static WERROR w95_open_root (REG_HANDLE *h, int hive, REG_KEY **key)
{
CREG *creg = h->backend_data;
+
+ if(hive != 0) return WERR_NO_MORE_ITEMS;
/* First element in rgkn should be root key */
- *key = reg_key_new_abs("\\", h, LOCN_RGKN(creg, sizeof(RGKN_HDR)));
+ *key = reg_key_new_abs("", h, LOCN_RGKN(creg, sizeof(RGKN_HDR)));
return WERR_OK;
}
@@ -356,7 +358,7 @@ static struct registry_ops reg_backend_w95 = {
.name = "w95",
.open_registry = w95_open_reg,
.close_registry = w95_close_reg,
- .open_root_key = w95_open_root,
+ .get_hive = w95_open_root,
.fetch_values = w95_fetch_values,
.get_subkey_by_index = w95_get_subkey_by_index,
};
diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c
index 7b06b2266f..e8800c6ee9 100644
--- a/source4/lib/registry/tools/gregedit.c
+++ b/source4/lib/registry/tools/gregedit.c
@@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
- Gtk registry frontend
+ GTK+ registry frontend
Copyright (C) Jelmer Vernooij 2004
@@ -115,20 +115,25 @@ static void registry_load_root()
{
REG_KEY *root;
GtkTreeIter iter, tmpiter;
- WERROR error;
+ WERROR error = WERR_OK;
+ int i = 0;
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,
+ while(1) {
+ error = reg_get_hive(registry, i, &root);
+ if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
+ return;
+ }
+ if(!W_ERROR_IS_OK(error)) {
+ gtk_show_werror(error);
+ return;
+ }
+
+ /* Add the root */
+ gtk_tree_store_append(store_keys, &iter, NULL);
+ gtk_tree_store_set (store_keys,
&iter,
0,
reg_key_name(root),
@@ -136,7 +141,9 @@ static void registry_load_root()
root,
-1);
- gtk_tree_store_append(store_keys, &tmpiter, &iter);
+ gtk_tree_store_append(store_keys, &tmpiter, &iter);
+ i++;
+ }
gtk_widget_set_sensitive( save, True );
gtk_widget_set_sensitive( save_as, True );
diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c
index d9419208cd..7520e653bb 100644
--- a/source4/lib/registry/tools/regdiff.c
+++ b/source4/lib/registry/tools/regdiff.c
@@ -100,10 +100,11 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
const char *credentials1= NULL, *credentials2 = NULL;
char *outputfile = NULL;
FILE *fd = stdout;
- REG_HANDLE *h2;
+ REG_HANDLE *h1, *h2;
REG_KEY *root1 = NULL, *root2;
int from_null = 0;
- WERROR error;
+ int i;
+ WERROR error, error2;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL},
@@ -130,7 +131,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
setup_logging(argv[0], True);
if(!from_null) {
- REG_HANDLE *h1;
const char *location1;
location1 = poptGetArg(pc);
if(!location1) {
@@ -145,8 +145,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1);
return 1;
}
-
- if(!W_ERROR_IS_OK(reg_get_root(h1, &root1))) return 1;
}
location2 = poptGetArg(pc);
@@ -163,12 +161,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
return 1;
}
- error = reg_get_root(h2, &root2);
- if(!W_ERROR_IS_OK(error)) {
- fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2);
- return 1;
- }
-
poptFreeContext(pc);
if(outputfile) {
@@ -182,7 +174,23 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
fprintf(fd, "REGEDIT4\n\n");
fprintf(fd, "; Generated using regdiff\n");
- writediff(root1, root2, fd);
+ error2 = error = WERR_OK;
+
+ for(i = 0; ; i++) {
+ if(backend1) error = reg_get_hive(h1, i, &root1);
+ else root1 = NULL;
+
+ if(!W_ERROR_IS_OK(error)) break;
+
+ if(backend2) error2 = reg_get_hive(h2, i, &root2);
+ else root2 = NULL;
+
+ if(!W_ERROR_IS_OK(error2)) break;
+
+ writediff(root1, root2, fd);
+
+ if(!root1 && !root2) break;
+ }
fclose(fd);
diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c
index 64c2637a0c..77c0f710c1 100644
--- a/source4/lib/registry/tools/regpatch.c
+++ b/source4/lib/registry/tools/regpatch.c
@@ -664,7 +664,7 @@ static CMD_FILE *cmd_file_create(const char *file)
char *str_type(unsigned char type);
-static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
+static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name)
{
CMD *cmd;
BOOL modified = False;
@@ -680,12 +680,12 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
*/
switch (cmd->cmd) {
case CMD_ADD_KEY:
- error = reg_open_key(root, cmd->key, &tmp);
+ error = reg_open_key_abs(r, cmd->key, &tmp);
/* If we found it, apply the other bits, else create such a key */
if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
- if(W_ERROR_IS_OK(reg_key_add_name_recursive(root, cmd->key))) {
- error = reg_open_key(root, cmd->key, &tmp);
+ if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) {
+ error = reg_open_key_abs(r, cmd->key, &tmp);
if(!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key));
continue;
@@ -732,7 +732,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
* Find the key if it exists, and delete it ...
*/
- error = reg_open_key(root, cmd->key, &tmp);
+ error = reg_open_key_abs(r, cmd->key, &tmp);
if(!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Unable to open key '%s'\n", cmd->key));
continue;
@@ -756,7 +756,6 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
{
int opt;
poptContext pc;
- REG_KEY *root;
const char *location;
const char *credentials = NULL;
const char *patch;
@@ -793,13 +792,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name)
if(!patch) patch = "/dev/stdin";
poptFreeContext(pc);
- error = reg_get_root(h, &root);
- if(!W_ERROR_IS_OK(error)) {
- DEBUG(0, ("Error opening root!\n"));
- return 1;
- }
-
- nt_apply_reg_command_file(root, patch);
+ nt_apply_reg_command_file(h, patch);
reg_free(h);
diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c
index e8b01081e8..26312ad4bc 100644
--- a/source4/lib/registry/tools/regshell.c
+++ b/source4/lib/registry/tools/regshell.c
@@ -27,6 +27,7 @@
* rmval/rm - remove value
* rmkey/rmdir - remove key
* mkkey/mkdir - make key
+ * ch - change hive
* help
* exit
*/
@@ -227,7 +228,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
setup_logging("regtree", True);
- error = reg_get_root(h, &curkey);
+ error = reg_get_hive(h, 0, &curkey);
if(!W_ERROR_IS_OK(error)) return 1;
diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c
index 477c63af2c..e583194a56 100644
--- a/source4/lib/registry/tools/regtree.c
+++ b/source4/lib/registry/tools/regtree.c
@@ -60,7 +60,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals)
int main(int argc, char **argv)
{
- int opt;
+ int opt, i;
const char *backend = "dir";
const char *credentials = NULL;
poptContext pc;
@@ -91,10 +91,14 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals)
}
poptFreeContext(pc);
- error = reg_get_root(h, &root);
- if(!W_ERROR_IS_OK(error)) return 1;
+ error = WERR_OK;
- print_tree(0, root, fullpath, no_values);
+ for(i = 0; W_ERROR_IS_OK(error); i++) {
+ error = reg_get_hive(h, i, &root);
+ if(!W_ERROR_IS_OK(error)) return 1;
+
+ print_tree(0, root, fullpath, no_values);
+ }
return 0;
}