diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2004-09-22 12:32:31 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:59:01 -0500 |
commit | 369a5d64e462e084e6c5fe4984d56da18b2c92d9 (patch) | |
tree | 815e7a10696ef40205c1e16c4e01b660a7a8f0b7 /source4 | |
parent | bc8ef3d1b6bfdf279d65783869b9a247c1da38aa (diff) | |
download | samba-369a5d64e462e084e6c5fe4984d56da18b2c92d9.tar.gz samba-369a5d64e462e084e6c5fe4984d56da18b2c92d9.tar.bz2 samba-369a5d64e462e084e6c5fe4984d56da18b2c92d9.zip |
r2518: Some long overdue changes:
- Samba4-style code in lib/registry (struct registry_key instead of REG_KEY, etc)
- Use hives (like Windows has drives) instead of one root key (like a Unix FS)
- usability fixes in the GTK utilities (autodetect the username,
enable/disable options, etc)
- fix gwsam compile
- several bugfixes in the registry rpc code
- do charset conversion in nt4 registry backend
(This used to be commit 2762ed3b9bf1d67dd54d63e02cddbfd71ea89892)
Diffstat (limited to 'source4')
23 files changed, 1011 insertions, 1326 deletions
diff --git a/source4/gtk/common/gtk-smb.c b/source4/gtk/common/gtk-smb.c index cc7013edc7..2348661cb7 100644 --- a/source4/gtk/common/gtk-smb.c +++ b/source4/gtk/common/gtk-smb.c @@ -55,6 +55,11 @@ static void on_browse_activate (GtkButton *button, gpointer user_d gtk_widget_destroy(GTK_WIDGET(shd)); } +static void on_krb5_toggled(GtkToggleButton *togglebutton, GtkRpcBindingDialog *d) +{ + gtk_widget_set_sensitive(d->entry_password, !gtk_toggle_button_get_active(togglebutton)); +} + static void gtk_rpc_binding_dialog_init (GtkRpcBindingDialog *gtk_rpc_binding_dialog) { GtkWidget *dialog_vbox1; @@ -75,7 +80,6 @@ static void gtk_rpc_binding_dialog_init (GtkRpcBindingDialog *gtk_rpc_binding_di GtkWidget *lbl_password; GtkWidget *btn_browse; GtkWidget *label9; - GtkWidget *chk_button; GtkWidget *lbl_credentials; GtkWidget *dialog_action_area1; GtkWidget *btn_cancel; @@ -138,7 +142,7 @@ static void gtk_rpc_binding_dialog_init (GtkRpcBindingDialog *gtk_rpc_binding_di gtk_widget_show (btn_browse); gtk_box_pack_start (GTK_BOX (hbox1), btn_browse, TRUE, TRUE, 0); - g_signal_connect ((gpointer) btn_browse, "pressed", + g_signal_connect ((gpointer) btn_browse, "pressed", G_CALLBACK (on_browse_activate), gtk_rpc_binding_dialog); @@ -208,12 +212,23 @@ static void gtk_rpc_binding_dialog_init (GtkRpcBindingDialog *gtk_rpc_binding_di (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); - chk_button = gtk_check_button_new_with_mnemonic ("_Use kerberos"); - gtk_widget_show (chk_button); - gtk_table_attach (GTK_TABLE (table1), chk_button, 1, 2, 2, 3, + gtk_entry_set_text(GTK_ENTRY(gtk_rpc_binding_dialog->entry_username), getenv("LOGNAME")); + + gtk_rpc_binding_dialog->krb5_chk_button = gtk_check_button_new_with_mnemonic ("_Use kerberos"); + gtk_widget_show (gtk_rpc_binding_dialog->krb5_chk_button); + gtk_table_attach (GTK_TABLE (table1), gtk_rpc_binding_dialog->krb5_chk_button, 1, 2, 2, 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + g_signal_connect ((gpointer) gtk_rpc_binding_dialog->krb5_chk_button, "toggled", + G_CALLBACK (on_krb5_toggled), + gtk_rpc_binding_dialog); + + /* Poor man's autodetection */ + if(getenv("KRB5CCNAME")) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gtk_rpc_binding_dialog->krb5_chk_button), TRUE); + } + lbl_credentials = gtk_label_new ("Credentials"); gtk_widget_show (lbl_credentials); gtk_frame_set_label_widget (GTK_FRAME (frame_credentials), lbl_credentials); @@ -278,6 +293,11 @@ const char *gtk_rpc_binding_dialog_get_password(GtkRpcBindingDialog *d) return gtk_entry_get_text(GTK_ENTRY(d->entry_password)); } +const char *gtk_rpc_binding_dialog_get_host(GtkRpcBindingDialog *d) +{ + return gtk_entry_get_text(GTK_ENTRY(d->entry_host)); +} + const char *gtk_rpc_binding_dialog_get_binding(GtkRpcBindingDialog *d, char *pipe_name) { const char *transport; diff --git a/source4/gtk/common/gtk-smb.h b/source4/gtk/common/gtk-smb.h index e9b62d94da..0f34bb3249 100644 --- a/source4/gtk/common/gtk-smb.h +++ b/source4/gtk/common/gtk-smb.h @@ -38,6 +38,7 @@ struct _GtkRpcBindingDialog GtkWidget *entry_host; GtkWidget *entry_username; GtkWidget *entry_password; + GtkWidget *krb5_chk_button; TALLOC_CTX *mem_ctx; }; diff --git a/source4/gtk/config.m4 b/source4/gtk/config.m4 index 05e7377860..757ce59c07 100644 --- a/source4/gtk/config.m4 +++ b/source4/gtk/config.m4 @@ -10,8 +10,7 @@ if test t$SMB_EXT_LIB_ENABLE_gtk = tYES; then SMB_SUBSYSTEM_ENABLE(GTKSMB, YES) SMB_BINARY_ENABLE(gregedit, YES) SMB_BINARY_ENABLE(gwcrontab, YES) - # this break the build on my SuSE 9.1 --metze - #SMB_BINARY_ENABLE(gwsam, YES) + SMB_BINARY_ENABLE(gwsam, YES) AC_DEFINE(HAVE_GTK, 1, [Whether GTK+ is available]) fi diff --git a/source4/gtk/tools/gregedit.c b/source4/gtk/tools/gregedit.c index 3297399b67..8938e634fa 100644 --- a/source4/gtk/tools/gregedit.c +++ b/source4/gtk/tools/gregedit.c @@ -28,17 +28,18 @@ GtkTreeStore *store_keys; GtkListStore *store_vals; GtkWidget *tree_keys; GtkWidget *mainwin; +TALLOC_CTX *mem_ctx; /* FIXME: Split up */ GtkWidget *save; GtkWidget *save_as; static GtkWidget* create_openfilewin (void); static GtkWidget* create_savefilewin (void); -REG_HANDLE *registry = NULL; +struct registry_context *registry = NULL; static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2) { GtkTreeIter firstiter, iter, tmpiter; - REG_KEY *k, *sub; + struct registry_key *k, *sub; char *name; WERROR error; int i; @@ -55,7 +56,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++) { + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, 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 @@ -70,7 +71,7 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * gtk_tree_store_set (store_keys, &iter, 0, - reg_key_name(sub), + sub->name, 1, sub, -1); @@ -84,36 +85,28 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * static void registry_load_root() { - REG_KEY *root; + struct registry_key *root; GtkTreeIter iter, tmpiter; - WERROR error = WERR_OK; int i = 0; if(!registry) return; gtk_tree_store_clear(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(mainwin, error); - return; - } + for(i = 0; i < registry->num_hives; i++) + { + root = registry->hives[i]->root; /* Add the root */ gtk_tree_store_append(store_keys, &iter, NULL); gtk_tree_store_set (store_keys, &iter, 0, - reg_key_name(root), + root->hive->name, 1, root, -1); gtk_tree_store_append(store_keys, &tmpiter, &iter); - i++; } gtk_widget_set_sensitive( save, True ); @@ -123,16 +116,20 @@ static void registry_load_root() static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) { gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); - char *filename; + char *filename, *tmp; WERROR error; switch(result) { case GTK_RESPONSE_OK: filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin))); - error = reg_open(user_data, filename, NULL, ®istry); + error = reg_open(®istry, user_data, filename, NULL); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); break; } + + tmp = g_strdup_printf("Registry Editor - %s", filename); + gtk_window_set_title (GTK_WINDOW (mainwin), tmp); + g_free(tmp); registry_load_root(); break; default: @@ -145,12 +142,14 @@ static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) static void on_open_gconf_activate (GtkMenuItem *menuitem, gpointer user_data) { - WERROR error = reg_open("gconf", NULL, NULL, ®istry); + WERROR error = reg_open(®istry, "gconf", NULL, NULL); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); return; } + gtk_window_set_title (GTK_WINDOW (mainwin), "Registry Editor - GConf"); + registry_load_root(); } @@ -158,31 +157,41 @@ static void on_open_remote_activate(GtkMenuItem *menuitem, gpointer user_data) { char *credentials; const char *location; + char *tmp; GtkWidget *rpcwin = GTK_WIDGET(gtk_rpc_binding_dialog_new(TRUE)); gint result = gtk_dialog_run(GTK_DIALOG(rpcwin)); WERROR error; - switch(result) { - case GTK_RESPONSE_ACCEPT: - location = gtk_rpc_binding_dialog_get_binding(GTK_RPC_BINDING_DIALOG(rpcwin), NULL); - asprintf(&credentials, "%s%%%s", gtk_rpc_binding_dialog_get_username(GTK_RPC_BINDING_DIALOG(rpcwin)), gtk_rpc_binding_dialog_get_password(GTK_RPC_BINDING_DIALOG(rpcwin))); - error = reg_open("rpc", location, credentials, ®istry); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(mainwin, error); - break; - } - free(credentials); - registry_load_root(); - break; - default: - break; + + if(result != GTK_RESPONSE_ACCEPT) + { + gtk_widget_destroy(rpcwin); + return; + } + + location = gtk_rpc_binding_dialog_get_binding(GTK_RPC_BINDING_DIALOG(rpcwin), NULL); + asprintf(&credentials, "%s%%%s", gtk_rpc_binding_dialog_get_username(GTK_RPC_BINDING_DIALOG(rpcwin)), gtk_rpc_binding_dialog_get_password(GTK_RPC_BINDING_DIALOG(rpcwin))); + error = reg_open(®istry, "rpc", location, credentials); + + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(mainwin, error); + gtk_widget_destroy(rpcwin); + return; } + free(credentials); + + tmp = g_strdup_printf("Registry Editor - Remote Registry at %s", gtk_rpc_binding_dialog_get_host(GTK_RPC_BINDING_DIALOG(rpcwin))); + gtk_window_set_title (GTK_WINDOW (mainwin), tmp); + g_free(tmp); + + registry_load_root(); + gtk_widget_destroy(rpcwin); } static void on_save_activate (GtkMenuItem *menuitem, - gpointer user_data) + gpointer user_data) { WERROR error = reg_save(registry, NULL); if(!W_ERROR_IS_OK(error)) { @@ -264,8 +273,8 @@ gboolean on_key_activate(GtkTreeSelection *selection, gpointer data) { int i; - REG_KEY *k; - REG_VAL *val; + struct registry_key *k; + struct registry_value *val; WERROR error; GtkTreeIter parent; if(path_currently_selected)return TRUE; @@ -277,17 +286,17 @@ gboolean on_key_activate(GtkTreeSelection *selection, gtk_list_store_clear(store_vals); - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(k, i, &val)); i++) { + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, k, i, &val)); i++) { GtkTreeIter iter; gtk_list_store_append(store_vals, &iter); gtk_list_store_set (store_vals, &iter, 0, - reg_val_name(val), + val->name, 1, - str_regtype(reg_val_type(val)), + str_regtype(val->data_type), 2, - reg_val_data_string(val), + reg_val_data_string(mem_ctx, val), 3, val, -1); @@ -607,6 +616,7 @@ static GtkWidget* create_savefilewin (void) load_interfaces(); gtk_init (&argc, &argv); + mem_ctx = talloc_init("gregedit"); pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); @@ -623,7 +633,7 @@ static GtkWidget* create_savefilewin (void) else backend = "nt4"; } - error = reg_open(backend, location, credentials, ®istry); + error = reg_open(®istry, backend, location, credentials); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); return -1; @@ -638,6 +648,7 @@ static GtkWidget* create_savefilewin (void) gtk_main (); - if(registry)reg_free(registry); + if(registry)talloc_destroy(registry->mem_ctx); + talloc_destroy(mem_ctx); return 0; } diff --git a/source4/gtk/tools/gwsam.c b/source4/gtk/tools/gwsam.c index 31bbf002de..2f0a8e300c 100644 --- a/source4/gtk/tools/gwsam.c +++ b/source4/gtk/tools/gwsam.c @@ -39,13 +39,12 @@ void update_userlist(void) struct samr_EnumDomainUsers r; uint32_t resume_handle=0; int i; - BOOL ret = True; TALLOC_CTX *mem_ctx; if(!sam_pipe) return; mem_ctx = talloc_init("update_userlist"); - r.in.handle = &domain_handle; + r.in.domain_handle = &domain_handle; r.in.resume_handle = &resume_handle; r.in.acct_flags = 0; r.in.max_size = (uint32_t)-1; @@ -87,7 +86,7 @@ on_select_domain_activate (GtkMenuItem *menuitem, { GtkSelectDomainDialog *d; gint result; - d = gtk_select_domain_dialog_new(sam_pipe); + d = GTK_SELECT_DOMAIN_DIALOG(gtk_select_domain_dialog_new(sam_pipe)); result = gtk_dialog_run(GTK_DIALOG(d)); switch(result) { case GTK_RESPONSE_ACCEPT: @@ -129,7 +128,7 @@ void on_connect_activate (GtkMenuItem *menuitem, gpointer user_data) r.in.system_name = 0; r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; - r.out.handle = &sam_handle; + r.out.connect_handle = &sam_handle; mem_ctx = talloc_init("connect"); status = dcerpc_samr_Connect(sam_pipe, mem_ctx, &r); @@ -218,13 +217,7 @@ create_mainwindow (void) GtkWidget *new1; GtkWidget *separatormenuitem1; GtkWidget *quit; - GtkWidget *menuitem2; GtkWidget *seldomain; - GtkWidget *menuitem2_menu; - GtkWidget *cut1; - GtkWidget *copy1; - GtkWidget *paste1; - GtkWidget *delete1; GtkWidget *policies; GtkWidget *policies_menu; GtkWidget *account; @@ -260,23 +253,20 @@ create_mainwindow (void) gtk_widget_show (menubar); gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, FALSE, 0); - menuitem1 = gtk_menu_item_new_with_mnemonic ("_User"); + menuitem1 = gtk_menu_item_new_with_mnemonic ("_File"); gtk_widget_show (menuitem1); gtk_container_add (GTK_CONTAINER (menubar), menuitem1); menuitem1_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu); - new1 = gtk_image_menu_item_new_from_stock ("gtk-new", accel_group); - gtk_widget_show (new1); - gtk_container_add (GTK_CONTAINER (menuitem1_menu), new1); - connect = gtk_menu_item_new_with_mnemonic ("_Connect"); gtk_widget_show (connect); gtk_container_add (GTK_CONTAINER (menuitem1_menu), connect); seldomain = gtk_menu_item_new_with_mnemonic("_Select Domain"); gtk_widget_show(seldomain); + gtk_widget_set_sensitive (seldomain, FALSE); gtk_container_add (GTK_CONTAINER (menuitem1_menu), seldomain); separatormenuitem1 = gtk_separator_menu_item_new (); @@ -288,9 +278,24 @@ create_mainwindow (void) gtk_widget_show (quit); gtk_container_add (GTK_CONTAINER (menuitem1_menu), quit); + menuitem1 = gtk_menu_item_new_with_mnemonic ("_User"); + gtk_widget_show (menuitem1); + gtk_container_add (GTK_CONTAINER (menubar), menuitem1); + gtk_widget_set_sensitive (menuitem1, FALSE); + + menuitem1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu); + + new1 = gtk_image_menu_item_new_from_stock ("gtk-new", accel_group); + gtk_widget_show (new1); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), new1); + + + policies = gtk_menu_item_new_with_mnemonic ("_Policies"); gtk_widget_show (policies); gtk_container_add (GTK_CONTAINER (menubar), policies); + gtk_widget_set_sensitive (policies, FALSE); policies_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (policies), policies_menu); @@ -326,6 +331,7 @@ create_mainwindow (void) refresh = gtk_image_menu_item_new_from_stock ("gtk-refresh", accel_group); gtk_widget_show (refresh); gtk_container_add (GTK_CONTAINER (menuitem3_menu), refresh); + gtk_widget_set_sensitive (refresh, FALSE); menuitem4 = gtk_menu_item_new_with_mnemonic ("_Help"); gtk_widget_show (menuitem4); diff --git a/source4/include/registry.h b/source4/include/registry.h index 162bb5e283..3aea70ecc1 100644 --- a/source4/include/registry.h +++ b/source4/include/registry.h @@ -43,11 +43,6 @@ #define REG_FULL_RESOURCE_DESCRIPTOR 9 #define REG_RESOURCE_REQUIREMENTS_LIST 10 -typedef struct reg_handle_s REG_HANDLE; -typedef struct reg_key_s REG_KEY; -typedef struct reg_val_s REG_VAL; -typedef struct reg_ops_s REG_OPS; - #if 0 /* FIXME */ typedef struct ace_struct_s { @@ -57,4 +52,117 @@ typedef struct ace_struct_s { } ACE; #endif +/* + * The general idea here is that every backend provides a 'hive'. Combining + * various hives gives you a complete registry like windows has + */ + +#define REGISTRY_INTERFACE_VERSION 1 + +/* structure to store the registry handles */ +struct registry_key { + char *name; /* Name of the key */ + char *path; /* Full path to the key */ + char *class_name; /* Name of key class */ + NTTIME last_mod; /* Time last modified */ + SEC_DESC *security; + struct registry_hive *hive; + void *backend_data; + int ref; +}; + +struct registry_value { + char *name; + int data_type; + int data_len; + void *data_blk; /* Might want a separate block */ + struct registry_hive *hive; + struct registry_key *parent; + void *backend_data; + int ref; +}; + +/* FIXME */ +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_operations { + const char *name; + + /* If one file, connection, etc may have more then one hive */ + WERROR (*list_available_hives) (TALLOC_CTX *, const char *location, const char *credentials, char ***hives); + + /* Implement this one */ + WERROR (*open_hive) (TALLOC_CTX *, struct registry_hive *, struct registry_key **); + + /* Or this one */ + WERROR (*open_key) (TALLOC_CTX *, struct registry_hive *, const char *name, struct registry_key **); + + /* Either implement these */ + WERROR (*num_subkeys) (struct registry_key *, int *count); + WERROR (*num_values) (struct registry_key *, int *count); + WERROR (*get_subkey_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_key **); + + /* Can not contain more then one level */ + WERROR (*get_subkey_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); + WERROR (*get_value_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_value **); + + /* Can not contain more then one level */ + WERROR (*get_value_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_value **); + + /* Security control */ + WERROR (*key_get_sec_desc) (TALLOC_CTX *, struct registry_key *, SEC_DESC **); + WERROR (*key_set_sec_desc) (struct registry_key *, SEC_DESC *); + + /* Notification */ + WERROR (*request_key_change_notify) (struct registry_key *, key_notification_function); + WERROR (*request_value_change_notify) (struct registry_value *, value_notification_function); + + /* Key management */ + WERROR (*add_key)(TALLOC_CTX *, struct registry_key *, const char *name, uint32_t access_mask, SEC_DESC *, struct registry_key **); + WERROR (*del_key)(struct registry_key *); + + /* Value management */ + WERROR (*set_value)(struct registry_key *, const char *name, int type, void *data, int len); + WERROR (*del_value)(struct registry_value *); +}; + +struct registry_hive { + const struct registry_operations *functions; + char *name; /* usually something like HKEY_CURRENT_USER, etc */ + char *location; + char *credentials; + char *backend_hivename; + void *backend_data; + struct registry_key *root; + struct registry_context *reg_ctx; +}; + +/* Handle to a full registry + * contains zero or more hives */ +struct registry_context { + TALLOC_CTX *mem_ctx; + int num_hives; + struct registry_hive **hives; +}; + +struct reg_init_function_entry { + /* Function to create a member of the pdb_methods list */ + const struct registry_operations *functions; + struct reg_init_function_entry *prev, *next; +}; + +/* Used internally */ +#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} + #endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 695f786b69..1dea9d2650 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -1,4 +1,3 @@ -- support subtrees - ..\..\, \bla\blie support in regshell - finish rpc_server diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f0a6807558..ec6188be71 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY @@ -29,10 +28,12 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); +#define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)) + /* Register new backend */ NTSTATUS registry_register(const void *_function) { - const struct registry_ops *functions = _function; + const struct registry_operations *functions = _function; struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { @@ -91,90 +92,157 @@ BOOL reg_has_backend(const char *backend) return reg_find_backend_entry(backend) != NULL?True:False; } -/* Open a registry file/host/etc */ -WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h) +WERROR reg_create(struct registry_context **_ret) +{ + TALLOC_CTX *mem_ctx; + struct registry_context *ret; + mem_ctx = talloc_init("registry handle"); + ret = talloc(mem_ctx, sizeof(struct registry_context)); + ret->mem_ctx = mem_ctx; + ZERO_STRUCTP(ret); + *_ret = ret; + return WERR_OK; +} + +WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives) { struct reg_init_function_entry *entry; + + entry = reg_find_backend_entry(backend); + + if (!entry) { + DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); + return WERR_GENERAL_FAILURE; + } + + if(!entry->functions->list_available_hives) { + return WERR_NOT_SUPPORTED; + } + + return entry->functions->list_available_hives(mem_ctx, location, credentials, hives); +} + +WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) +{ + WERROR error = reg_create(ret); + char **hives; + int i; + TALLOC_CTX *mem_ctx = talloc_init("reg_open"); + + if(!W_ERROR_IS_OK(error)) return error; + + error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives); + + if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) { + return reg_import_hive(*ret, backend, location, credentials, NULL); + } + + if(!W_ERROR_IS_OK(error)) return error; + + for(i = 0; hives[i]; i++) + { + error = reg_import_hive(*ret, backend, location, credentials, hives[i]); + if(!W_ERROR_IS_OK(error)) return error; + (*ret)->hives[i]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); + } + + return WERR_OK; +} + +/* Open a registry file/host/etc */ +WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) +{ + struct registry_hive *ret; TALLOC_CTX *mem_ctx; - REG_HANDLE *ret; + struct reg_init_function_entry *entry; WERROR werr; - + entry = reg_find_backend_entry(backend); if (!entry) { DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); return WERR_GENERAL_FAILURE; } + + if(!entry->functions->open_hive) { + return WERR_NOT_SUPPORTED; + } - mem_ctx = talloc_init(backend); - ret = talloc(mem_ctx, sizeof(REG_HANDLE)); - ZERO_STRUCTP(ret); + + mem_ctx = h->mem_ctx; + ret = talloc_p(mem_ctx, struct registry_hive); ret->location = location?talloc_strdup(mem_ctx, location):NULL; + ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL; ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; ret->functions = entry->functions; ret->backend_data = NULL; - ret->mem_ctx = mem_ctx; - *h = ret; + ret->reg_ctx = h; - if(!entry->functions->open_registry) { - return WERR_OK; - } + werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); + + if(!W_ERROR_IS_OK(werr)) return werr; - werr = entry->functions->open_registry(ret, location, credentials); + if(!ret->root) return WERR_GENERAL_FAILURE; - if(W_ERROR_IS_OK(werr)) - return WERR_OK; + ret->root->hive = ret; + ret->root->name = NULL; + ret->root->path = ""; - talloc_destroy(mem_ctx); - return werr; + /* Add hive to context */ + h->num_hives++; + h->hives = talloc_realloc_p(h->hives, struct registry_hive *, h->num_hives); + h->hives[h->num_hives-1] = ret; + + return WERR_OK; } /* Open a key by name (including the hive name!) */ -WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result) +WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; 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); - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); + + if(!W_ERROR_IS_OK(error)) { + return error; } - return error; + return reg_open_key(mem_ctx, hive, name, result); } /* 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 */ -WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) +WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result) { char *fullname; WERROR error; - TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); return WERR_INVALID_PARAM; } - if(!parent->handle->functions->open_key && - (parent->handle->functions->get_subkey_by_name || - parent->handle->functions->get_subkey_by_index)) { + if(!parent->hive->functions->open_key && + (parent->hive->functions->get_subkey_by_name || + parent->hive->functions->get_subkey_by_index)) { char *orig = strdup(name), *curbegin = orig, *curend = strchr(orig, '\\'); - REG_KEY *curkey = parent; + struct registry_key *curkey = parent; while(curbegin && *curbegin) { if(curend)*curend = '\0'; - error = reg_key_get_subkey_by_name(curkey, curbegin, result); + error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey); if(!W_ERROR_IS_OK(error)) { SAFE_FREE(orig); return error; @@ -184,94 +252,63 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) curend = strchr(curbegin, '\\'); } SAFE_FREE(orig); - + *result = curkey; + return WERR_OK; } - if(!parent->handle->functions->open_key) { + if(!parent->hive->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); return WERR_NOT_SUPPORTED; } - mem_ctx = talloc_init("mem_ctx"); + fullname = reg_make_path(mem_ctx, parent, name); - fullname = talloc_asprintf(mem_ctx, "%s%s%s", - reg_key_get_path(parent), - strlen(reg_key_get_path(parent))?"\\":"", - name); + error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); - error = parent->handle->functions->open_key(parent->handle, - parent->hive, fullname, result); - - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } + if(!W_ERROR_IS_OK(error)) return error; - (*result)->handle = parent->handle; - (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; - talloc_steal((*result)->mem_ctx, fullname); - - talloc_destroy(mem_ctx); + (*result)->path = fullname; + (*result)->hive = parent->hive; return WERR_OK; } -WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) +WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_index) { - WERROR status = key->handle->functions->get_value_by_index(key, idx, val); + if(key->hive->functions->get_value_by_index) { + WERROR status = key->hive->functions->get_value_by_index(mem_ctx, 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); - - if(idx < key->cache_values_count && idx >= 0) { - *val = reg_val_dup(key->cache_values[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_num_subkeys(REG_KEY *key, int *count) +WERROR reg_key_num_subkeys(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->num_subkeys) { - return key->handle->functions->num_subkeys(key, count); + if(key->hive->functions->num_subkeys) { + return key->hive->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); - - *count = key->cache_subkeys_count; - return WERR_OK; - } - - if(key->handle->functions->get_subkey_by_index) { + if(key->hive->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); - } + struct registry_key *dest; + TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); + + for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++); + talloc_destroy(mem_ctx); *count = i; if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK; @@ -281,74 +318,49 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_num_values(REG_KEY *key, int *count) +WERROR reg_key_num_values(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->num_values) { - if(!key->handle->functions->fetch_values) { - DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - if(!key->cache_values) - key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); - - *count = key->cache_values_count; - return WERR_OK; - } - - - return key->handle->functions->num_values(key, count); + return key->hive->functions->num_values(key, count); } -WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_index) { - WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); + if(key->hive->functions->get_subkey_by_index) { + WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey); if(!NT_STATUS_IS_OK(status)) return status; - } else if(key->handle->functions->fetch_subkeys) { - if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, - &key->cache_subkeys_count, &key->cache_subkeys); - - if(idx < key->cache_subkeys_count) { - *subkey = reg_key_dup(key->cache_subkeys[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; - (*subkey)->hive = key->hive; - + if(key->hive->root == key) + (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name); + else + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); + (*subkey)->hive = key->hive; return WERR_OK;; } -WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_name) { - error = key->handle->functions->get_subkey_by_name(key,name,subkey); - } else if(key->handle->functions->get_subkey_by_index || key->handle->functions->fetch_subkeys) { + if(key->hive->functions->get_subkey_by_name) { + error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); + } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_subkey_by_index(key, i, subkey); + error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { return error; } - reg_key_free(*subkey); } } else { return WERR_NOT_SUPPORTED; @@ -356,29 +368,27 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk if(!W_ERROR_IS_OK(error)) return error; - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); (*subkey)->hive = key->hive; return WERR_OK; } -WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) +WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_name) { - error = key->handle->functions->get_value_by_name(key,name, val); + if(key->hive->functions->get_value_by_name) { + error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val); } else { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_value_by_index(key, i, val); + error = reg_key_get_value_by_index(mem_ctx, key, i, val); if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) { break; } - reg_val_free(*val); } } @@ -386,52 +396,49 @@ WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) return error; (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_del(REG_KEY *key) +WERROR reg_key_del(struct registry_key *key) { WERROR error; if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->del_key) + if(!key->hive->functions->del_key) return WERR_NOT_SUPPORTED; - error = key->handle->functions->del_key(key); + error = key->hive->functions->del_key(key); if(!W_ERROR_IS_OK(error)) return error; - /* Invalidate cache */ - key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_sync(REG_KEY *h, const char *location) -{ - if(!h->handle->functions->sync_key) - return WERR_OK; - - return h->handle->functions->sync_key(h, location); -} - -WERROR reg_key_del_recursive(REG_KEY *key) +WERROR reg_key_del_recursive(struct registry_key *key) { WERROR error = WERR_OK; int i; + + TALLOC_CTX *mem_ctx = talloc_init("del_recursive"); /* Delete all values for specified key */ for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_VAL *val; - error = reg_key_get_value_by_index(key, i, &val); + struct registry_value *val; + error = reg_key_get_value_by_index(mem_ctx, key, i, &val); if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + { + talloc_destroy(mem_ctx); return error; + } if(W_ERROR_IS_OK(error)) { - error = reg_val_del(val); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_del_value(val); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } } } @@ -439,204 +446,150 @@ WERROR reg_key_del_recursive(REG_KEY *key) /* Delete all keys below this one */ for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_KEY *subkey; + struct registry_key *subkey; - error = reg_key_get_subkey_by_index(key, i, &subkey); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey); + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } error = reg_key_del_recursive(subkey); - if(!W_ERROR_IS_OK(error)) return error; + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } } + talloc_destroy(mem_ctx); return reg_key_del(key); } -WERROR reg_val_del(REG_VAL *val) -{ - WERROR error; - if (!val) return WERR_INVALID_PARAM; - - if (!val->handle->functions->del_value) { - DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - error = val->handle->functions->del_value(val); - - if(!W_ERROR_IS_OK(error)) return error; - - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - - return WERR_OK; -} - -WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name) +WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; 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); - } - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); - return error; + if(!W_ERROR_IS_OK(error)) return error; + + return reg_key_add_name_recursive(hive, name); } -WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) +WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) { - REG_KEY *cur, *prevcur = parent; - WERROR error; - /* FIXME: we should never write to a 'const char *' !!! --metze */ - char *begin = (char *)path, *end; + struct registry_key *cur, *prevcur = parent; + WERROR error = WERR_OK; + char *dup, *begin, *end; + TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); + + begin = dup = strdup(path); while(1) { end = strchr(begin, '\\'); if(end) *end = '\0'; - error = reg_key_get_subkey_by_name(prevcur, begin, &cur); + error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur); /* Key is not there, add it */ if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - error = reg_key_add_name(prevcur, begin, 0, NULL, &cur); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur); + if(!W_ERROR_IS_OK(error)) break; } if(!W_ERROR_IS_OK(error)) { if(end) *end = '\\'; - return error; + break; } - if(!end) break; + if(!end) { + error = WERR_OK; + break; + } + *end = '\\'; begin = end+1; prevcur = cur; } - return WERR_OK; + SAFE_FREE(dup); + talloc_destroy(mem_ctx); + return error; } -WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **newkey) +WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey) { WERROR error; if (!parent) return WERR_INVALID_PARAM; - if (!parent->handle->functions->add_key) { - DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); + if (!parent->hive->functions->add_key) { + DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name)); return WERR_NOT_SUPPORTED; } - error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey); + error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey); if(!W_ERROR_IS_OK(error)) return error; - (*newkey)->handle = parent->handle; - (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name); + (*newkey)->hive = parent->hive; + (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name); - parent->cache_subkeys = NULL; - parent->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_val_update(REG_VAL *val, int type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len) { - WERROR error; - - /* A 'real' update function has preference */ - if (val->handle->functions->update_value) - return val->handle->functions->update_value(val, type, data, len); - - /* Otherwise, just remove and add again */ - if (val->handle->functions->add_value && - val->handle->functions->del_value) { - REG_VAL *new; - if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) - return error; - - error = val->handle->functions->add_value(val->parent, val->name, type, data, len); - if(!W_ERROR_IS_OK(error)) return error; - memcpy(val, new, sizeof(REG_VAL)); - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - return WERR_OK; - } - - DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; -} - -void reg_free(REG_HANDLE *h) -{ - if(!h->functions->close_registry) return; + /* A 'real' set function has preference */ + if (key->hive->functions->set_value) + return key->hive->functions->set_value(key, value, type, data, len); - h->functions->close_registry(h); + DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name)); + return WERR_NOT_SUPPORTED; } -WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key) +WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) { - WERROR ret; - - if(h->functions->get_hive) { - ret = h->functions->get_hive(h, hivenum, key); - } else if(h->functions->open_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 or get_hive method implemented\n", h->functions->name)); - ret = WERR_NOT_SUPPORTED; - } - - if(W_ERROR_IS_OK(ret)) { - (*key)->handle = h; - if(!(*key)->path) { - (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name); + int i; + for(i = 0; i < h->num_hives; i++) + { + if(!strcmp(h->hives[i]->name, name)) { + *key = h->hives[i]->root; + return WERR_OK; } - (*key)->hive = hivenum; } - return ret; + return WERR_NO_MORE_ITEMS; } -WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +WERROR reg_del_value(struct registry_value *val) { WERROR ret = WERR_OK; - if(!key->handle->functions->add_value) + if(!val->hive->functions->del_value) return WERR_NOT_SUPPORTED; - ret = key->handle->functions->add_value(key, name, type, value, vallen); + ret = val->hive->functions->del_value(val); if(!W_ERROR_IS_OK(ret)) return ret; - /* Invalidate the cache */ - key->cache_values = NULL; - key->cache_values_count = 0; return ret; } -WERROR reg_save(REG_HANDLE *h, const char *location) +WERROR reg_save(struct registry_context *h, const char *location) { /* FIXME */ return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) +WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent) { char *parent_name; char *last; - REG_KEY *root; + struct registry_key *root; WERROR error; - 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)); + parent_name = strdup(key->path); last = strrchr(parent_name, '\\'); if(!last) { @@ -645,7 +598,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) } *last = '\0'; - error = reg_open_key(root, parent_name, parent); + error = reg_open_key(mem_ctx, root, parent_name, parent); SAFE_FREE(parent_name); return error; } diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c deleted file mode 100644 index d911b4650b..0000000000 --- a/source4/lib/registry/common/reg_objects.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Gerald Carter 2002. - * Copyright (C) Jelmer Vernooij 2003-2004. - * - * 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. - */ - -/* Implementation of registry frontend view functions. */ - -#include "includes.h" -#include "lib/registry/common/registry.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -/*********************************************************************** - allocate memory for and duplicate a REG_VAL. - This is malloc'd memory so the caller should free it when done - **********************************************************************/ - -REG_VAL* reg_val_dup( REG_VAL *val ) -{ - val->ref++; - return val; -} - -/********************************************************************** - free the memory allocated to a REG_VAL - *********************************************************************/ - -void reg_val_free( REG_VAL *val ) -{ - if ( !val ) - return; - - val->ref--; - if(val->ref) return; - - if(val->handle->functions->free_val_backend_data) - val->handle->functions->free_val_backend_data(val); - - talloc_destroy( val->mem_ctx ); - - return; -} - -/********************************************************************** - *********************************************************************/ - -uint8_t * reg_val_data_blk( REG_VAL *val ) -{ - return val->data_blk; -} - -/********************************************************************** - *********************************************************************/ - -int reg_val_size( REG_VAL *val ) -{ - return val->data_len; -} - -/********************************************************************** - *********************************************************************/ - -char *reg_val_name( REG_VAL *val ) -{ - return val->name; -} - -/********************************************************************** - *********************************************************************/ - -uint32_t reg_val_type( REG_VAL *val ) -{ - return val->data_type; -} - -/********************************************************************** - *********************************************************************/ - -REG_HANDLE *reg_key_handle (REG_KEY *key) -{ - return key->handle; -} - -char *reg_key_name( REG_KEY *key ) -{ - return key->name; -} - -char *reg_key_class( REG_KEY *key ) -{ - return key->class_name; -} - -NTTIME reg_key_last_modified( REG_KEY *key ) -{ - return key->last_mod; -} - -REG_KEY *reg_key_dup(REG_KEY *key) -{ - key->ref++; - return key; -} - -void reg_key_free(REG_KEY *key) -{ - if(!key) - return; - - key->ref--; - if(key->ref) return; - - if(key->handle->functions->free_key_backend_data) - key->handle->functions->free_key_backend_data(key); - - if(key->cache_values) { - int i; - for(i = 0; i < key->cache_values_count; i++) { - reg_val_free(key->cache_values[i]); - } - } - - if(key->cache_subkeys) { - int i; - for(i = 0; i < key->cache_subkeys_count; i++) { - reg_key_free(key->cache_subkeys[i]); - } - } - - talloc_destroy(key->mem_ctx); -} - -char *reg_val_get_path(REG_VAL *v) -{ - /* FIXME */ - return NULL; -} - -const char *reg_key_get_path(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return strchr(k->path, '\\')?strchr(k->path, '\\')+1:""; -} - -const char *reg_key_get_path_abs(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return k->path; -} - -/* For use by the backends _ONLY_ */ -REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) -{ - REG_KEY *r; - TALLOC_CTX *mem_ctx = talloc_init(path); - r = talloc(mem_ctx, sizeof(REG_KEY)); - ZERO_STRUCTP(r); - r->handle = h; - r->mem_ctx = mem_ctx; - r->path = talloc_strdup(mem_ctx, path); - r->name = talloc_strdup(mem_ctx, strrchr(path, '\\')?strrchr(path,'\\')+1:path); - r->backend_data = data; - r->ref = 1; - return r; -} - -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->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); - r->backend_data = data; - r->mem_ctx = mem_ctx; - r->ref = 1; - return r; -} - -REG_VAL *reg_val_new(REG_KEY *parent, void *data) -{ - REG_VAL *r; - TALLOC_CTX *mem_ctx = talloc_init("value"); - r = talloc(mem_ctx, sizeof(REG_VAL)); - ZERO_STRUCTP(r); - r->mem_ctx = mem_ctx; - r->handle = parent->handle; - r->backend_data = data; - r->ref = 1; - return r; -} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index db5e97bf7f..21c925deab 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -34,90 +34,68 @@ const char *str_regtype(int type) return "Unknown"; } -char *reg_val_data_string(REG_VAL *v) +char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) { char *asciip; char *ret = NULL; int i; - if(reg_val_size(v) == 0) return strdup(""); + if(v->data_len == 0) return talloc_strdup(mem_ctx, ""); - switch (reg_val_type(v)) { + switch (v->data_type) { case REG_SZ: - /* FIXME: Convert to ascii */ - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_EXPAND_SZ: - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_BINARY: - ret = malloc(reg_val_size(v) * 3 + 2); + ret = talloc(mem_ctx, v->data_len * 3 + 2); asciip = ret; - for (i=0; i<reg_val_size(v); i++) { - int str_rem = reg_val_size(v) * 3 - (asciip - ret); - asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(reg_val_data_blk(v)+i)); - if (i < reg_val_size(v) && str_rem > 0) + for (i=0; i<v->data_len; i++) { + int str_rem = v->data_len * 3 - (asciip - ret); + asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(v->data_blk+i)); + if (i < v->data_len && str_rem > 0) *asciip = ' '; asciip++; } *asciip = '\0'; return ret; - break; case REG_DWORD: - if (*(int *)reg_val_data_blk(v) == 0) - ret = strdup("0"); - else - asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v)); - break; + if (*(int *)v->data_blk == 0) + return talloc_strdup(mem_ctx, "0"); + + return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data_blk); case REG_MULTI_SZ: /* FIXME */ break; default: - return 0; break; } return ret; } -char *reg_val_description(REG_VAL *val) +char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) { - char *ret, *ds = reg_val_data_string(val); - asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"<No Name>", str_regtype(reg_val_type(val)), ds); - free(ds); - return ret; + return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); } -BOOL reg_val_set_string(REG_VAL *val, char *str) +BOOL reg_val_set_string(struct registry_value *val, char *str) { /* FIXME */ return False; } -WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname, REG_VAL **val) +WERROR reg_key_get_subkey_val(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *subname, const char *valname, struct registry_value **val) { - REG_KEY *k; - WERROR error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_get_value_by_name(k, valname, val); -} - -WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8_t *data, int real_len) -{ - REG_KEY *k; - REG_VAL *v; - WERROR error; - - error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - error = reg_key_get_value_by_name(k, valname, &v); + struct registry_key *k; + WERROR error = reg_key_get_subkey_by_name(mem_ctx, key, subname, &k); if(!W_ERROR_IS_OK(error)) return error; - return reg_val_update(v, type, data, real_len); + return reg_key_get_value_by_name(mem_ctx, k, valname, val); } /*********************************************************************** diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h deleted file mode 100644 index 89d0ac6b14..0000000000 --- a/source4/lib/registry/common/registry.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - This file contains the _internal_ structs for the registry - subsystem. Backends and the subsystem itself are the only - files that need to include this file. - Copyright (C) Gerald Carter 2002. - Copyright (C) Jelmer Vernooij 2003-2004. - - 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. -*/ - -#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */ -#define _REGISTRY_REGISTRY_H - -#define REGISTRY_INTERFACE_VERSION 1 - -/* structure to store the registry handles */ -struct reg_key_s { - char *name; /* Name of the key */ - char *path; /* Full path to the key */ - char *class_name; /* Name of key class */ - NTTIME last_mod; /* Time last modified */ - SEC_DESC *security; - REG_HANDLE *handle; - void *backend_data; - REG_VAL **cache_values; - int cache_values_count; - REG_KEY **cache_subkeys; - int cache_subkeys_count; - int hive; - TALLOC_CTX *mem_ctx; - int ref; -}; - -struct reg_val_s { - char *name; - int has_name; - int data_type; - int data_len; - void *data_blk; /* Might want a separate block */ - REG_HANDLE *handle; - REG_KEY *parent; - void *backend_data; - TALLOC_CTX *mem_ctx; - int ref; -}; - -/* FIXME */ -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 { - const char *name; - WERROR (*open_registry) (REG_HANDLE *, const char *location, const char *credentials); - 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 (*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 (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); - WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); - - /* Security control */ - WERROR (*key_get_sec_desc) (REG_KEY *, SEC_DESC **); - WERROR (*key_set_sec_desc) (REG_KEY *, SEC_DESC *); - - /* Notification */ - WERROR (*request_key_change_notify) (REG_KEY *, key_notification_function); - WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function); - - /* Key management */ - WERROR (*add_key)(REG_KEY *, const char *name, uint32_t access_mask, SEC_DESC *, REG_KEY **); - WERROR (*del_key)(REG_KEY *); - - /* Value management */ - WERROR (*add_value)(REG_KEY *, const char *name, int type, void *data, int len); - WERROR (*del_value)(REG_VAL *); - - /* If update is not available, value will first be deleted and then added - * again */ - WERROR (*update_value)(REG_VAL *, int type, void *data, int len); - - void (*free_key_backend_data) (REG_KEY *); - void (*free_val_backend_data) (REG_VAL *); -}; - -struct reg_handle_s { - const struct registry_ops *functions; - char *location; - char *credentials; - void *backend_data; - TALLOC_CTX *mem_ctx; -}; - -struct reg_init_function_entry { - /* Function to create a member of the pdb_methods list */ - const struct registry_ops *functions; - struct reg_init_function_entry *prev, *next; -}; - -/* Used internally */ -#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} - -#endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 8100c798e6..659e705d5d 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -60,7 +60,6 @@ REQUIRED_SUBSYSTEMS = \ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ - lib/registry/common/reg_objects.o \ lib/registry/common/reg_util.o REQUIRED_SUBSYSTEMS = \ LIBBASIC 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 b2bd34bf71..95d4c47af0 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -19,13 +19,12 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" -static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **result) +static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) { char *path; int ret; - asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name); + asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name); path = reg_path_win2unix(path); ret = mkdir(path, 0700); SAFE_FREE(path); @@ -33,19 +32,16 @@ static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32_t access return WERR_INVALID_PARAM; } -static WERROR reg_dir_del_key(REG_KEY *k) +static WERROR reg_dir_del_key(struct registry_key *k) { return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; } -static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **subkey) +static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **subkey) { DIR *d; char *fullpath; - REG_KEY *ret; - TALLOC_CTX *mem_ctx; - - if(hive != 0) return WERR_NO_MORE_ITEMS; + struct registry_key *ret; if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); @@ -53,33 +49,28 @@ static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KE } - mem_ctx = talloc_init("tmp"); fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); d = opendir(fullpath); if(!d) { DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); - talloc_destroy(mem_ctx); return WERR_BADFILE; } closedir(d); - ret = reg_key_new_abs(name, h, fullpath); - talloc_steal(ret->mem_ctx, fullpath); - talloc_destroy(mem_ctx); + ret = talloc_p(mem_ctx, struct registry_key); + ret->hive = h; + ret->path = fullpath; *subkey = ret; return WERR_OK; } -static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) +static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **key) { struct dirent *e; - int max = 200; char *fullpath = k->backend_data; - REG_KEY **ar; + int i = 0; DIR *d; - (*count) = 0; - ar = talloc(k->mem_ctx, sizeof(REG_KEY *) * max); d = opendir(fullpath); @@ -96,13 +87,15 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) stat(thispath, &stbuf); if(S_ISDIR(stbuf.st_mode)) { - ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); - ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, thispath); - if(ar[(*count)])(*count)++; - - if((*count) == max) { - max+=200; - ar = realloc(ar, sizeof(REG_KEY *) * max); + i++; + if(i == idx) { + (*key) = talloc_p(mem_ctx, struct registry_key); + (*key)->name = e->d_name; + (*key)->path = NULL; + (*key)->backend_data = talloc_strdup(mem_ctx, thispath); + SAFE_FREE(thispath); + closedir(d); + return WERR_OK; } } @@ -112,44 +105,38 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) closedir(d); - *r = ar; - return WERR_OK; + return WERR_NO_MORE_ITEMS; } -static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentials) { - if(!loc) return WERR_INVALID_PARAM; +static WERROR reg_dir_open(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) +{ + if(!h->location) return WERR_INVALID_PARAM; + + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->backend_data = talloc_strdup(mem_ctx, h->location); return WERR_OK; } -static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) +static WERROR reg_dir_set_value(struct registry_key *p, const char *name, int type, void *data, int len) { /* FIXME */ return WERR_NOT_SUPPORTED; } -static WERROR reg_dir_get_hive(REG_HANDLE *h, int hive, REG_KEY **key) -{ - if(hive != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - (*key)->backend_data = talloc_strdup((*key)->mem_ctx, h->location); - return WERR_OK; -} - -static WERROR reg_dir_del_value(REG_VAL *v) +static WERROR reg_dir_del_value(struct registry_value *v) { /* FIXME*/ return WERR_NOT_SUPPORTED; } -static struct registry_ops reg_backend_dir = { +static struct registry_operations reg_backend_dir = { .name = "dir", - .open_registry = reg_dir_open, + .open_hive = reg_dir_open, .open_key = reg_dir_open_key, - .get_hive = reg_dir_get_hive, - .fetch_subkeys = reg_dir_fetch_subkeys, .add_key = reg_dir_add_key, .del_key = reg_dir_del_key, - .add_value = reg_dir_add_value, + .get_subkey_by_index = reg_dir_key_by_index, + .set_value = reg_dir_set_value, .del_value = reg_dir_del_value, }; diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 15a8319711..d8c8d951c1 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" #include <gconf/gconf-client.h> static WERROR gerror_to_werror(GError *error) @@ -29,33 +28,24 @@ static WERROR gerror_to_werror(GError *error) return WERR_FOOBAR; } -static WERROR reg_open_gconf(REG_HANDLE *h, const char *location, const char *credentials) +static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { + g_type_init(); h->backend_data = (void *)gconf_client_get_default(); if(!h->backend_data) return WERR_FOOBAR; + + *k = talloc_p(mem_ctx, struct registry_key); + (*k)->name = ""; + (*k)->path = ""; + (*k)->backend_data = talloc_strdup(mem_ctx, "/"); return WERR_OK; } -static WERROR reg_close_gconf(REG_HANDLE *h) -{ - return WERR_OK; -} - -static WERROR gconf_get_hive (REG_HANDLE *h, int hivenum, REG_KEY **key) -{ - if(hivenum != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - (*key)->backend_data = talloc_strdup((*key)->mem_ctx, "/"); - return WERR_OK; -} - -static WERROR gconf_open_key (REG_HANDLE *h, int hivenum, const char *name, REG_KEY **key) +static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { - REG_KEY *ret; + struct registry_key *ret; char *fullpath; - if(hivenum != 0) return WERR_NO_MORE_ITEMS; - fullpath = reg_path_win2unix(strdup(name)); /* Check if key exists */ @@ -63,143 +53,134 @@ static WERROR gconf_open_key (REG_HANDLE *h, int hivenum, const char *name, REG_ SAFE_FREE(fullpath); return WERR_DEST_NOT_FOUND; } - ret = reg_key_new_abs(name, h, NULL); - ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath); + + ret = talloc_p(mem_ctx, struct registry_key); + ret->backend_data = talloc_strdup(mem_ctx, fullpath); SAFE_FREE(fullpath); *key = ret; return WERR_OK; } -static WERROR gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) +static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_value **val) { GSList *entries; GSList *cur; - REG_VAL **ar = talloc(p->mem_ctx, sizeof(REG_VAL *)); + GConfEntry *entry; + GConfValue *value; + struct registry_value *newval; char *fullpath = p->backend_data; - cur = entries = gconf_client_all_entries((GConfClient*)p->handle->backend_data, fullpath, NULL); - - (*count) = 0; - while(cur) { - GConfEntry *entry = cur->data; - GConfValue *value = gconf_entry_get_value(entry); - REG_VAL *newval = reg_val_new(p, NULL); - newval->name = talloc_strdup(newval->mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); - if(value) { - switch(value->type) { - case GCONF_VALUE_INVALID: - newval->data_type = REG_NONE; - break; - - case GCONF_VALUE_STRING: - newval->data_type = REG_SZ; - newval->data_blk = talloc_strdup(newval->mem_ctx, gconf_value_get_string(value)); - newval->data_len = strlen(newval->data_blk); - break; - - case GCONF_VALUE_INT: - newval->data_type = REG_DWORD; - newval->data_blk = talloc(newval->mem_ctx, sizeof(long)); - *((long *)newval->data_blk) = gconf_value_get_int(value); - newval->data_len = sizeof(long); - break; - - case GCONF_VALUE_FLOAT: - newval->data_blk = talloc(newval->mem_ctx, sizeof(double)); - newval->data_type = REG_BINARY; - *((double *)newval->data_blk) = gconf_value_get_float(value); - newval->data_len = sizeof(double); - break; - - case GCONF_VALUE_BOOL: - newval->data_blk = talloc(newval->mem_ctx, sizeof(BOOL)); - newval->data_type = REG_BINARY; - *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); - newval->data_len = sizeof(BOOL); - break; - - default: - newval->data_type = REG_NONE; - DEBUG(0, ("Not implemented..\n")); - break; - } - } else newval->data_type = REG_NONE; - - ar[(*count)] = newval; - ar = talloc_realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); - (*count)++; - g_free(cur->data); - cur = cur->next; - } + int i; + cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + entry = cur->data; + value = gconf_entry_get_value(entry); + + newval = talloc_p(mem_ctx, struct registry_value); + newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); + if(value) { + switch(value->type) { + case GCONF_VALUE_INVALID: + newval->data_type = REG_NONE; + break; + + case GCONF_VALUE_STRING: + newval->data_type = REG_SZ; + newval->data_blk = talloc_strdup(mem_ctx, gconf_value_get_string(value)); + newval->data_len = strlen(newval->data_blk); + break; + + case GCONF_VALUE_INT: + newval->data_type = REG_DWORD; + newval->data_blk = talloc_p(mem_ctx, long); + *((long *)newval->data_blk) = gconf_value_get_int(value); + newval->data_len = sizeof(long); + break; + + case GCONF_VALUE_FLOAT: + newval->data_blk = talloc_p(mem_ctx, double); + newval->data_type = REG_BINARY; + *((double *)newval->data_blk) = gconf_value_get_float(value); + newval->data_len = sizeof(double); + break; + + case GCONF_VALUE_BOOL: + newval->data_blk = talloc_p(mem_ctx, BOOL); + newval->data_type = REG_BINARY; + *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); + newval->data_len = sizeof(BOOL); + break; + + default: + newval->data_type = REG_NONE; + DEBUG(0, ("Not implemented..\n")); + break; + } + } else newval->data_type = REG_NONE; g_slist_free(entries); - *vals = ar; + *val = newval; return WERR_OK; } -static WERROR gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) +static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_key **sub) { GSList *dirs; GSList *cur; - REG_KEY **ar = talloc_array_p(p->mem_ctx, REG_KEY *, 1); + int i; char *fullpath = p->backend_data; - cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); - - (*count) = 0; - while(cur) { - char *winpath = reg_path_unix2win(strdup((char *)cur->data)); - ar[(*count)] = reg_key_new_abs(winpath, p->handle,NULL); - free(winpath); - ar[(*count)]->backend_data = reg_path_win2unix(talloc_strdup(ar[*count]->mem_ctx, cur->data)); - ar = talloc_realloc_p(ar, REG_KEY *, (*count)+2); - (*count)++; - g_free(cur->data); - cur = cur->next; - } + cur = dirs = gconf_client_all_dirs((GConfClient*)p->hive->backend_data, fullpath,NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + *sub = talloc_p(mem_ctx, struct registry_key); + (*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1); + (*sub)->backend_data = talloc_strdup(mem_ctx, cur->data); g_slist_free(dirs); - *subs = ar; return WERR_OK; } -static WERROR gconf_update_value(REG_VAL *val, int type, void *data, int len) +static WERROR gconf_set_value(struct registry_key *key, const char *valname, int type, void *data, int len) { GError *error = NULL; - char *keypath = val->backend_data; char *valpath; - if(val->name)asprintf(&valpath, "%s/%s", keypath, val->name); - else valpath = strdup(keypath); + asprintf(&valpath, "%s/%s", key->path, valname); switch(type) { case REG_SZ: case REG_EXPAND_SZ: - gconf_client_set_string((GConfClient *)val->handle->backend_data, valpath, data, &error); - free(valpath); + gconf_client_set_string((GConfClient *)key->hive->backend_data, valpath, data, &error); + SAFE_FREE(valpath); return gerror_to_werror(error); case REG_DWORD: - gconf_client_set_int((GConfClient *)val->handle->backend_data, valpath, + gconf_client_set_int((GConfClient *)key->hive->backend_data, valpath, *((int *)data), &error); - free(valpath); + SAFE_FREE(valpath); return gerror_to_werror(error); default: DEBUG(0, ("Unsupported type: %d\n", type)); - free(valpath); + SAFE_FREE(valpath); return WERR_NOT_SUPPORTED; } return WERR_NOT_SUPPORTED; } -static struct registry_ops reg_backend_gconf = { +static struct registry_operations reg_backend_gconf = { .name = "gconf", - .open_registry = reg_open_gconf, - .close_registry = reg_close_gconf, - .get_hive = gconf_get_hive, + .open_hive = reg_open_gconf_hive, .open_key = gconf_open_key, - .fetch_subkeys = gconf_fetch_subkeys, - .fetch_values = gconf_fetch_values, - .update_value = gconf_update_value, + .get_subkey_by_index = gconf_get_subkey_by_id, + .get_value_by_index = gconf_get_value_by_id, + .set_value = gconf_set_value, /* Note: * since GConf uses schemas for what keys and values are allowed, there diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 47cb60d711..e0f65f2c37 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { @@ -55,40 +54,46 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * return ret; } + +static int ldb_close_registry(void *data) +{ + ldb_close((struct ldb_context *)data); + return 0; +} + + /* * Saves the dn as private_data for every key/val */ -static WERROR ldb_open_registry(REG_HANDLE *handle, const char *location, const char *credentials) +static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) { struct ldb_context *c; - if (!location) return WERR_INVALID_PARAM; - c = ldb_connect(location, 0, NULL); + if (!hive->location) return WERR_INVALID_PARAM; + c = ldb_connect(hive->location, 0, NULL); ldb_set_debug_stderr(c); + if(!c) return WERR_FOOBAR; - handle->backend_data = c; + hive->backend_data = c; + talloc_set_destructor(c, ldb_close_registry); return WERR_OK; } -static WERROR ldb_close_registry(REG_HANDLE *h) -{ - ldb_close((struct ldb_context *)h->backend_data); - return WERR_OK; -} - -static WERROR ldb_add_key(REG_KEY *p, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **new) +static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **new) { return WERR_NOT_SUPPORTED; } -static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) +#if 0 +FIXME +static WERROR ldb_fetch_subkeys(struct registry_key *k, int *count, struct registry_key ***subkeys) { - struct ldb_context *c = k->handle->backend_data; + struct ldb_context *c = k->hive->backend_data; int ret, i, j; struct ldb_message **msg; @@ -99,7 +104,7 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) return WERR_FOOBAR; } - *subkeys = talloc_array_p(k->mem_ctx, REG_KEY *, ret); + *subkeys = talloc_array_p(k->mem_ctx, struct registry_key *, ret); j = 0; for(i = 0; i < ret; i++) { struct ldb_message_element *el; @@ -121,9 +126,9 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) return WERR_OK; } -static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +static WERROR ldb_fetch_values(struct registry_key *k, int *count, REG_VAL ***values) { - struct ldb_context *c = k->handle->backend_data; + struct ldb_context *c = k->hive->backend_data; int ret, i, j; struct ldb_message **msg; @@ -156,21 +161,14 @@ static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) return WERR_OK; } -static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) -{ - if(num != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - return WERR_OK; -} +#endif -static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) +static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { struct ldb_context *c = h->backend_data; struct ldb_message **msg; char *ldap_path; int ret; - TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); - if(num != 0) return WERR_NO_MORE_ITEMS; ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "*", NULL,&msg); @@ -182,25 +180,20 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k return WERR_FOOBAR; } - *key = reg_key_new_abs(name, h, ldap_path); - talloc_steal((*key)->mem_ctx, ldap_path); - printf("Got something!\n"); + *key = talloc_p(mem_ctx, struct registry_key); /* FIXME */ ldb_search_free(c, msg); - talloc_destroy(mem_ctx); return WERR_OK; } -static struct registry_ops reg_backend_ldb = { +static struct registry_operations reg_backend_ldb = { .name = "ldb", - .open_registry = ldb_open_registry, - .get_hive = ldb_get_hive, - .close_registry = ldb_close_registry, + .open_hive = ldb_open_hive, .open_key = ldb_open_key, - .fetch_subkeys = ldb_fetch_subkeys, - .fetch_values = ldb_fetch_values, +/* .fetch_subkeys = ldb_fetch_subkeys, + .fetch_values = ldb_fetch_values,*/ .add_key = ldb_add_key, }; 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 ee9f8bf24f..c271c55991 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -304,9 +304,9 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, *************************************************************************/ #include "includes.h" -#include "lib/registry/common/registry.h" #define REG_KEY_LIST_SIZE 10 +#define FLAG_HAS_NAME 0x01 /*FIXME*/ /* @@ -514,7 +514,7 @@ static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, con /* * Create a default ACL */ -static SEC_ACL *nt_create_default_acl(REG_HANDLE *regf) +static SEC_ACL *nt_create_default_acl(struct registry_hive *regf) { SEC_ACE aces[8]; @@ -534,7 +534,7 @@ static SEC_ACL *nt_create_default_acl(REG_HANDLE *regf) * Create a default security descriptor. We pull in things from env * if need be */ -static SEC_DESC *nt_create_def_sec_desc(REG_HANDLE *regf) +static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) { SEC_DESC *tmp; @@ -559,7 +559,7 @@ static SEC_DESC *nt_create_def_sec_desc(REG_HANDLE *regf) * says, but the Owner and Group SIDs can be overwridden from the command line * and additional ACEs can be applied from the command line etc. */ -static KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) +static KEY_SEC_DESC *nt_inherit_security(struct registry_key *key) { if (!key) return NULL; @@ -570,7 +570,7 @@ static KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) * Create an initial security descriptor and init other structures, if needed * We assume that the initial security stuff is empty ... */ -static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) +static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) { REGF *regf = h->backend_data; KEY_SEC_DESC *tsec = NULL; @@ -618,7 +618,7 @@ static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) /* Get the header of the registry. Return a pointer to the structure * If the mmap'd area has not been allocated, then mmap the input file */ -static REGF_HDR *nt_get_regf_hdr(REG_HANDLE *h) +static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) { REGF *regf = h->backend_data; SMB_REG_ASSERT(regf); @@ -676,7 +676,7 @@ static int valid_regf_hdr(REGF_HDR *regf_hdr) /* * Create a new entry in the map, and increase the size of the map if needed */ -static SK_MAP *alloc_sk_map_entry(REG_HANDLE *h, KEY_SEC_DESC *tmp, int sk_off) +static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, int sk_off) { REGF *regf = h->backend_data; if (!regf->sk_map) { /* Allocate a block of 10 */ @@ -731,7 +731,7 @@ KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) /* * Allocate a KEY_SEC_DESC if we can't find one in the map */ -static KEY_SEC_DESC *lookup_create_sec_key(REG_HANDLE *h, SK_MAP *sk_map, int sk_off) +static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_map, int sk_off) { REGF *regf = h->backend_data; KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); @@ -750,7 +750,7 @@ static KEY_SEC_DESC *lookup_create_sec_key(REG_HANDLE *h, SK_MAP *sk_map, int sk } } -static SEC_DESC *process_sec_desc(REG_HANDLE *regf, SEC_DESC *sec_desc) +static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc) { SEC_DESC *tmp = NULL; @@ -790,7 +790,7 @@ static SEC_DESC *process_sec_desc(REG_HANDLE *regf, SEC_DESC *sec_desc) return tmp; } -static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, int size) +static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_off, int size) { KEY_SEC_DESC *tmp = NULL; int sk_next_off, sk_prev_off, sk_size; @@ -879,38 +879,34 @@ static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, in /* * Process a VK header and return a value */ -static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **value) +static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR *vk_hdr, int size, struct registry_value **value) { - char val_name[1024]; - REGF *regf = parent->handle->backend_data; + REGF *regf = parent->hive->backend_data; int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - REG_VAL *tmp = NULL; + struct registry_value *tmp = NULL; if (!vk_hdr) return WERR_INVALID_PARAM; if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", - vk_id, (int)vk_hdr, parent->handle->location)); + vk_id, (int)vk_hdr, parent->hive->location)); return WERR_GENERAL_FAILURE; } nam_len = SVAL(&vk_hdr->nam_len,0); - val_name[nam_len] = '\0'; flag = SVAL(&vk_hdr->flag,0); dat_type = IVAL(&vk_hdr->dat_type,0); dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ dat_off = IVAL(&vk_hdr->dat_off,0); - tmp = reg_val_new(parent, NULL); - tmp->has_name = flag; + tmp = talloc_p(mem_ctx, struct registry_value); tmp->data_type = dat_type; - if (flag & 0x01) { - strncpy(val_name, vk_hdr->dat_name, nam_len); - tmp->name = strdup(val_name); + if (flag & FLAG_HAS_NAME) { + tmp->name = talloc_strndup(mem_ctx, vk_hdr->dat_name, nam_len); + } else { + tmp->name = NULL; } - else - strncpy(val_name, "<No Name>", 10); /* * Allocate space and copy the data as a BLOB @@ -918,9 +914,7 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val if (dat_len&0x7FFFFFFF) { - char *dtmp = (char *)talloc(tmp->mem_ctx, dat_len&0x7FFFFFFF); - - tmp->data_blk = dtmp; + char *dtmp = (char *)talloc(mem_ctx, dat_len&0x7FFFFFFF); if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ char *dat_ptr = LOCN(regf->base, dat_off); @@ -937,6 +931,15 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val memcpy(dtmp, &dat_off, dat_len); } + + if(tmp->data_type == REG_SZ) { + char *ret; + dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (const void **)&ret); + dtmp = ret; + } + + + tmp->data_blk = dtmp; tmp->data_len = dat_len; } @@ -958,7 +961,7 @@ static BOOL vl_verify(VL_TYPE vl, int count, int size) #endif -static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) { int lf_id; if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { @@ -969,7 +972,7 @@ static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) return WERR_OK; } -static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count) +static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, int *count) { WERROR error; @@ -986,23 +989,23 @@ static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count } -static WERROR nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **); +static WERROR nk_to_key(TALLOC_CTX *, struct registry_hive *regf, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **); /* * Process an LF Header and return a list of sub-keys */ -static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG_KEY **key) +static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_HDR *lf_hdr, int size, int n, struct registry_key **key) { - REGF *regf = parent->handle->backend_data; + REGF *regf = parent->hive->backend_data; int count, nk_off; NK_HDR *nk_hdr; WERROR error; if (!lf_hdr) return WERR_INVALID_PARAM; - error = lf_verify(parent->handle, lf_hdr, size); + error = lf_verify(parent->hive, lf_hdr, size); if(!W_ERROR_IS_OK(error)) return error; SMB_REG_ASSERT(size < 0); @@ -1015,13 +1018,13 @@ static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); DEBUG(2, ("NK Offset: %0X\n", nk_off)); nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent, key); + return nk_to_key(mem_ctx, parent->hive, nk_hdr, BLK_SIZE(nk_hdr), parent, key); } -static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **key) +static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **key) { REGF *regf = h->backend_data; - REG_KEY *tmp = NULL, *own; + struct registry_key *tmp = NULL, *own; int namlen, clsname_len, sk_off, own_off; uint_t nk_id; SK_HDR *sk_hdr; @@ -1032,7 +1035,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", - nk_id, (int)nk_hdr, parent->handle->location)); + nk_id, (int)nk_hdr, parent->hive->location)); return WERR_INVALID_PARAM; } @@ -1071,8 +1074,9 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent return WERR_GENERAL_FAILURE; } - if(type == REG_ROOT_KEY) tmp = reg_key_new_abs(key_name, h, nk_hdr); - else tmp = reg_key_new_rel(key_name, parent, nk_hdr); + tmp = talloc_p(mem_ctx, struct registry_key); + tmp->name = talloc_strdup(mem_ctx, key_name); + tmp->backend_data = nk_hdr; DEBUG(2, ("Key name: %s\n", key_name)); @@ -1089,7 +1093,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)); - pull_ucs2_talloc(tmp->mem_ctx, &tmp->class_name, clsnamep); + pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); DEBUGADD(2,(" Class Name: %s\n", cls_name)); @@ -1100,7 +1104,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent */ own_off = IVAL(&nk_hdr->own_off,0); - own = (REG_KEY *)LOCN(regf->base, own_off); + own = (struct registry_key *)LOCN(regf->base, own_off); DEBUG(2, ("Owner Offset: %0X\n", own_off)); DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", @@ -1136,7 +1140,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent /* * Allocate a new hbin block, set up the header for the block etc */ -static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) +static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) { REGF *regf = h->backend_data; HBIN_BLK *tmp; @@ -1185,7 +1189,7 @@ static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) * Allocate a unit of space ... and return a pointer as function param * and the block's offset as a side effect */ -static void *nt_alloc_regf_space(REG_HANDLE *h, int size, uint_t *off) +static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) { REGF *regf = h->backend_data; int tmp = 0; @@ -1268,7 +1272,7 @@ static void *nt_alloc_regf_space(REG_HANDLE *h, int size, uint_t *off) /* * Store a SID at the location provided */ -static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, uint8_t *locn) +static int nt_store_SID(struct registry_hive *regf, DOM_SID *sid, uint8_t *locn) { int i; uint8_t *p = locn; @@ -1290,7 +1294,7 @@ static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, uint8_t *locn) } -static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, uint8_t *locn) +static int nt_store_ace(struct registry_hive *regf, SEC_ACE *ace, uint8_t *locn) { int size = 0; SEC_ACE *reg_ace = (SEC_ACE *)locn; @@ -1321,7 +1325,7 @@ static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, uint8_t *locn) /* * Store an ACL at the location provided */ -static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { +static int nt_store_acl(struct registry_hive *regf, SEC_ACL *acl, uint8_t *locn) { int size = 0, i; uint8_t *p = locn, *s; @@ -1357,7 +1361,7 @@ static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { * that first, then the owner, then the group SID. So, we do it that way * too. */ -static uint_t nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) +static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char *locn) { SEC_DESC *rsd = (SEC_DESC *)locn; uint_t size = 0, off = 0; @@ -1424,7 +1428,7 @@ static uint_t nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) * If it has already been stored, just get its offset from record * otherwise, store it and record its offset */ -static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) +static uint_t nt_store_security(struct registry_hive *regf, KEY_SEC_DESC *sec) { int size = 0; uint_t sk_off; @@ -1480,7 +1484,7 @@ static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) * We return the offset of the NK struct * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... */ -static int nt_store_reg_key(REG_HANDLE *regf, REG_KEY *key) +static int nt_store_reg_key(struct registry_hive *regf, struct registry_key *key) { NK_HDR *nk_hdr; uint_t nk_off, sk_off, size; @@ -1543,7 +1547,7 @@ error: * We actually create the registry header block and link it to the chain * of output blocks. */ -static REGF_HDR *nt_get_reg_header(REG_HANDLE *h) { +static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { REGF *regf = h->backend_data; HBIN_BLK *tmp = NULL; @@ -1567,7 +1571,7 @@ error: #endif -static WERROR nt_close_registry (REG_HANDLE *h) +static WERROR nt_close_registry (struct registry_hive *h) { REGF *regf = h->backend_data; if (regf->base) munmap(regf->base, regf->sbuf.st_size); @@ -1577,16 +1581,16 @@ static WERROR nt_close_registry (REG_HANDLE *h) return WERR_OK; } -static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials) +static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) { REGF *regf; REGF_HDR *regf_hdr; uint_t regf_id, hbin_id; HBIN_HDR *hbin_hdr; - regf = (REGF *)talloc_p(h->mem_ctx, REGF); + regf = (REGF *)talloc_p(mem_ctx, REGF); memset(regf, 0, sizeof(REGF)); - regf->owner_sid_str = credentials; + regf->owner_sid_str = h->credentials; h->backend_data = regf; DEBUG(5, ("Attempting to load registry file\n")); @@ -1659,18 +1663,13 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char h->backend_data = regf; - return WERR_OK; + return nk_to_key(mem_ctx, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, 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); -} -static WERROR nt_num_subkeys(REG_KEY *k, int *num) +static WERROR nt_num_subkeys(struct registry_key *k, int *num) { - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; LF_HDR *lf_hdr; int lf_off; NK_HDR *nk_hdr = k->backend_data; @@ -1682,23 +1681,23 @@ static WERROR nt_num_subkeys(REG_KEY *k, int *num) } lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr), num); + return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); } -static WERROR nt_num_values(REG_KEY *k, int *count) +static WERROR nt_num_values(struct registry_key *k, int *count) { NK_HDR *nk_hdr = k->backend_data; *count = IVAL(&nk_hdr->val_cnt,0); return WERR_OK; } -static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) +static WERROR nt_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_value **value) { VL_TYPE *vl; int val_off, vk_off; int val_count; VK_HDR *vk_hdr; - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; NK_HDR *nk_hdr = k->backend_data; val_count = IVAL(&nk_hdr->val_cnt,0); val_off = IVAL(&nk_hdr->val_off,0); @@ -1709,12 +1708,12 @@ static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) vk_off = IVAL(&vl[n],0); vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr), value); + return vk_to_val(mem_ctx, k, vk_hdr, BLK_SIZE(vk_hdr), value); } -static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey) +static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_key **subkey) { - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; int lf_off; NK_HDR *nk_hdr = k->backend_data; LF_HDR *lf_hdr; @@ -1727,17 +1726,15 @@ static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey) if (lf_off != -1) { lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); + return lf_get_entry(mem_ctx, k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); } return WERR_NO_MORE_ITEMS; } -static struct registry_ops reg_backend_nt4 = { +static struct registry_operations reg_backend_nt4 = { .name = "nt4", - .open_registry = nt_open_registry, - .close_registry = nt_close_registry, - .get_hive = nt_get_root_key, + .open_hive = nt_open_hive, .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 0d8d935a4a..1c887fc411 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" -#include "lib/registry/common/registry.h" /** * This is the RPC backend for the registry library. @@ -37,7 +36,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) } -#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \ +#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ { \ struct winreg_Open ## u r; \ struct winreg_OpenUnknown unknown; \ @@ -49,7 +48,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ - status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \ + status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ if (NT_STATUS_IS_ERR(status)) {\ DEBUG(0,("Error executing open\n"));\ return ntstatus_to_werror(status);\ @@ -74,7 +73,7 @@ struct rpc_key_data { struct { const char *name; - WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h); + WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); } known_hives[] = { { "HKEY_LOCAL_MACHINE", open_HKLM }, { "HKEY_CURRENT_USER", open_HKCU }, @@ -84,122 +83,124 @@ struct { { NULL, NULL } }; -static WERROR rpc_query_key(REG_KEY *k); +static WERROR rpc_query_key(struct registry_key *k); -static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) +WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) +{ + int i = 0; + *hives = talloc_p(mem_ctx, char *); + for(i = 0; known_hives[i].name; i++) { + *hives = talloc_realloc_p(*hives, char *, i+2); + (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name); + } + (*hives)[i] = NULL; + return WERR_OK; +} + +static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { NTSTATUS status; char *user, *pass; + struct rpc_key_data *mykeydata; + struct dcerpc_pipe *p; + int n; - if(!credentials || !location) return WERR_INVALID_PARAM; + if(!h->credentials || !h->location) return WERR_INVALID_PARAM; - user = talloc_strdup(h->mem_ctx, credentials); + user = talloc_strdup(mem_ctx, h->credentials); pass = strchr(user, '%'); - *pass = '\0'; pass++; + if(pass) + { + *pass = '\0'; pass++; + } else { + pass = ""; + } - status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, h->location, + status = dcerpc_pipe_connect(&p, h->location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), user, pass); - - return ntstatus_to_werror(status); -} -static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k) -{ - struct rpc_key_data *mykeydata; - WERROR error; + h->backend_data = p; + + if(NT_STATUS_IS_ERR(status)) return ntstatus_to_werror(status); + + for(n = 0; known_hives[n].name; n++) + { + if(!strcmp(known_hives[n].name, h->backend_hivename)) break; + } + 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); + + *k = talloc_p(mem_ctx, struct registry_key); + (*k)->backend_data = mykeydata = talloc_p(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; + return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol)); } -static WERROR rpc_close_registry(REG_HANDLE *h) +static WERROR rpc_close_registry(struct registry_hive *h) { 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) +static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) { struct winreg_OpenKey r; - WERROR error; - REG_KEY *hivekey; struct rpc_key_data *mykeydata; - 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; + k->backend_data = mykeydata = talloc_p(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(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.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); + init_winreg_String(&r.in.keyname, k->path); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); return r.out.result; } -static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key) +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { struct rpc_key_data *mykeydata; struct winreg_OpenKey r; - REG_KEY *hivekey; - WERROR error; - - *key = reg_key_new_abs(name, h, NULL); - (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data); + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->name = talloc_strdup(mem_ctx, name); + + (*key)->backend_data = mykeydata = talloc_p(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); + r.in.handle = &(((struct rpc_key_data *)h->root->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); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->backend_data), mem_ctx, &r); return r.out.result; } -static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) +static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) { - struct winreg_EnumValue r; - struct winreg_Uint8buf vb; - struct winreg_EnumValueName vn; - NTSTATUS status; - struct rpc_key_data *mykeydata; - uint32_t type = 0x0, requested_len = 0, returned_len = 0; + struct rpc_key_data *mykeydata = parent->backend_data; + uint32_t requested_len = 0; WERROR error; - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - if(mykeydata->num_values == -1) { error = rpc_query_key(parent); if(!W_ERROR_IS_OK(error)) return error; @@ -207,6 +208,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) requested_len = mykeydata->max_valdatalen; +#if 0 /* EnumValue is not working yet ... */ r.in.handle = &mykeydata->pol; r.in.enum_index = n; r.in.type = r.out.type = &type; @@ -225,7 +227,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) vb.max_len = mykeydata->max_valdatalen; vb.offset = 0x0; vb.len = 0x0; - vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen); + vb.buffer = talloc_array_p(mem_ctx, uint8, mykeydata->max_valdatalen); r.in.value = r.out.value = &vb; status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); @@ -242,23 +244,20 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) exit(1); return WERR_OK; } +#endif - return r.out.result; + return WERR_NOT_SUPPORTED; } -static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) +static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) { struct winreg_EnumKey r; struct winreg_EnumKeyNameRequest keyname; struct winreg_String classname; struct winreg_Time tm; struct rpc_key_data *mykeydata = parent->backend_data; - WERROR error; NTSTATUS status; - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - r.in.handle = &mykeydata->pol; keyname.unknown = 0x0000020a; init_winreg_String(&keyname.key_name, NULL); @@ -271,40 +270,33 @@ 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((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); + status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, 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->hive->root == parent) + return rpc_open_key(mem_ctx, parent->hive, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); + return rpc_open_key(mem_ctx, parent->hive, talloc_asprintf(mem_ctx, "%s\\%s", parent->path, r.out.out_name->name), subkey); } return r.out.result; } -static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **key) +static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) { - struct rpc_key_data *mykeydata; - WERROR error; - - 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) +static WERROR rpc_query_key(struct registry_key *k) { NTSTATUS status; - WERROR error; struct winreg_QueryInfoKey r; - struct rpc_key_data *mykeydata; - - error = rpc_key_put_rpc_data(k, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; + struct rpc_key_data *mykeydata = k->backend_data; + TALLOC_CTX *mem_ctx = talloc_init("query_key"); init_winreg_String(&r.in.class, NULL); r.in.handle = &mykeydata->pol; - status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r); + talloc_destroy(mem_ctx); if (!NT_STATUS_IS_OK(status)) { printf("QueryInfoKey failed - %s\n", nt_errstr(status)); @@ -321,40 +313,37 @@ static WERROR rpc_query_key(REG_KEY *k) return r.out.result; } -static WERROR rpc_del_key(REG_KEY *k) +static WERROR rpc_del_key(struct registry_key *k) { NTSTATUS status; struct rpc_key_data *mykeydata = k->backend_data; struct winreg_DeleteKey r; - REG_KEY *parent; + struct registry_key *parent; WERROR error; + TALLOC_CTX *mem_ctx = talloc_init("del_key"); - error = reg_key_get_parent(k, &parent); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_get_parent(mem_ctx, k, &parent); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } + + mykeydata = parent->backend_data; - 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((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); - return r.out.result; -} + talloc_destroy(mem_ctx); -static void rpc_close_key(REG_KEY *k) -{ - reg_key_free(k); + return r.out.result; } -static WERROR rpc_num_values(REG_KEY *key, int *count) { +static WERROR rpc_num_values(struct registry_key *key, int *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - error = rpc_key_put_rpc_data(key, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - if(mykeydata->num_values == -1) { error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; @@ -364,13 +353,10 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) { return WERR_OK; } -static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { +static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - 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; @@ -380,19 +366,17 @@ static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { return WERR_OK; } -static struct registry_ops reg_backend_rpc = { +static struct registry_operations reg_backend_rpc = { .name = "rpc", - .open_registry = rpc_open_registry, - .close_registry = rpc_close_registry, - .get_hive = rpc_get_hive, + .open_hive = rpc_open_hive, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, .get_value_by_index = rpc_get_value_by_index, .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, + .list_available_hives = rpc_list_hives, }; NTSTATUS registry_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 index f392759b8d..2184a8855d 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -20,7 +20,6 @@ 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 @@ -179,67 +178,18 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) } } -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))); - - return WERR_OK; -} - -static WERROR w95_get_subkey_by_index (REG_KEY *parent, int n, REG_KEY **key) -{ - CREG *creg = parent->handle->backend_data; - RGKN_KEY *rgkn_key = parent->backend_data; - RGKN_KEY *child; - DWORD child_offset; - DWORD cur = 0; - - /* Get id of first child */ - child_offset = rgkn_key->first_child_offset; - - while(child_offset != 0xFFFFFFFF) { - child = LOCN_RGKN(creg, child_offset); - - /* n == cur ? return! */ - if(cur == n) { - RGDB_KEY *rgdb_key; - char *name; - rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); - if(!rgdb_key) { - DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); - return WERR_FOOBAR; - } - name = strndup((char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); - *key = reg_key_new_rel(name, parent, child); - SAFE_FREE(name); - return WERR_OK; - } - - cur++; - - child_offset = child->next_offset; - } - - return WERR_NO_MORE_ITEMS; -} - -static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) +static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **root) { CREG *creg; DWORD creg_id, rgkn_id; DWORD i; DWORD offset; - creg = talloc_p(h->mem_ctx, CREG); + creg = talloc_p(mem_ctx, CREG); memset(creg, 0, sizeof(CREG)); h->backend_data = creg; - if((creg->fd = open(location, O_RDONLY, 0000)) < 0) { + if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) { return WERR_FOOBAR; } @@ -250,7 +200,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0); if ((int)creg->base == 1) { - DEBUG(0,("Could not mmap file: %s, %s\n", location, strerror(errno))); + DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno))); return WERR_FOOBAR; } @@ -258,7 +208,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) { DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n", - creg_id, location)); + creg_id, h->location)); return WERR_FOOBAR; } @@ -266,7 +216,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", - rgkn_id, location)); + rgkn_id, h->location)); return WERR_FOOBAR; } @@ -282,7 +232,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre } #endif - creg->rgdb_keys = talloc_array_p(h->mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); + creg->rgdb_keys = talloc_array_p(mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); offset = 0; DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); @@ -291,14 +241,14 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n", - rgdb_hdr->RGDB_ID, location)); + rgdb_hdr->RGDB_ID, h->location)); return WERR_FOOBAR; } else { DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); } - creg->rgdb_keys[i] = talloc_array_p(h->mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); + creg->rgdb_keys[i] = talloc_array_p(mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); parse_rgdb_block(creg, rgdb_hdr); @@ -306,11 +256,51 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre offset+=rgdb_hdr->size; } - + /* First element in rgkn should be root key */ + *root = talloc_p(mem_ctx, struct registry_key); + (*root)->name = NULL; + (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); + return WERR_OK; } -static WERROR w95_close_reg(REG_HANDLE *h) +static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **key) +{ + CREG *creg = parent->hive->backend_data; + RGKN_KEY *rgkn_key = parent->backend_data; + RGKN_KEY *child; + DWORD child_offset; + DWORD cur = 0; + + /* Get id of first child */ + child_offset = rgkn_key->first_child_offset; + + while(child_offset != 0xFFFFFFFF) { + child = LOCN_RGKN(creg, child_offset); + + /* n == cur ? return! */ + if(cur == n) { + RGDB_KEY *rgdb_key; + rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); + if(!rgdb_key) { + DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); + return WERR_FOOBAR; + } + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->backend_data = child; + (*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); + return WERR_OK; + } + + cur++; + + child_offset = child->next_offset; + } + + return WERR_NO_MORE_ITEMS; +} + +static WERROR w95_close_reg(struct registry_hive *h) { CREG *creg = h->backend_data; if (creg->base) munmap(creg->base, creg->sbuf.st_size); @@ -319,47 +309,51 @@ static WERROR w95_close_reg(REG_HANDLE *h) return WERR_OK; } +static WERROR w95_num_values(struct registry_key *k, int *count) +{ + RGKN_KEY *rgkn_key = k->backend_data; + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + + if(!rgdb_key) return WERR_FOOBAR; + + *count = rgdb_key->num_values; + + return WERR_OK; +} -static WERROR w95_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) { RGKN_KEY *rgkn_key = k->backend_data; DWORD i; DWORD offset = 0; - RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->handle->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + RGDB_VALUE *curval; if(!rgdb_key) return WERR_FOOBAR; - *count = rgdb_key->num_values; + if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS; - if((*count) == 0) return WERR_OK; + for(i = 0; i < idx; i++) { + curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); + offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len; + } - (*values) = talloc_array_p(k->mem_ctx, REG_VAL *, (*count)+1); - for(i = 0; i < rgdb_key->num_values; i++) { - RGDB_VALUE *val = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); - (*values)[i] = reg_val_new(k, val); - - /* Name */ - (*values)[i]->name = talloc_strndup(k->mem_ctx, (char *)val+sizeof(RGDB_VALUE), val->name_len); + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->backend_data = curval; + (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); - /* Value */ - (*values)[i]->data_len = val->data_len; - (*values)[i]->data_blk = talloc_memdup((*values)[i]->mem_ctx, (char *)val+sizeof(RGDB_VALUE)+val->name_len, val->data_len); - - /* Type */ - (*values)[i]->data_type = val->type; - - offset+=sizeof(RGDB_VALUE) + val->name_len + val->data_len; - } + (*value)->data_len = curval->data_len; + (*value)->data_blk = talloc_memdup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); + (*value)->data_type = curval->type; return WERR_OK; } -static struct registry_ops reg_backend_w95 = { +static struct registry_operations reg_backend_w95 = { .name = "w95", - .open_registry = w95_open_reg, - .close_registry = w95_close_reg, - .get_hive = w95_open_root, - .fetch_values = w95_fetch_values, + .open_hive = w95_open_reg, + .get_value_by_index = w95_get_value_by_id, + .num_values = w95_num_values, .get_subkey_by_index = w95_get_subkey_by_index, }; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index c46411ae31..524e538591 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -21,47 +21,57 @@ #include "includes.h" -static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) +static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) { int i; - REG_KEY *t1, *t2; - REG_VAL *v1, *v2; + struct registry_key *t1, *t2; + struct registry_value *v1, *v2; WERROR error1, error2; + TALLOC_CTX *mem_ctx = talloc_init("writediff"); - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(oldkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(newkey, reg_key_name(t1), &t2); + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2); if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "-%s\n", reg_key_get_path(t1)+1); + fprintf(out, "-%s\n", t1->path+1); } else if(!W_ERROR_IS_OK(error2)) { DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(newkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1), &t2); + mem_ctx = talloc_init("writediff"); + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2); if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1); + fprintf(out, "\n[%s]\n", t1->path+1); } else if(!W_ERROR_IS_OK(error2)) { DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } writediff(t2, t1, out); } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(newkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(oldkey, reg_val_name(v1), &v2); - if ((W_ERROR_IS_OK(error2) && (reg_val_size(v2) != reg_val_size(v1) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1)))) + + mem_ctx = talloc_init("writediff"); + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); + if ((W_ERROR_IS_OK(error2) && (v2->data_len != v1->data_len || memcmp(v1->data_blk, v2->data_blk, v1->data_len))) || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(v1), str_regtype(reg_val_type(v1)), reg_val_data_string(v1)); + fprintf(out, "\"%s\"=%s:%s\n", v1->name, str_regtype(v1->data_type), reg_val_data_string(mem_ctx, v1)); } if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { @@ -69,22 +79,27 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; } + mem_ctx = talloc_init("writediff"); - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(oldkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(newkey, reg_val_name(v1), &v2); + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2); if(W_ERROR_IS_OK(error2)) { } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=-\n", reg_val_name(v1)); + fprintf(out, "\"%s\"=-\n", v1->name); } else { DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; @@ -100,8 +115,7 @@ 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 *h1, *h2; - REG_KEY *root1 = NULL, *root2; + struct registry_context *h1, *h2; int from_null = 0; int i; WERROR error, error2; @@ -114,6 +128,12 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -140,7 +160,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(!backend1) backend1 = "dir"; - error = reg_open(backend1, location1, credentials1, &h1); + error = reg_open(&h1, backend1, location1, credentials1); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); return 1; @@ -155,7 +175,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(!backend2) backend2 = "dir"; - error = reg_open(backend2, location2, credentials2, &h2); + error = reg_open(&h2, backend2, location2, credentials2); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); return 1; @@ -176,20 +196,8 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) 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; + for(i = 0; i < h1->num_hives && i < h2->num_hives; i++) { + writediff(h1->hives[i]->root, h2->hives[i]->root, fd); } fclose(fd); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 7eddea2b93..1b33628a71 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -664,12 +664,13 @@ static CMD_FILE *cmd_file_create(const char *file) char *str_type(uint8_t type); -static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) +static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd_file_name) { CMD *cmd; BOOL modified = False; CMD_FILE *cmd_file = NULL; - REG_KEY *tmp = NULL; + TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file"); + struct registry_key *tmp = NULL; WERROR error; cmd_file = cmd_file_create(cmd_file_name); @@ -680,12 +681,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) */ switch (cmd->cmd) { case CMD_ADD_KEY: - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, 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_abs(r, cmd->key))) { - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, 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; @@ -699,12 +700,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) while (cmd->val_count) { VAL_SPEC_LIST *val = cmd->val_spec_list; - REG_VAL *reg_val = NULL; + struct registry_value *reg_val = NULL; if (val->type == REG_DELETE) { - error = reg_key_get_value_by_name( tmp, val->name, ®_val); + error = reg_key_get_value_by_name( mem_ctx, tmp, val->name, ®_val); if(W_ERROR_IS_OK(error)) { - error = reg_val_del(reg_val); + error = reg_del_value(reg_val); } if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error removing value '%s'\n", val->name)); @@ -712,7 +713,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) modified = True; } else { - if(!W_ERROR_IS_OK(reg_key_add_value(tmp, val->name, val->type, val->val, strlen(val->val)))) { + if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, val->val, strlen(val->val)))) { DEBUG(0, ("Error adding new value '%s'\n", val->name)); continue; } @@ -732,7 +733,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) * Find the key if it exists, and delete it ... */ - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); continue; @@ -760,7 +761,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) const char *credentials = NULL; const char *patch; const char *backend = "dir"; - REG_HANDLE *h; + struct registry_context *h; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP @@ -769,6 +770,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -782,7 +789,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) return 1; } - error = reg_open(backend, location, credentials, &h); + error = reg_open(&h, backend, location, credentials); if(!h) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); return 1; @@ -794,7 +801,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) nt_apply_reg_command_file(h, patch); - reg_free(h); + talloc_destroy(h->mem_ctx); return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 638ed70d5e..78fe36f1a0 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -33,96 +33,96 @@ * exit */ -static REG_KEY *cmd_info(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { time_t last_mod; - printf("Name: %s\n", reg_key_name(cur)); - printf("Full path: %s\n", reg_key_get_path(cur)); - printf("Key Class: %s\n", reg_key_class(cur)); - last_mod = nt_time_to_unix(reg_key_last_modified(cur)); + printf("Name: %s\n", cur->name); + printf("Full path: %s\n", cur->path); + printf("Key Class: %s\n", cur->class_name); + last_mod = nt_time_to_unix(cur->last_mod); printf("Time Last Modified: %s\n", ctime(&last_mod)); /* FIXME: Security info */ return cur; } -static REG_KEY *cmd_pwd(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - printf("%s\n", reg_key_get_path_abs(cur)); + printf("%s\n", cur->path); return cur; } -static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { /* FIXME */ return NULL; } -static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *new = NULL; + struct registry_key *new = NULL; WERROR error; if(argc < 2) { new = cur; } else { - error = reg_open_key(cur, argv[1], &new); + error = reg_open_key(mem_ctx, cur, argv[1], &new); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error))); return NULL; } } - printf("Current path is: %s\n", reg_key_get_path_abs(new)); + printf("Current path is: %s\n", new->path); return new; } -static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; WERROR error; - REG_VAL *value; - REG_KEY *sub; - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(cur, i, &sub)); i++) { - printf("K %s\n", reg_key_name(sub)); + struct registry_value *value; + struct registry_key *sub; + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, cur, i, &sub)); i++) { + printf("K %s\n", sub->name); } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error))); } - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(cur, i, &value)); i++) { - printf("V \"%s\" %s %s\n", reg_val_name(value), str_regtype(reg_val_type(value)), reg_val_data_string(value)); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) { + printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); } return NULL; } -static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *tmp; + struct registry_key *tmp; if(argc < 2) { fprintf(stderr, "Usage: mkkey <keyname>\n"); return NULL; } - if(!W_ERROR_IS_OK(reg_key_add_name(cur, argv[1], 0, NULL, &tmp))) { + if(!W_ERROR_IS_OK(reg_key_add_name(mem_ctx, cur, argv[1], 0, NULL, &tmp))) { fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]); return NULL; } - fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path_abs(cur)); + fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], cur->path); return NULL; } -static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *key; + struct registry_key *key; if(argc < 2) { fprintf(stderr, "Usage: rmkey <name>\n"); return NULL; } - if(!W_ERROR_IS_OK(reg_open_key(cur, argv[1], &key))) { + if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) { fprintf(stderr, "No such subkey '%s'\n", argv[1]); return NULL; } @@ -136,20 +136,20 @@ static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_VAL *val; + struct registry_value *val; if(argc < 2) { fprintf(stderr, "Usage: rmval <valuename>\n"); return NULL; } - if(!W_ERROR_IS_OK(reg_key_get_value_by_name(cur, argv[1], &val))) { + if(!W_ERROR_IS_OK(reg_key_get_value_by_name(mem_ctx, cur, argv[1], &val))) { fprintf(stderr, "No such value '%s'\n", argv[1]); return NULL; } - if(!W_ERROR_IS_OK(reg_val_del(val))) { + if(!W_ERROR_IS_OK(reg_del_value(val))) { fprintf(stderr, "Error deleting value '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); @@ -158,38 +158,33 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *cmd_hive(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; - WERROR error = WERR_OK; - for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_KEY *hive; - error = reg_get_hive(reg_key_handle(cur), i, &hive); - if(!W_ERROR_IS_OK(error)) break; + for(i = 0; i < cur->hive->reg_ctx->num_hives; i++) { if(argc == 1) { - printf("%s\n", reg_key_name(hive)); - } else if(!strcmp(reg_key_name(hive), argv[1])) { - return hive; + printf("%s\n", cur->hive->reg_ctx->hives[i]->name); + } else if(!strcmp(cur->hive->reg_ctx->hives[i]->name, argv[1])) { + return cur->hive->reg_ctx->hives[i]->root; } - reg_key_free(hive); } return NULL; } -static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { exit(0); return NULL; } -static REG_KEY *cmd_help(REG_KEY *, int, char **); +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *, int, char **); struct { const char *name; const char *alias; const char *help; - REG_KEY *(*handle)(REG_KEY *, int argc, char **argv); + struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_key *, int argc, char **argv); } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, {"ch", "hive", "Change current hive", cmd_hive }, @@ -205,7 +200,7 @@ struct { {NULL } }; -static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; printf("Available commands:\n"); @@ -215,7 +210,7 @@ static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *process_cmd(REG_KEY *k, char *line) +static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key *k, char *line) { int argc; char **argv = NULL; @@ -229,7 +224,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) for(i = 0; regshell_cmds[i].name; i++) { if(!strcmp(regshell_cmds[i].name, argv[0]) || (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) { - return regshell_cmds[i].handle(k, argc, argv); + return regshell_cmds[i].handle(mem_ctx, k, argc, argv); } } @@ -240,7 +235,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) #define MAX_COMPLETIONS 100 -static REG_KEY *current_key = NULL; +static struct registry_key *current_key = NULL; static char **reg_complete_command(const char *text, int end) { @@ -295,10 +290,11 @@ cleanup: static char **reg_complete_key(const char *text, int end) { - REG_KEY *subkey; + struct registry_key *subkey; int i, j = 0; int len; char **matches; + TALLOC_CTX *mem_ctx; /* Complete argument */ matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); @@ -306,22 +302,24 @@ static char **reg_complete_key(const char *text, int end) matches[0] = NULL; len = strlen(text); + mem_ctx = talloc_init("completion"); for(i = 0; j < MAX_COMPLETIONS-1; i++) { - WERROR status = reg_key_get_subkey_by_index(current_key, i, &subkey); + WERROR status = reg_key_get_subkey_by_index(mem_ctx, current_key, i, &subkey); if(W_ERROR_IS_OK(status)) { - if(!strncmp(text, reg_key_name(subkey), len)) { - matches[j] = strdup(reg_key_name(subkey)); + if(!strncmp(text, subkey->name, len)) { + matches[j] = strdup(subkey->name); j++; } - reg_key_free(subkey); } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) { break; } else { printf("Error creating completion list: %s\n", win_errstr(status)); + talloc_destroy(mem_ctx); return NULL; } } matches[j] = NULL; + talloc_destroy(mem_ctx); return matches; } @@ -341,10 +339,11 @@ static char **reg_completion(const char *text, int start, int end) int opt; const char *backend = "dir"; const char *credentials = NULL; - REG_KEY *curkey = NULL; + struct registry_key *curkey = NULL; poptContext pc; WERROR error; - REG_HANDLE *h; + TALLOC_CTX *mem_ctx = talloc_init("cmd"); + struct registry_context *h; struct poptOption long_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA @@ -352,13 +351,19 @@ static char **reg_completion(const char *text, int start, int end) {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL}, POPT_TABLEEND }; + + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { } - error = reg_open(backend, poptPeekArg(pc), credentials, &h); + error = reg_open(&h, backend, poptPeekArg(pc), credentials); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); return 1; @@ -367,14 +372,16 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); - error = reg_get_hive(h, 0, &curkey); - - if(!W_ERROR_IS_OK(error)) return 1; + curkey = h->hives[0]->root; while(True) { char *line, *prompt; - asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey)); + if(curkey->hive->name) { + asprintf(&prompt, "%s:%s> ", curkey->hive->name, curkey->path); + } else { + asprintf(&prompt, "%s> ", curkey->path); + } current_key = curkey; /* No way to pass a void * pointer via readline :-( */ @@ -384,10 +391,11 @@ static char **reg_completion(const char *text, int start, int end) break; if(line[0] != '\n') { - REG_KEY *new = process_cmd(curkey, line); + struct registry_key *new = process_cmd(mem_ctx, curkey, line); if(new)curkey = new; } } + talloc_destroy(mem_ctx); return 0; } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index b1ca9b3fb2..9748ca3438 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -21,39 +21,45 @@ #include "includes.h" -static void print_tree(int l, REG_KEY *p, int fullpath, int novals) +static void print_tree(int l, struct registry_key *p, int fullpath, int novals) { - REG_KEY *subkey; - REG_VAL *value; + struct registry_key *subkey; + struct registry_value *value; WERROR error; int i; + TALLOC_CTX *mem_ctx; for(i = 0; i < l; i++) putchar(' '); - if(fullpath) printf("%s\n", reg_key_get_path_abs(p)); - else printf("%s\n", reg_key_name(p)); + + /* Hive name */ + if(p->hive->root == p) printf("%s\n", p->hive->name); + else if(!p->name) printf("<No Name>\n"); + else if(fullpath) printf("%s\n", p->path); + else printf("%s\n", p->name); - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(p, i, &subkey)); i++) { + mem_ctx = talloc_init("print_tree"); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) { print_tree(l+1, subkey, fullpath, novals); - reg_key_free(subkey); } + talloc_destroy(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", p->path, win_errstr(error))); } if(!novals) { - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(p, i, &value)); i++) { + mem_ctx = talloc_init("print_tree"); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, p, i, &value)); i++) { int j; char *desc; for(j = 0; j < l+1; j++) putchar(' '); - desc = reg_val_description(value); + desc = reg_val_description(mem_ctx, value); printf("%s\n", desc); - free(desc); - reg_val_free(value); } + talloc_destroy(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching values for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error))); } } } @@ -64,8 +70,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) const char *backend = "dir"; const char *credentials = NULL; poptContext pc; - REG_KEY *root; - REG_HANDLE *h; + struct registry_context *h; WERROR error; int fullpath = 0, no_values = 0; struct poptOption long_options[] = { @@ -77,6 +82,12 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -84,7 +95,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) setup_logging("regtree", True); - error = reg_open(backend, poptPeekArg(pc), credentials, &h); + error = reg_open(&h, backend, poptPeekArg(pc), credentials); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error)); return 1; @@ -93,11 +104,8 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) error = WERR_OK; - 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); + for(i = 0; i < h->num_hives; i++) { + print_tree(0, h->hives[i]->root, fullpath, no_values); } return 0; diff --git a/source4/librpc/idl/winreg.idl b/source4/librpc/idl/winreg.idl index 812aa4e11f..46fa8d0d67 100644 --- a/source4/librpc/idl/winreg.idl +++ b/source4/librpc/idl/winreg.idl @@ -149,10 +149,9 @@ WERROR winreg_EnumValue( [in,ref] policy_handle *handle, [in] uint32 enum_index, - [in,out,ref] winreg_EnumValueName *name, + [out,ref] winreg_EnumValueName *name, [in,out] uint32 *type, [in,out] winreg_Uint8buf *value, - [in,out] uint32 *requested_len, [in,out] uint32 *returned_len ); |