diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/registry/common/reg_interface.c | 49 | ||||
-rw-r--r-- | source4/lib/registry/common/registry.h | 4 | ||||
-rw-r--r-- | source4/lib/registry/config.m4 | 1 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_dir/reg_backend_dir.c | 15 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 33 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 216 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 170 | ||||
-rw-r--r-- | source4/lib/registry/tools/gregedit.c | 11 | ||||
-rw-r--r-- | source4/torture/rpc/winreg.c | 16 |
9 files changed, 317 insertions, 198 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, ®c->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(®c_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", ®_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); diff --git a/source4/torture/rpc/winreg.c b/source4/torture/rpc/winreg.c index 42326b1468..3864de6503 100644 --- a/source4/torture/rpc/winreg.c +++ b/source4/torture/rpc/winreg.c @@ -493,6 +493,11 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn) ret = False; } + if (!test_FlushKey(p, mem_ctx, &handle)) { + printf("FlushKey failed\n"); + ret = False; + } + if (!test_OpenKey(p, mem_ctx, &handle, "spottyfoot", &newhandle)) { printf("CreateKey failed (OpenKey after Create didn't work)\n"); ret = False; @@ -503,6 +508,11 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn) ret = False; } + if (!test_FlushKey(p, mem_ctx, &handle)) { + printf("FlushKey failed\n"); + ret = False; + } + if (test_OpenKey(p, mem_ctx, &handle, "spottyfoot", &newhandle)) { printf("DeleteKey failed (OpenKey after Delete didn't work)\n"); ret = False; @@ -513,12 +523,6 @@ static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn) ret = False; } - if (!test_FlushKey(p, mem_ctx, &handle)) { - printf("FlushKey failed\n"); - ret = False; - } - - /* The HKCR hive has a very large fanout */ if (open_fn == test_OpenHKCR) { |