summaryrefslogtreecommitdiff
path: root/source4/lib/registry
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/registry')
-rw-r--r--source4/lib/registry/common/reg_interface.c49
-rw-r--r--source4/lib/registry/common/registry.h4
-rw-r--r--source4/lib/registry/config.m41
-rw-r--r--source4/lib/registry/reg_backend_dir/reg_backend_dir.c15
-rw-r--r--source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c33
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c216
-rw-r--r--source4/lib/registry/reg_backend_w95/reg_backend_w95.c170
-rw-r--r--source4/lib/registry/tools/gregedit.c11
8 files changed, 307 insertions, 192 deletions
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index 5e6b4fbac8..917b03cf32 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -214,7 +214,11 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count)
{
if(!key) return WERR_INVALID_PARAM;
- if(!key->handle->functions->num_subkeys) {
+ if(key->handle->functions->num_subkeys) {
+ return key->handle->functions->num_subkeys(key, count);
+ }
+
+ if(key->handle->functions->fetch_subkeys) {
if(!key->cache_subkeys)
key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
@@ -222,7 +226,20 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count)
return WERR_OK;
}
- return key->handle->functions->num_subkeys(key, count);
+ if(key->handle->functions->get_subkey_by_index) {
+ int i;
+ WERROR error;
+ REG_KEY *dest;
+ for(i = 0; W_ERROR_IS_OK(error = key->handle->functions->get_subkey_by_index(key, i, &dest)); i++) {
+ reg_key_free(dest);
+ }
+
+ *count = i;
+ if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK;
+ return error;
+ }
+
+ return WERR_NOT_SUPPORTED;
}
WERROR reg_key_num_values(REG_KEY *key, int *count)
@@ -306,8 +323,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk
WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val)
{
- int i, max;
- REG_VAL *ret = NULL;
+ int i;
WERROR error = WERR_OK;
if(!key) return WERR_INVALID_PARAM;
@@ -361,7 +377,6 @@ WERROR reg_sync(REG_KEY *h, const char *location)
WERROR reg_key_del_recursive(REG_KEY *key)
{
- BOOL succeed = True;
WERROR error = WERR_OK;
int i;
@@ -543,3 +558,27 @@ WERROR reg_save(REG_HANDLE *h, const char *location)
/* FIXME */
return WERR_NOT_SUPPORTED;
}
+
+WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent)
+{
+ char *parent_name;
+ char *last;
+ REG_KEY *root;
+ WERROR error;
+
+ error = reg_get_root(key->handle, &root);
+ if(!W_ERROR_IS_OK(error)) return error;
+
+ parent_name = strdup(reg_key_get_path(key));
+ last = strrchr(parent_name, '\\');
+
+ if(!last) {
+ SAFE_FREE(parent_name);
+ return WERR_FOOBAR;
+ }
+ *last = '\0';
+
+ error = reg_open_key(root, parent_name, parent);
+ SAFE_FREE(parent_name);
+ return error;
+}
diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h
index 9d7e17cf56..208bcae1e1 100644
--- a/source4/lib/registry/common/registry.h
+++ b/source4/lib/registry/common/registry.h
@@ -58,8 +58,8 @@ struct reg_val_s {
};
/* FIXME */
-typedef void (*key_notification_function) ();
-typedef void (*value_notification_function) ();
+typedef void (*key_notification_function) (void);
+typedef void (*value_notification_function) (void);
/*
diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4
index c00b7cc507..d8acb26397 100644
--- a/source4/lib/registry/config.m4
+++ b/source4/lib/registry/config.m4
@@ -11,6 +11,7 @@ PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC)
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_w95, REG, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.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])
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 4daaf3d628..375daa319b 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 WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc)
+static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **result)
{
char *path;
int ret;
@@ -29,7 +29,7 @@ static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_m
path = reg_path_win2unix(path);
ret = mkdir(path, 0700);
SAFE_FREE(path);
- if(ret == 0)return WERR_OK;
+ if(ret == 0)return WERR_OK; /* FIXME */
return WERR_INVALID_PARAM;
}
@@ -83,7 +83,6 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
if(e->d_type == DT_DIR &&
strcmp(e->d_name, ".") &&
strcmp(e->d_name, "..")) {
- char *newfullpath;
ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL);
ar[(*count)]->backend_data = talloc_asprintf(ar[*count]->mem_ctx, "%s/%s", fullpath, e->d_name);
if(ar[(*count)])(*count)++;
@@ -106,16 +105,8 @@ static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentia
return WERR_OK;
}
-static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len, REG_VAL **value)
+static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len)
{
- char *fullpath;
- FILE *fd;
- *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 WERR_NOT_SUPPORTED;
}
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 a7e5051ce4..fd91b4fbe6 100644
--- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
+++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
@@ -165,7 +165,7 @@ Offset Size Contents
To determine the number of values, you have to look at the owner-nk-record!
-Der vk-Record
+The vk-Record
=============
Offset Size Contents
0x0000 Word ID: ASCII-"vk" = 0x6B76
@@ -473,7 +473,7 @@ typedef struct regf_struct_s {
int fd;
struct stat sbuf;
char *base;
- int modified;
+ BOOL modified;
NTTIME last_mod_time;
NK_HDR *first_key;
int sk_count, sk_map_size;
@@ -485,7 +485,6 @@ typedef struct regf_struct_s {
* keys when we are preparing to write them to a file
*/
HBIN_BLK *blk_head, *blk_tail, *free_space;
- TALLOC_CTX *mem_ctx;
} REGF;
DWORD str_to_dword(const char *a) {
@@ -886,7 +885,6 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val
char val_name[1024];
REGF *regf = parent->handle->backend_data;
int nam_len, dat_len, flag, dat_type, dat_off, vk_id;
- const char *val_type;
REG_VAL *tmp = NULL;
if (!vk_hdr) return WERR_INVALID_PARAM;
@@ -1021,7 +1019,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent
{
REGF *regf = h->backend_data;
REG_KEY *tmp = NULL, *own;
- int name_len, clsname_len, sk_off, own_off;
+ int namlen, clsname_len, sk_off, own_off;
unsigned int nk_id;
SK_HDR *sk_hdr;
int type;
@@ -1037,32 +1035,32 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent
SMB_REG_ASSERT(size < 0);
- name_len = SVAL(&nk_hdr->nam_len,0);
+ namlen = SVAL(&nk_hdr->nam_len,0);
clsname_len = SVAL(&nk_hdr->clsnam_len,0);
/*
* The value of -size should be ge
- * (sizeof(NK_HDR) - 1 + name_len)
+ * (sizeof(NK_HDR) - 1 + namlen)
* The -1 accounts for the fact that we included the first byte of
* the name in the structure. clsname_len is the length of the thing
* pointed to by clsnam_off
*/
- if (-size < (sizeof(NK_HDR) - 1 + name_len)) {
+ if (-size < (sizeof(NK_HDR) - 1 + namlen)) {
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));
+ sizeof(NK_HDR), namlen, clsname_len));
return WERR_GENERAL_FAILURE;
}
- DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", name_len, clsname_len));
+ DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", namlen, clsname_len));
/* Fish out the key name and process the LF list */
- SMB_REG_ASSERT(name_len < sizeof(key_name));
+ SMB_REG_ASSERT(namlen < sizeof(key_name));
- strncpy(key_name, nk_hdr->key_nam, name_len);
- key_name[name_len] = '\0';
+ strncpy(key_name, nk_hdr->key_nam, namlen);
+ key_name[namlen] = '\0';
type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY);
if(type == REG_ROOT_KEY && parent) {
@@ -1088,7 +1086,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent
clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off);
DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off));
- tmp->class_name = talloc_strdup_w(regf->mem_ctx, clsnamep);
+ tmp->class_name = talloc_strdup_w(h->mem_ctx, clsnamep);
DEBUGADD(2,(" Class Name: %s\n", cls_name));
@@ -1572,22 +1570,17 @@ static WERROR nt_close_registry (REG_HANDLE *h)
regf->base = NULL;
close(regf->fd); /* Ignore the error :-) */
- free(regf->sk_map);
- regf->sk_count = regf->sk_map_size = 0;
-
- free(regf);
return WERR_OK;
}
static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials)
{
- REGF *regf = (REGF *)malloc(sizeof(REGF));
+ REGF *regf = (REGF *)talloc_p(h->mem_ctx, REGF);
REGF_HDR *regf_hdr;
unsigned int regf_id, hbin_id;
HBIN_HDR *hbin_hdr;
memset(regf, 0, sizeof(REGF));
- regf->mem_ctx = talloc_init("regf");
regf->owner_sid_str = credentials;
h->backend_data = regf;
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 7c30302e84..f17bdbb3f5 100644
--- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
@@ -20,6 +20,13 @@
#include "includes.h"
#include "lib/registry/common/registry.h"
+/**
+ * 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)
{
name->name = s;
@@ -35,7 +42,6 @@ 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) \
{ \
- NTSTATUS status; \
struct winreg_Open ## u r; \
struct winreg_OpenUnknown unknown; \
struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \
@@ -66,7 +72,7 @@ struct rpc_data {
};
struct {
- char *name;
+ const char *name;
struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h);
} known_hives[] = {
{ "HKEY_LOCAL_MACHINE", open_HKLM },
@@ -98,7 +104,6 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char
lp_workgroup(),
user, pass);
-
h->backend_data = mydata;
return ntstatus_to_werror(status);
@@ -118,64 +123,66 @@ static WERROR rpc_close_registry(REG_HANDLE *h)
return WERR_OK;
}
-static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path)
+static WERROR rpc_key_put_policy_handle(REG_KEY *k)
{
- char *hivename;
- int i = 0;
- struct rpc_data *mydata = h->backend_data;
- struct policy_handle *hive = NULL;
- char *end = strchr(path+1, '\\');
- NTSTATUS status;
+ struct policy_handle *key_handle, *hive = NULL;
struct winreg_OpenKey r;
- struct policy_handle *key_handle = talloc(h->mem_ctx, sizeof(struct policy_handle));
- TALLOC_CTX *mem_ctx;
-
- if(end) hivename = strndup(path+1, end-path-1);
- else hivename = strdup(path+1);
+ int i;
+ struct rpc_data *mydata = k->handle->backend_data;
+ char *realkeyname, *hivename;
+ if(k->backend_data) return WERR_OK;
+
+ /* First, ensure the handle to the hive is opened */
+ realkeyname = strchr(k->path, '\\');
+ 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, h);
+ 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 NULL;
+ return WERR_FOOBAR;
}
- DEBUG(2, ("Opening %s, hive: %s\n", path, hivename));
+ if(realkeyname[0] == '\\')realkeyname++;
- if(!end || !(*end) || !(*(end+1))) return hive;
+ if(!realkeyname || !(*realkeyname)) {
+ k->backend_data = 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));
r.in.handle = hive;
- init_winreg_String(&r.in.keyname, end+1);
+ init_winreg_String(&r.in.keyname, realkeyname);
r.in.unknown = 0x00000000;
r.in.access_mask = 0x02000000;
r.out.handle = key_handle;
-
- mem_ctx = talloc_init("openkey");
- status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r);
- talloc_destroy(mem_ctx);
-
- if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
- return NULL;
- }
- return key_handle;
+ 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)
{
- 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;
+ WERROR error;
+ *key = reg_key_new_abs(name, h, NULL);
+ return rpc_key_put_policy_handle(*key);
}
-static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
+static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey)
{
struct winreg_EnumKey r;
struct winreg_EnumKeyNameRequest keyname;
@@ -183,28 +190,22 @@ static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
struct winreg_Time tm;
struct rpc_data *mydata = parent->handle->backend_data;
int i;
- REG_KEY **ar = talloc(parent->mem_ctx, sizeof(REG_KEY *));
- NTSTATUS status = NT_STATUS_OK;
+ NTSTATUS status;
TALLOC_CTX *mem_ctx;
- /* List the hives */
- if(parent->backend_data == parent->handle->backend_data) {
- for(i = 0; known_hives[i].name; i++) {
- ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL);
- (*count)++;
- ar = talloc_realloc(parent->mem_ctx, ar, sizeof(REG_KEY *) * ((*count)+1));
- }
+ /* If parent is the root key, list the hives */
+ if(parent->backend_data == mydata) {
+ if(!known_hives[n].name) return WERR_NO_MORE_ITEMS;
- *subkeys = ar;
+ *subkey = reg_key_new_rel(known_hives[n].name, parent, known_hives[n].open(mydata->pipe, parent->handle));
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 WERR_GENERAL_FAILURE;
+ if(!parent->backend_data) {
+ rpc_key_put_policy_handle(parent);
+ }
- (*count) = 0;
r.in.handle = parent->backend_data;
keyname.unknown = 0x0000020a;
init_winreg_String(&keyname.key_name, NULL);
@@ -215,134 +216,59 @@ static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
r.in.last_changed_time = &tm;
r.out.result.v = 0;
- for(i = 0; NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result); i++) {
- r.in.enum_index = i;
- 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);
- if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
- ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL);
- (*count)++;
- ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_KEY *));
- }
- }
-
- *subkeys = ar;
- return r.out.result;
-}
-
-static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
-{
- struct winreg_EnumValue r;
- struct winreg_Uint8buf value;
- struct winreg_String valuename;
- struct rpc_data *mydata = parent->handle->backend_data;
- TALLOC_CTX *mem_ctx;
- uint32 type, requested_len, returned_len;
- NTSTATUS status = NT_STATUS_OK;
- REG_VAL **ar = malloc(sizeof(REG_VAL *));
-
- (*count) = 0;
-
- /* Root */
- if(parent->backend_data == parent->handle->backend_data) {
- *values = ar;
- return WERR_OK;
+ 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);
+ 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);
}
-
- if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
-
- if(!parent->backend_data) return WERR_GENERAL_FAILURE;
-
- r.in.handle = parent->backend_data;
- r.in.enum_index = 0;
-
- init_winreg_String(&valuename, NULL);
- r.in.name = r.out.name = &valuename;
-
- type = 0;
- r.in.type = r.out.type = &type;
- value.max_len = 0x7fff;
- value.offset = 0;
- value.len = 0;
- value.buffer = NULL;
-
- r.in.value = r.out.value = &value;
-
- requested_len = value.max_len;
- r.in.requested_len = &requested_len;
- returned_len = 0;
- r.in.returned_len = &returned_len;
- r.out.result.v = 0;
-
- while(1) {
- status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r);
- if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
- r.in.enum_index++;
- ar[(*count)] = reg_val_new(parent, NULL);
- ar[(*count)]->name = talloc_strdup(ar[*count]->mem_ctx, r.out.name->name);
- ar[(*count)]->data_type = *r.out.type;
- ar[(*count)]->data_len = value.len;
- ar[(*count)]->data_blk = talloc(ar[*count]->mem_ctx, value.len);
- memcpy(ar[(*count)]->data_blk, value.buffer, value.len);
- (*count)++;
- ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_VAL *));
- } else break;
- }
-
- *values = ar;
return r.out.result;
}
-static WERROR rpc_add_key(REG_KEY *parent, const char *name)
+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);
/* FIXME */
return WERR_NOT_SUPPORTED;
}
-static struct policy_handle*get_hive(REG_KEY *k)
-{
- 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);
+ REG_KEY *parent;
+ WERROR error = reg_key_get_parent(k, &parent);
+ if(!W_ERROR_IS_OK(error)) return error;
+ rpc_key_put_policy_handle(parent);
- 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);
+ r.in.handle = parent->backend_data;
+ init_winreg_String(&r.in.key, k->name);
status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r);
return r.out.result;
}
+static void rpc_close_key(REG_KEY *k)
+{
+ reg_key_free(k);
+}
+
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,
.open_key = rpc_open_key,
- .fetch_subkeys = rpc_fetch_subkeys,
- .fetch_values = rpc_fetch_values,
+ .get_subkey_by_index = rpc_get_subkey_by_index,
.add_key = rpc_add_key,
.del_key = rpc_del_key,
+ .free_key_backend_data = rpc_close_key,
};
NTSTATUS reg_rpc_init(void)
diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
new file mode 100644
index 0000000000..79ebd54510
--- /dev/null
+++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
@@ -0,0 +1,170 @@
+/*
+ Samba Unix/Linux SMB client utility libeditreg.c
+ Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
+
+ Backend for Windows '95 registry files. Explanation of file format
+ comes from http://www.cs.mun.ca/~michael/regutils/.
+
+ 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"
+
+/**
+ * The registry starts with a header that contains pointers to
+ * the rgdb.
+ *
+ * After the main header follows the RGKN header (key index table) */
+
+typedef unsigned int DWORD;
+typedef unsigned short WORD;
+
+typedef struct regc_block {
+ DWORD REGC_ID; /* REGC */
+ DWORD uk1;
+ DWORD rgdb_offset;
+ DWORD chksum;
+ WORD num_rgdb;
+ WORD flags;
+ DWORD uk2;
+ DWORD uk3;
+ DWORD uk4;
+ DWORD uk5;
+} REGC_HDR;
+
+typedef struct rgkn_block {
+ DWORD RGKN_ID; /* RGKN */
+ DWORD size;
+ DWORD root_offset;
+ DWORD free_offset;
+ DWORD flags;
+ DWORD chksum;
+ DWORD uk1;
+ DWORD uk2;
+} RGKN_HDR;
+
+typedef struct rgkn_key {
+ DWORD inuse;
+ DWORD hash;
+ DWORD next_free;
+ DWORD parent;
+ DWORD child;
+ DWORD next;
+ WORD id;
+ WORD rgdb;
+} RGKN_KEY;
+
+typedef struct rgdb_block {
+ DWORD RGDB_ID; /* RGDB */
+ DWORD size;
+ DWORD unused_size;
+ WORD flags;
+ WORD section;
+ DWORD free_offset; /* -1 if there is no free space */
+ WORD max_id;
+ WORD first_free_id;
+ DWORD uk1;
+ DWORD chksum;
+} RGDB_HDR;
+
+typedef struct rgdb_key {
+ DWORD inuse;
+ DWORD hash;
+ DWORD next_free;
+ DWORD parent;
+ DWORD child;
+ DWORD next;
+ WORD id;
+ WORD rgdb;
+} RGDB_KEY;
+
+typedef struct rgdb_value {
+ DWORD type;
+ DWORD uk1;
+ DWORD name_len;
+ DWORD data_len;
+} RGDB_VALUE;
+
+typedef struct regc_struct_s {
+ int fd;
+ struct stat sbuf;
+ BOOL modified;
+ char *base;
+} REGC;
+
+static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials)
+{
+ REGC *regc = talloc_p(h->mem_ctx, REGC);
+ REGC_HDR *regc_hdr;
+ RGKN_HDR *rgkn_hdr;
+ DWORD regc_id, rgkn_id;
+ memset(regc, 0, sizeof(REGC));
+ h->backend_data = regc;
+
+ if((regc->fd = open(location, O_RDONLY, 0000)) < 0) {
+ return WERR_FOOBAR;
+ }
+
+ if(fstat(regc->fd, &regc->sbuf) < 0) {
+ return WERR_FOOBAR;
+ }
+
+ regc->base = mmap(0, regc->sbuf.st_size, PROT_READ, MAP_SHARED, regc->fd, 0);
+ regc_hdr = (REGC_HDR *)regc->base;
+
+ if ((int)regc->base == 1) {
+ return WERR_FOOBAR;
+ }
+
+ if ((regc_id = IVAL(&regc_hdr->REGC_ID,0)) != str_to_dword("REGC")) {
+ DEBUG(0, ("Unrecognized Windows 95 registry header id: %0X, %s\n",
+ regc_id, location));
+ return WERR_FOOBAR;
+ }
+
+ rgkn_hdr = (RGKN_HDR *)regc->base + sizeof(REGC_HDR);
+
+ if ((rgkn_id = IVAL(&rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) {
+ DEBUG(0, ("Unrecognized Windows 95 registry key index id: %0X, %s\n",
+ rgkn_id, location));
+ return WERR_FOOBAR;
+ }
+
+ //rgkn = (RGKN_KEY *)regc->base + sizeof(REGC_HDR) + sizeof(RGKN_HDR);
+
+ /* FIXME */
+
+ return WERR_OK;
+}
+
+static WERROR w95_close_reg(REG_HANDLE *h)
+{
+ REGC *regc = h->backend_data;
+ if (regc->base) munmap(regc->base, regc->sbuf.st_size);
+ regc->base = NULL;
+ close(regc->fd);
+ return WERR_OK;
+}
+
+static struct registry_ops reg_backend_w95 = {
+ .name = "w95",
+ .open_registry = w95_open_reg,
+ .close_registry = w95_close_reg,
+};
+
+NTSTATUS reg_w95_init(void)
+{
+ return register_backend("registry", &reg_backend_w95);
+}
diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c
index 51fad4287d..4fbb1b2705 100644
--- a/source4/lib/registry/tools/gregedit.c
+++ b/source4/lib/registry/tools/gregedit.c
@@ -84,6 +84,7 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *
g_assert(k);
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(k, i, &sub)); i++) {
+ int count;
/* 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
@@ -103,14 +104,8 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *
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_IS_OK(reg_key_num_subkeys(sub, &count)) && count > 0)
+ gtk_tree_store_append(store_keys, &tmpiter, &iter);
}
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error);