summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/registry/common/reg_interface.c11
-rw-r--r--source4/lib/registry/common/reg_objects.c3
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c141
-rw-r--r--source4/lib/registry/tools/regtree.c2
4 files changed, 127 insertions, 30 deletions
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index 5753de1bca..fdbb7345d2 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -187,7 +187,12 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
{
if(!key) return WERR_INVALID_PARAM;
- if(!key->handle->functions->get_value_by_index) {
+ if(key->handle->functions->get_value_by_index) {
+ WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
+ if(!W_ERROR_IS_OK(status))
+ return status;
+
+ } else if(key->handle->functions->fetch_values) {
if(!key->cache_values)
key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values);
@@ -197,9 +202,7 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val)
return WERR_NO_MORE_ITEMS;
}
} else {
- WERROR status = key->handle->functions->get_value_by_index(key, idx, val);
- if(!W_ERROR_IS_OK(status))
- return status;
+ return WERR_NOT_SUPPORTED;
}
(*val)->parent = key;
diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c
index 3f721c107e..787ec52127 100644
--- a/source4/lib/registry/common/reg_objects.c
+++ b/source4/lib/registry/common/reg_objects.c
@@ -163,11 +163,14 @@ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data)
REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data)
{
REG_KEY *r;
+ const char *parent_path = k?reg_key_get_path(k):"";
TALLOC_CTX *mem_ctx = talloc_init(name);
r = talloc(mem_ctx, sizeof(REG_KEY));
ZERO_STRUCTP(r);
r->handle = k->handle;
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);
r->backend_data = data;
r->mem_ctx = mem_ctx;
r->ref = 1;
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 f17bdbb3f5..f5a7127ed6 100644
--- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
@@ -71,6 +71,12 @@ struct rpc_data {
struct policy_handle *hives[10];
};
+struct rpc_key_data {
+ struct policy_handle pol;
+ int num_subkeys;
+ int num_values;
+};
+
struct {
const char *name;
struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
@@ -119,21 +125,30 @@ static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k)
static WERROR rpc_close_registry(REG_HANDLE *h)
{
dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe);
- free(h->backend_data);
return WERR_OK;
}
-static WERROR rpc_key_put_policy_handle(REG_KEY *k)
+static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data)
{
- struct policy_handle *key_handle, *hive = NULL;
+ struct policy_handle *hive = NULL;
struct winreg_OpenKey r;
int i;
struct rpc_data *mydata = k->handle->backend_data;
+ struct rpc_key_data *mykeydata;
char *realkeyname, *hivename;
- if(k->backend_data) return WERR_OK;
+
+ if(k->backend_data) {
+ *data = k->backend_data;
+ return WERR_OK;
+ }
+
+ k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data);
+ *data = mykeydata;
+ mykeydata->num_values = -1;
+ mykeydata->num_subkeys = -1;
/* First, ensure the handle to the hive is opened */
- realkeyname = strchr(k->path, '\\');
+ realkeyname = strchr(k->path+1, '\\');
if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1);
else hivename = strdup(k->path+1);
@@ -150,15 +165,13 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k)
return WERR_FOOBAR;
}
- if(realkeyname[0] == '\\')realkeyname++;
+ if(realkeyname && realkeyname[0] == '\\')realkeyname++;
if(!realkeyname || !(*realkeyname)) {
- k->backend_data = hive;
+ mykeydata->pol = *hive;
return WERR_OK;
}
- key_handle = talloc(k->mem_ctx, sizeof(struct policy_handle));
-
/* Then, open the handle using the hive */
memset(&r, 0, sizeof(struct winreg_OpenKey));
@@ -166,20 +179,19 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k)
init_winreg_String(&r.in.keyname, realkeyname);
r.in.unknown = 0x00000000;
r.in.access_mask = 0x02000000;
- r.out.handle = key_handle;
+ r.out.handle = &mykeydata->pol;
dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r);
- if(W_ERROR_IS_OK(r.out.result)) k->backend_data = key_handle;
-
return r.out.result;
}
static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key)
{
WERROR error;
+ struct rpc_key_data *mykeydata;
*key = reg_key_new_abs(name, h, NULL);
- return rpc_key_put_policy_handle(*key);
+ return rpc_key_put_rpc_data(*key, &mykeydata);
}
static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
@@ -189,6 +201,8 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
struct winreg_String classname;
struct winreg_Time tm;
struct rpc_data *mydata = parent->handle->backend_data;
+ struct rpc_key_data *mykeydata = parent->backend_data;
+ WERROR error;
int i;
NTSTATUS status;
TALLOC_CTX *mem_ctx;
@@ -196,17 +210,14 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
/* 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, known_hives[n].open(mydata->pipe, parent->handle));
-
- return WERR_OK;
+ *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL);
+ return rpc_key_put_rpc_data(*subkey, &mykeydata);
}
- if(!parent->backend_data) {
- rpc_key_put_policy_handle(parent);
- }
+ error = rpc_key_put_rpc_data(parent, &mykeydata);
+ if(!W_ERROR_IS_OK(error)) return error;
- r.in.handle = parent->backend_data;
+ r.in.handle = &mykeydata->pol;
keyname.unknown = 0x0000020a;
init_winreg_String(&keyname.key_name, NULL);
init_winreg_String(&classname, NULL);
@@ -229,24 +240,56 @@ 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)
{
- rpc_key_put_policy_handle(parent);
+ struct rpc_key_data *mykeydata;
+ WERROR error = rpc_key_put_rpc_data(parent, &mykeydata);
+ if(!W_ERROR_IS_OK(error)) return error;
+
/* FIXME */
return WERR_NOT_SUPPORTED;
}
+static WERROR rpc_query_key(REG_KEY *k)
+{
+ NTSTATUS status;
+ struct winreg_QueryInfoKey r;
+ struct rpc_data *mydata = k->handle->backend_data;
+ struct rpc_key_data *mykeydata;
+ WERROR error = rpc_key_put_rpc_data(k, &mykeydata);
+
+ r.in.handle = &mykeydata->pol;
+ init_winreg_String(&r.in.class, NULL);
+
+ status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("QueryInfoKey failed - %s\n", nt_errstr(status));
+ return ntstatus_to_werror(status);
+ }
+
+ if (W_ERROR_IS_OK(r.out.result)) {
+ mykeydata->num_subkeys = r.out.num_subkeys;
+ mykeydata->num_values = r.out.num_values;
+ }
+ return r.out.result;
+}
static WERROR rpc_del_key(REG_KEY *k)
{
NTSTATUS status;
struct rpc_data *mydata = k->handle->backend_data;
+ struct rpc_key_data *mykeydata;
struct winreg_DeleteKey r;
REG_KEY *parent;
- WERROR error = reg_key_get_parent(k, &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;
- rpc_key_put_policy_handle(parent);
- r.in.handle = parent->backend_data;
+ r.in.handle = &mykeydata->pol;
init_winreg_String(&r.in.key, k->name);
status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
@@ -259,6 +302,52 @@ static void rpc_close_key(REG_KEY *k)
reg_key_free(k);
}
+static WERROR rpc_num_values(REG_KEY *key, int *count) {
+ struct rpc_key_data *mykeydata;
+ 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;
+
+ if(mykeydata->num_values == -1) {
+ WERROR error = rpc_query_key(key);
+ if(!W_ERROR_IS_OK(error)) return error;
+ }
+
+ *count = mykeydata->num_values;
+ return WERR_OK;
+}
+
+static WERROR rpc_num_subkeys(REG_KEY *key, int *count) {
+ struct rpc_key_data *mykeydata;
+ 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) {
+ WERROR error = rpc_query_key(key);
+ if(!W_ERROR_IS_OK(error)) return error;
+ }
+
+ *count = mykeydata->num_subkeys;
+ return WERR_OK;
+}
+
static struct registry_ops reg_backend_rpc = {
.name = "rpc",
.open_registry = rpc_open_registry,
@@ -269,6 +358,8 @@ static struct registry_ops reg_backend_rpc = {
.add_key = rpc_add_key,
.del_key = rpc_del_key,
.free_key_backend_data = rpc_close_key,
+ .num_subkeys = rpc_num_subkeys,
+ .num_values = rpc_num_values,
};
NTSTATUS reg_rpc_init(void)
diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c
index b8a5f50496..eb32b1e55e 100644
--- a/source4/lib/registry/tools/regtree.c
+++ b/source4/lib/registry/tools/regtree.c
@@ -38,7 +38,7 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals)
}
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
- DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p)));
+ DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path(p), win_errstr(error)));
}
if(!novals) {