summaryrefslogtreecommitdiff
path: root/source4/lib/registry/reg_backend_rpc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/registry/reg_backend_rpc')
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c141
1 files changed, 116 insertions, 25 deletions
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)