From bf52e242f53aeaac33eea69fbdfb3477634b90fb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 22 May 2004 18:49:25 +0000 Subject: 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) --- source4/lib/registry/common/reg_interface.c | 62 +++++++- source4/lib/registry/common/reg_objects.c | 7 + source4/lib/registry/common/registry.h | 24 +-- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 10 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 5 +- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 168 ++++++++------------- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 8 +- source4/lib/registry/tools/gregedit.c | 31 ++-- source4/lib/registry/tools/regdiff.c | 32 ++-- source4/lib/registry/tools/regpatch.c | 19 +-- source4/lib/registry/tools/regshell.c | 3 +- source4/lib/registry/tools/regtree.c | 12 +- 12 files changed, 213 insertions(+), 168 deletions(-) (limited to 'source4') 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 @@ -139,6 +139,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; } -- cgit