summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-12-10 20:07:04 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:06:29 -0500
commit444a86792471c0bef33dde15c7a4a33e16a951b4 (patch)
tree075b0cdd27acb80470a4e90e99598cbcea3b082c
parent60c69445f6fa86b27bd697cc8af52b582f620725 (diff)
downloadsamba-444a86792471c0bef33dde15c7a4a33e16a951b4.tar.gz
samba-444a86792471c0bef33dde15c7a4a33e16a951b4.tar.bz2
samba-444a86792471c0bef33dde15c7a4a33e16a951b4.zip
r4132: - Bunch of rather large fixes in the registry
- Added some README files Not everything works yet, e.g. the EnumValue test appears to be broken. (This used to be commit c169e86c1f52763b83e77e509f89cb91f9b69071)
-rw-r--r--source4/gtk/tools/gregedit.c98
-rw-r--r--source4/include/credentials.h36
-rw-r--r--source4/include/registry.h49
-rw-r--r--source4/lib/registry/README30
-rw-r--r--source4/lib/registry/common/reg_interface.c182
-rw-r--r--source4/lib/registry/config.mk17
-rw-r--r--source4/lib/registry/reg_backend_dir.c (renamed from source4/lib/registry/reg_backend_dir/reg_backend_dir.c)8
-rw-r--r--source4/lib/registry/reg_backend_gconf.c (renamed from source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c)12
-rw-r--r--source4/lib/registry/reg_backend_ldb.c (renamed from source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c)8
-rw-r--r--source4/lib/registry/reg_backend_nt4.c (renamed from source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c)10
-rw-r--r--source4/lib/registry/reg_backend_rpc.c (renamed from source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c)141
-rw-r--r--source4/lib/registry/reg_backend_w95.c (renamed from source4/lib/registry/reg_backend_w95/reg_backend_w95.c)12
-rw-r--r--source4/lib/registry/reg_backend_wine.c (renamed from source4/lib/registry/reg_backend_wine/reg_backend_wine.c)15
-rw-r--r--source4/lib/registry/reg_samba.c62
-rw-r--r--source4/lib/registry/tools/regdiff.c76
-rw-r--r--source4/lib/registry/tools/regpatch.c25
-rw-r--r--source4/lib/registry/tools/regshell.c87
-rw-r--r--source4/lib/registry/tools/regtree.c38
-rw-r--r--source4/rpc_server/winreg/README3
-rw-r--r--source4/rpc_server/winreg/rpc_winreg.c58
-rw-r--r--source4/torture/rpc/winreg.c1
21 files changed, 551 insertions, 417 deletions
diff --git a/source4/gtk/tools/gregedit.c b/source4/gtk/tools/gregedit.c
index 31df3086f2..6301910a48 100644
--- a/source4/gtk/tools/gregedit.c
+++ b/source4/gtk/tools/gregedit.c
@@ -62,6 +62,7 @@ static GtkWidget* create_FindDialog (void)
FindDialog = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (FindDialog), "Find Key or Value");
+ gtk_window_set_resizable (GTK_WINDOW (FindDialog), FALSE);
gtk_window_set_type_hint (GTK_WINDOW (FindDialog), GDK_WINDOW_TYPE_HINT_DIALOG);
dialog_vbox2 = GTK_DIALOG (FindDialog)->vbox;
@@ -135,7 +136,6 @@ static GtkWidget* create_SetValueDialog (void)
SetValueDialog = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (SetValueDialog), "Set Registry Value");
- GTK_WINDOW (SetValueDialog)->type = GTK_WINDOW_POPUP;
gtk_window_set_position (GTK_WINDOW (SetValueDialog), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (SetValueDialog), FALSE);
gtk_window_set_type_hint (GTK_WINDOW (SetValueDialog), GDK_WINDOW_TYPE_HINT_DIALOG);
@@ -207,7 +207,6 @@ static GtkWidget* create_NewKeyDialog (void)
NewKeyDialog = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (NewKeyDialog), "New Registry Key");
- GTK_WINDOW (NewKeyDialog)->type = GTK_WINDOW_POPUP;
gtk_window_set_position (GTK_WINDOW (NewKeyDialog), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (NewKeyDialog), FALSE);
gtk_window_set_type_hint (GTK_WINDOW (NewKeyDialog), GDK_WINDOW_TYPE_HINT_DIALOG);
@@ -287,45 +286,51 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(mainwin, error);
}
+static void registry_load_hive(struct registry_key *root)
+{
+ GtkTreeIter iter, tmpiter;
+ /* Add the root */
+ gtk_tree_store_append(store_keys, &iter, NULL);
+ gtk_tree_store_set (store_keys,
+ &iter,
+ 0,
+ root->name?root->name:"",
+ 1,
+ root,
+ -1);
+
+ gtk_tree_store_append(store_keys, &tmpiter, &iter);
+
+ gtk_widget_set_sensitive( save, True );
+ gtk_widget_set_sensitive( save_as, True );
+}
+
static void registry_load_root(void)
{
struct registry_key *root;
- GtkTreeIter iter, tmpiter;
- int i = 0;
+ uint32_t i = 0;
if(!registry) return;
gtk_tree_store_clear(store_keys);
- for(i = 0; i < registry->num_hives; i++)
+ for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++)
{
- root = registry->hives[i]->root;
+ if (!W_ERROR_IS_OK(reg_get_hive(registry, i, &root))) { continue; }
- /* Add the root */
- gtk_tree_store_append(store_keys, &iter, NULL);
- gtk_tree_store_set (store_keys,
- &iter,
- 0,
- root->hive->name?root->hive->name:"",
- 1,
- root,
- -1);
-
- gtk_tree_store_append(store_keys, &tmpiter, &iter);
+ registry_load_hive(root);
}
-
- gtk_widget_set_sensitive( save, True );
- gtk_widget_set_sensitive( save_as, True );
}
static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data)
{
gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin()));
char *filename, *tmp;
+ struct registry_key *root;
WERROR error;
switch(result) {
case GTK_RESPONSE_OK:
filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin)));
- error = reg_open(&registry, user_data, filename, NULL);
+ error = reg_open_hive(NULL, user_data, filename, NULL, &root);
if(!W_ERROR_IS_OK(error)) {
gtk_show_werror(mainwin, error);
break;
@@ -334,7 +339,8 @@ static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data)
tmp = g_strdup_printf("Registry Editor - %s", filename);
gtk_window_set_title (GTK_WINDOW (mainwin), tmp);
g_free(tmp);
- registry_load_root();
+ gtk_tree_store_clear(store_keys);
+ registry_load_hive(root);
break;
default:
break;
@@ -346,7 +352,8 @@ 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(&registry, "gconf", NULL, NULL);
+ struct registry_key *root;
+ WERROR error = reg_open_hive(NULL, "gconf", NULL, NULL, &root);
if(!W_ERROR_IS_OK(error)) {
gtk_show_werror(mainwin, error);
return;
@@ -354,13 +361,12 @@ static void on_open_gconf_activate (GtkMenuItem *menui
gtk_window_set_title (GTK_WINDOW (mainwin), "Registry Editor - GConf");
- registry_load_root();
+ gtk_tree_store_clear(store_keys);
+ registry_load_hive(root);
}
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(FALSE, NULL));
gint result = gtk_dialog_run(GTK_DIALOG(rpcwin));
@@ -372,16 +378,16 @@ static void on_open_remote_activate(GtkMenuItem *menuitem, gpointer user_data)
return;
}
- location = gtk_rpc_binding_dialog_get_binding_string(GTK_RPC_BINDING_DIALOG(rpcwin), mem_ctx);
- 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(&registry, "rpc", location, credentials);
+ error = reg_open_remote(&registry,
+ gtk_rpc_binding_dialog_get_username(GTK_RPC_BINDING_DIALOG(rpcwin)),
+ gtk_rpc_binding_dialog_get_password(GTK_RPC_BINDING_DIALOG(rpcwin)),
+ gtk_rpc_binding_dialog_get_binding_string(GTK_RPC_BINDING_DIALOG(rpcwin), mem_ctx));
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);
@@ -805,14 +811,10 @@ static GtkWidget* create_savefilewin (void)
int main(int argc, char *argv[])
{
poptContext pc;
- const char *backend = NULL;
- const char *credentials = NULL;
- const char *location;
+ WERROR error;
int opt;
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
- {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%%password)", NULL},
POPT_TABLEEND
};
@@ -829,32 +831,18 @@ static GtkWidget* create_savefilewin (void)
while((opt = poptGetNextOpt(pc)) != -1) {
}
- location = poptGetArg(pc);
-
- if(location) {
- WERROR error;
-
- if(!backend) {
- if(credentials)backend = "rpc";
- else backend = "nt4";
- }
-
- error = reg_open(&registry, backend, location, credentials);
- if(!W_ERROR_IS_OK(error)) {
- gtk_show_werror(mainwin, error);
- return -1;
- }
- mainwin = create_mainwin ();
- registry_load_root();
- } else {
- mainwin = create_mainwin ();
+ error = reg_open_local(&registry);
+ if(!W_ERROR_IS_OK(error)) {
+ gtk_show_werror(mainwin, error);
+ return -1;
}
+ mainwin = create_mainwin ();
+ registry_load_root();
gtk_widget_show_all (mainwin);
gtk_main ();
- if(registry)talloc_destroy(registry->mem_ctx);
talloc_destroy(mem_ctx);
return 0;
}
diff --git a/source4/include/credentials.h b/source4/include/credentials.h
new file mode 100644
index 0000000000..99173ab421
--- /dev/null
+++ b/source4/include/credentials.h
@@ -0,0 +1,36 @@
+/*
+ samba -- Unix SMB/CIFS implementation.
+
+ Client credentials structure
+
+ Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org>
+
+ 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.
+*/
+
+struct cli_credentials {
+ /* Preferred methods, NULL means default */
+ const char **preferred_methods;
+
+ const char *username;
+ const char *password;
+ const char *domain;
+ const char *realm;
+
+ const char *(*username_cb) (void);
+ const char *(*password_cb) (void);
+ const char *(*domain_cb) (void);
+ const char *(*realm_cb) (void);
+};
diff --git a/source4/include/registry.h b/source4/include/registry.h
index a099ae1e0f..4ce9569376 100644
--- a/source4/include/registry.h
+++ b/source4/include/registry.h
@@ -22,26 +22,36 @@
#ifndef _REGISTRY_H /* _REGISTRY_H */
#define _REGISTRY_H
-#define HKEY_CLASSES_ROOT 0x80000000
-#define HKEY_CURRENT_USER 0x80000001
-#define HKEY_LOCAL_MACHINE 0x80000002
-#define HKEY_USERS 0x80000003
+
+enum hkeys {
+ HKEY_CLASSES_ROOT = 0x80000000,
+ HKEY_CURRENT_USER = 0x80000001,
+ HKEY_LOCAL_MACHINE = 0x80000002,
+ HKEY_USERS = 0x80000003,
+ HKEY_PERFORMANCE_DATA = 0x80000004,
+ HKEY_CURRENT_CONFIG = 0x80000005,
+ HKEY_DYN_DATA = 0x80000006,
+ HKEY_PT = 0x80000007, /* Don't know if this is correct! */
+ HKEY_PN = 0x80000008 /* Don't know if this is correct! */
+};
/* Registry data types */
-#define REG_DELETE -1
+#define REG_DELETE -1
#define REG_NONE 0
#define REG_SZ 1
#define REG_EXPAND_SZ 2
#define REG_BINARY 3
-#define REG_DWORD 4
-#define REG_DWORD_LE 4 /* DWORD, little endian*/
-#define REG_DWORD_BE 5 /* DWORD, big endian */
+#define REG_DWORD_LE 4
+#define REG_DWORD REG_DWORD_LE
+#define REG_DWORD_BE 5
#define REG_LINK 6
#define REG_MULTI_SZ 7
#define REG_RESOURCE_LIST 8
#define REG_FULL_RESOURCE_DESCRIPTOR 9
#define REG_RESOURCE_REQUIREMENTS_LIST 10
+#define REG_QWORD_LE 11
+#define REG_QWORD REQ_QWORD_LE
#if 0
/* FIXME */
@@ -62,7 +72,7 @@ typedef struct ace_struct_s {
/* structure to store the registry handles */
struct registry_key {
char *name; /* Name of the key */
- char *path; /* Full path to the key */
+ const char *path; /* Full path to the key */
char *class_name; /* Name of key class */
NTTIME last_mod; /* Time last modified */
SEC_DESC *security;
@@ -92,18 +102,15 @@ typedef void (*value_notification_function) (void);
*
* Backends can provide :
* - just one hive (example: nt4, w95)
- * - several hives (example: rpc)
+ * - several hives (example: rpc).
*
*/
-struct registry_operations {
+struct hive_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 **);
+ WERROR (*open_hive) (struct registry_hive *, struct registry_key **);
WERROR (*close_hive) (struct registry_hive *);
/* Or this one */
@@ -140,11 +147,8 @@ struct registry_operations {
};
struct registry_hive {
- const struct registry_operations *functions;
- char *name; /* usually something like HKEY_CURRENT_USER, etc */
+ const struct hive_operations *functions;
char *location;
- char *credentials;
- char *backend_hivename;
void *backend_data;
struct registry_key *root;
struct registry_context *reg_ctx;
@@ -153,14 +157,13 @@ struct registry_hive {
/* Handle to a full registry
* contains zero or more hives */
struct registry_context {
- TALLOC_CTX *mem_ctx;
- int num_hives;
- struct registry_hive **hives;
+ void *backend_data;
+ WERROR (*get_hive) (struct registry_context *, uint32 hkey, struct registry_key **);
};
struct reg_init_function_entry {
/* Function to create a member of the pdb_methods list */
- const struct registry_operations *functions;
+ const struct hive_operations *hive_functions;
struct reg_init_function_entry *prev, *next;
};
diff --git a/source4/lib/registry/README b/source4/lib/registry/README
new file mode 100644
index 0000000000..757029cdc2
--- /dev/null
+++ b/source4/lib/registry/README
@@ -0,0 +1,30 @@
+This is the registry library. The registry is basically a bunch of hives
+(HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc) that can be loaded from
+different places.
+
+The various registry backends provide support for loading/saving specific types
+of hives:
+ - ldb
+ - w95 (USER.DAT-style files)
+ - nt4 (NTUSER.DAT-style files)
+ - gconf (GNOME configuration)
+ - rpc (Remote individual hives)
+
+Instead of opening individual hives, one can also open a 'complete' registry by
+using one of these three functions:
+
+ - reg_open_local() - load local registry, see below
+ - reg_open_remote() - connect to remote registry over RPC
+ - reg_open_wine() (not working yet)
+
+reg_open_local() loads a set of hives based on smb.conf settings.
+Lines in smb.conf should have the following syntax:
+
+registry:<hivename> = <backend>:<location>
+
+So an example usage could be:
+
+registry:HKEY_CURRENT_USER = nt4:NTUSER.DAT
+registry:HKEY_LOCAL_MACHINE = ldb:tdb://registry.tdb
+
+WERR_NOT_SUPPORTED will be returned for all hives that haven't been set.
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index f7d3af0705..740d849db1 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -30,32 +30,25 @@ 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)
+NTSTATUS registry_register(const void *_hive_ops)
{
- const struct registry_operations *functions = _function;
+ const struct hive_operations *hive_ops = _hive_ops;
struct reg_init_function_entry *entry = backends;
- if (!functions || !functions->name) {
- DEBUG(0, ("Invalid arguments while registering registry backend\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
+ DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
/* Check for duplicates */
- if (reg_find_backend_entry(functions->name)) {
- DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
+ if (reg_find_backend_entry(hive_ops->name)) {
+ DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- entry = malloc_p(struct reg_init_function_entry);
- entry->functions = functions;
+ entry = talloc_p(NULL, struct reg_init_function_entry);
+ entry->hive_functions = hive_ops;
DLIST_ADD(backends, entry);
- DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
+ DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
return NT_STATUS_OK;
}
@@ -67,7 +60,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
entry = backends;
while(entry) {
- if (strcmp(entry->functions->name, name) == 0) return entry;
+ if (strcmp(entry->hive_functions->name, name) == 0) return entry;
entry = entry->next;
}
@@ -80,85 +73,83 @@ BOOL reg_has_backend(const char *backend)
return reg_find_backend_entry(backend) != NULL?True:False;
}
-WERROR reg_create(struct registry_context **_ret)
+static struct {
+ uint32 hkey;
+ const char *name;
+} hkey_names[] =
{
- TALLOC_CTX *mem_ctx;
- struct registry_context *ret;
- mem_ctx = talloc_init("registry handle");
- ret = talloc_p(mem_ctx, 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)
+ {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
+ {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
+ {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
+ {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
+ {HKEY_USERS, "HKEY_USERS" },
+ {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
+ {HKEY_DYN_DATA, "HKEY_DYN_DATA" },
+ {HKEY_PT, "HKEY_PT" },
+ {HKEY_PN, "HKEY_PN" },
+ { 0, NULL }
+};
+
+int reg_list_hives(TALLOC_CTX *mem_ctx, char ***hives, uint32_t **hkeys)
{
- 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;
- }
+ int i;
+ *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names));
+ *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(hkey_names));
- if(!entry->functions->list_available_hives) {
- return WERR_NOT_SUPPORTED;
+ for (i = 0; hkey_names[i].name; i++) {
+ (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name);
+ (*hkeys)[i] = hkey_names[i].hkey;
}
- return entry->functions->list_available_hives(mem_ctx, location, credentials, hives);
+ return i;
}
-WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials)
+const char *reg_get_hkey_name(uint32_t hkey)
{
- WERROR error = reg_create(ret), reterror = WERR_NO_MORE_ITEMS;
- char **hives;
- int i, j;
- 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);
+ int i;
+ for (i = 0; hkey_names[i].name; i++) {
+ if (hkey_names[i].hkey == hkey) return hkey_names[i].name;
}
-
- if(!W_ERROR_IS_OK(error)) return error;
- j = 0;
- for(i = 0; hives[i]; i++)
- {
- error = reg_import_hive(*ret, backend, location, credentials, hives[i]);
- if (W_ERROR_IS_OK(error)) {
- reterror = WERR_OK;
- (*ret)->hives[j]->name = talloc_strdup((*ret)->mem_ctx, hives[i]);
- j++;
- } else if (!W_ERROR_IS_OK(reterror)) reterror = error;
+ return NULL;
+}
+
+WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
+{
+ int i;
+
+ for (i = 0; hkey_names[i].name; i++) {
+ if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].hkey, key);
}
- return reterror;
+ DEBUG(1, ("No hive with name '%s'\n", name));
+
+ return WERR_BADFILE;
}
WERROR reg_close (struct registry_context *ctx)
{
- int i;
- for (i = 0; i < ctx->num_hives; i++) {
- if (ctx->hives[i]->functions->close_hive) {
- ctx->hives[i]->functions->close_hive(ctx->hives[i]);
- }
- }
talloc_destroy(ctx);
return WERR_OK;
}
+WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
+{
+ WERROR ret = ctx->get_hive(ctx, hkey, key);
+
+ if (W_ERROR_IS_OK(ret)) {
+ (*key)->name = talloc_strdup(*key, reg_get_hkey_name(hkey));
+ (*key)->path = "";
+ }
+
+ return ret;
+}
+
/* 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)
+WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root)
{
struct registry_hive *ret;
- TALLOC_CTX *mem_ctx;
struct reg_init_function_entry *entry;
WERROR werr;
@@ -169,24 +160,21 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch
return WERR_GENERAL_FAILURE;
}
- if(!entry->functions->open_hive) {
+ if(!entry->hive_functions || !entry->hive_functions->open_hive) {
return WERR_NOT_SUPPORTED;
}
-
- 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 = talloc_p(parent_ctx, struct registry_hive);
+ ret->location = location?talloc_strdup(ret, location):NULL;
+ ret->functions = entry->hive_functions;
ret->backend_data = NULL;
- ret->reg_ctx = h;
- ret->name = NULL;
+ ret->reg_ctx = parent_ctx;
- werr = entry->functions->open_hive(mem_ctx, ret, &ret->root);
+ werr = entry->hive_functions->open_hive(ret, &ret->root);
- if(!W_ERROR_IS_OK(werr)) return werr;
+ if(!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
if(!ret->root) {
DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
@@ -195,12 +183,9 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch
ret->root->hive = ret;
ret->root->name = NULL;
- ret->root->path = talloc_strdup(mem_ctx, "");
-
- /* Add hive to context */
- h->num_hives++;
- h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives);
- h->hives[h->num_hives-1] = ret;
+ ret->root->path = talloc_strdup(ret, "");
+
+ *root = ret->root;
return WERR_OK;
}
@@ -217,7 +202,7 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co
else hivelength = strlen(name);
hivename = strndup(name, hivelength);
- error = reg_get_hive(handle, hivename, &hive);
+ error = reg_get_hive_by_name(handle, hivename, &hive);
SAFE_FREE(hivename);
if(!W_ERROR_IS_OK(error)) {
@@ -272,7 +257,8 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char
return WERR_NOT_SUPPORTED;
}
- fullname = reg_make_path(mem_ctx, parent, name);
+
+ fullname = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result);
@@ -499,7 +485,7 @@ WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const cha
else hivelength = strlen(name);
hivename = strndup(name, hivelength);
- error = reg_get_hive(handle, hivename, &hive);
+ error = reg_get_hive_by_name(handle, hivename, &hive);
SAFE_FREE(hivename);
if(!W_ERROR_IS_OK(error)) return error;
@@ -578,19 +564,7 @@ WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *
return WERR_NOT_SUPPORTED;
}
-WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key)
-{
- 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;
- }
- }
- return WERR_NO_MORE_ITEMS;
-}
WERROR reg_del_value(struct registry_value *val)
{
diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk
index b91ec647a0..af9fb83bab 100644
--- a/source4/lib/registry/config.mk
+++ b/source4/lib/registry/config.mk
@@ -6,7 +6,7 @@
INIT_FUNCTION = registry_nt4_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_nt4/reg_backend_nt4.o
+ lib/registry/reg_backend_nt4.o
# End MODULE registry_nt4
################################################
@@ -16,7 +16,7 @@ INIT_OBJ_FILES = \
INIT_FUNCTION = registry_w95_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_w95/reg_backend_w95.o
+ lib/registry/reg_backend_w95.o
# End MODULE registry_w95
################################################
@@ -26,7 +26,7 @@ INIT_OBJ_FILES = \
INIT_FUNCTION = registry_dir_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_dir/reg_backend_dir.o
+ lib/registry/reg_backend_dir.o
# End MODULE registry_dir
################################################
@@ -36,18 +36,20 @@ INIT_OBJ_FILES = \
INIT_FUNCTION = registry_rpc_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_rpc/reg_backend_rpc.o
+ lib/registry/reg_backend_rpc.o
REQUIRED_SUBSYSTEMS = RPC_NDR_WINREG
# End MODULE registry_rpc
################################################
+
+
################################################
# Start MODULE registry_gconf
[MODULE::registry_gconf]
INIT_FUNCTION = registry_gconf_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_gconf/reg_backend_gconf.o
+ lib/registry/reg_backend_gconf.o
REQUIRED_SUBSYSTEMS = EXT_LIB_gconf
# End MODULE registry_gconf
################################################
@@ -58,7 +60,7 @@ REQUIRED_SUBSYSTEMS = EXT_LIB_gconf
INIT_FUNCTION = registry_ldb_init
SUBSYSTEM = REGISTRY
INIT_OBJ_FILES = \
- lib/registry/reg_backend_ldb/reg_backend_ldb.o
+ lib/registry/reg_backend_ldb.o
REQUIRED_SUBSYSTEMS = \
LIBLDB
# End MODULE registry_ldb
@@ -70,7 +72,8 @@ REQUIRED_SUBSYSTEMS = \
INIT_OBJ_FILES = \
lib/registry/common/reg_interface.o
ADD_OBJ_FILES = \
- lib/registry/common/reg_util.o
+ lib/registry/common/reg_util.o \
+ lib/registry/reg_samba.o
REQUIRED_SUBSYSTEMS = \
LIBBASIC
# End MODULE registry_ldb
diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c
index 8712e7ce7c..5c3ed3c44c 100644
--- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
+++ b/source4/lib/registry/reg_backend_dir.c
@@ -110,12 +110,12 @@ static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k,
return WERR_NO_MORE_ITEMS;
}
-static WERROR reg_dir_open(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key)
+static WERROR reg_dir_open(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);
+ *key = talloc_p(h, struct registry_key);
+ (*key)->backend_data = talloc_strdup(*key, h->location);
return WERR_OK;
}
@@ -131,7 +131,7 @@ static WERROR reg_dir_del_value(struct registry_value *v)
return WERR_NOT_SUPPORTED;
}
-static struct registry_operations reg_backend_dir = {
+static struct hive_operations reg_backend_dir = {
.name = "dir",
.open_hive = reg_dir_open,
.open_key = reg_dir_open_key,
diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c
index fd258ca285..2fed2417b7 100644
--- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c
+++ b/source4/lib/registry/reg_backend_gconf.c
@@ -29,16 +29,16 @@ static WERROR gerror_to_werror(GError *error)
return WERR_FOOBAR;
}
-static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k)
+static WERROR reg_open_gconf_hive(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 = talloc_strdup(mem_ctx, "");
- (*k)->path = talloc_strdup(mem_ctx, "");
- (*k)->backend_data = talloc_strdup(mem_ctx, "/");
+ *k = talloc_p(h, struct registry_key);
+ (*k)->name = talloc_strdup(*k, "");
+ (*k)->path = talloc_strdup(*k, "");
+ (*k)->backend_data = talloc_strdup(*k, "/");
return WERR_OK;
}
@@ -173,7 +173,7 @@ static WERROR gconf_set_value(struct registry_key *key, const char *valname, int
return WERR_NOT_SUPPORTED;
}
-static struct registry_operations reg_backend_gconf = {
+static struct hive_operations reg_backend_gconf = {
.name = "gconf",
.open_hive = reg_open_gconf_hive,
.open_key = gconf_open_key,
diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c
index 380a8010f2..7eaf6194a5 100644
--- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c
+++ b/source4/lib/registry/reg_backend_ldb.c
@@ -137,7 +137,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c
return WERR_OK;
}
-static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k)
+static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k)
{
struct ldb_context *c;
@@ -151,8 +151,8 @@ static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, str
ldb_set_debug_stderr(c);
hive->backend_data = c;
- hive->root = talloc_zero_p(mem_ctx, struct registry_key);
- hive->root->name = talloc_strdup(mem_ctx, "");
+ hive->root = talloc_zero_p(hive, struct registry_key);
+ hive->root->name = talloc_strdup(hive->root, "");
return WERR_OK;
}
@@ -202,7 +202,7 @@ static WERROR ldb_close_hive (struct registry_hive *hive)
return WERR_OK;
}
-static struct registry_operations reg_backend_ldb = {
+static struct hive_operations reg_backend_ldb = {
.name = "ldb",
.add_key = ldb_add_key,
.del_key = ldb_del_key,
diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c
index 381f0c3bcf..117d8d1b81 100644
--- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c
+++ b/source4/lib/registry/reg_backend_nt4.c
@@ -1573,16 +1573,16 @@ error:
#endif
-static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key)
+static WERROR nt_open_hive (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(mem_ctx, REGF);
+ regf = (REGF *)talloc_p(h, REGF);
memset(regf, 0, sizeof(REGF));
- regf->owner_sid_str = h->credentials;
+ regf->owner_sid_str = NULL; /* FIXME: Fill in */
h->backend_data = regf;
DEBUG(5, ("Attempting to load registry file\n"));
@@ -1655,7 +1655,7 @@ static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct
h->backend_data = regf;
- return nk_to_key(mem_ctx, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key);
+ return nk_to_key(h, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key);
}
@@ -1724,7 +1724,7 @@ static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n
return WERR_NO_MORE_ITEMS;
}
-static struct registry_operations reg_backend_nt4 = {
+static struct hive_operations reg_backend_nt4 = {
.name = "nt4",
.open_hive = nt_open_hive,
.num_subkeys = nt_num_subkeys,
diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c
index 3969a763e0..18563b2478 100644
--- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc.c
@@ -21,6 +21,8 @@
#include "registry.h"
#include "librpc/gen_ndr/ndr_winreg.h"
+static struct hive_operations reg_backend_rpc;
+
/**
* This is the RPC backend for the registry library.
*/
@@ -76,93 +78,56 @@ struct rpc_key_data {
};
struct {
- const char *name;
+ uint32 hkey;
WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h);
} known_hives[] = {
-{ "HKEY_LOCAL_MACHINE", open_HKLM },
-{ "HKEY_CURRENT_USER", open_HKCU },
-{ "HKEY_CLASSES_ROOT", open_HKCR },
-{ "HKEY_PERFORMANCE_DATA", open_HKPD },
-{ "HKEY_USERS", open_HKU },
-{ "HKEY_DYN_DATA", open_HKDD },
-{ "HKEY_CURRENT_CONFIG", open_HKCC },
-{ NULL, NULL }
+{ HKEY_LOCAL_MACHINE, open_HKLM },
+{ HKEY_CURRENT_USER, open_HKCU },
+{ HKEY_CLASSES_ROOT, open_HKCR },
+{ HKEY_PERFORMANCE_DATA, open_HKPD },
+{ HKEY_USERS, open_HKU },
+{ HKEY_DYN_DATA, open_HKDD },
+{ HKEY_CURRENT_CONFIG, open_HKCC },
+{ 0, NULL }
};
static WERROR rpc_query_key(struct registry_key *k);
-static 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(mem_ctx, *hives, char *, i+2);
- (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name);
- }
- (*hives)[i] = NULL;
- return WERR_OK;
-}
-
-static WERROR rpc_close_hive (struct registry_hive *h)
+static WERROR rpc_get_hive (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k)
{
- dcerpc_pipe_close(h->backend_data);
- return WERR_OK;
-}
-
-static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k)
-{
- NTSTATUS status;
- char *user;
- char *pass;
- struct rpc_key_data *mykeydata;
- struct dcerpc_pipe *p;
int n;
+ struct registry_hive *h;
+ struct rpc_key_data *mykeydata;
- if (!h->credentials) return WERR_INVALID_PARAM;
-
- /* Default to local smbd if no connection is specified */
- if (!h->location) {
- h->location = talloc_strdup(mem_ctx, "ncalrpc:");
- }
-
- user = talloc_strdup(mem_ctx, h->credentials);
- pass = strchr(user, '%');
- if (pass) {
- *pass = '\0';
- pass = strdup(pass+1);
- } else {
- pass = strdup("");
- }
-
- status = dcerpc_pipe_connect(&p, h->location,
- DCERPC_WINREG_UUID,
- DCERPC_WINREG_VERSION,
- lp_workgroup(),
- user, pass);
- free(pass);
-
- h->backend_data = p;
-
- if(NT_STATUS_IS_ERR(status)) {
- DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status)));
- return ntstatus_to_werror(status);
- }
-
- for(n = 0; known_hives[n].name; n++)
+ for(n = 0; known_hives[n].hkey; n++)
{
- if(!strcmp(known_hives[n].name, h->backend_hivename)) break;
+ if(known_hives[n].hkey == hkey_type) break;
}
- if(!known_hives[n].name) {
- DEBUG(1, ("No such hive %s\n", known_hives[n].name));
+ if(!known_hives[n].open) {
+ DEBUG(1, ("No such hive %d\n", hkey_type));
return WERR_NO_MORE_ITEMS;
}
+
+ h = talloc_p(ctx, struct registry_hive);
+ h->functions = &reg_backend_rpc;
+ h->location = NULL;
+ h->backend_data = ctx->backend_data;
+ h->reg_ctx = ctx;
- *k = talloc_p(mem_ctx, struct registry_key);
- (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data);
+ (*k) = h->root = talloc_p(h, struct registry_key);
+ (*k)->hive = h;
+ (*k)->backend_data = mykeydata = talloc_p(*k, struct rpc_key_data);
mykeydata->num_values = -1;
mykeydata->num_subkeys = -1;
- return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol));
+ return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol));
+}
+
+static int rpc_close (void *_h)
+{
+ struct registry_context *h = _h;
+ dcerpc_pipe_close(h->backend_data);
+ return 0;
}
#if 0
@@ -385,10 +350,8 @@ static WERROR rpc_num_subkeys(struct registry_key *key, int *count) {
return WERR_OK;
}
-static struct registry_operations reg_backend_rpc = {
+static struct hive_operations reg_backend_rpc = {
.name = "rpc",
- .open_hive = rpc_open_hive,
- .close_hive = rpc_close_hive,
.open_key = rpc_open_key,
.get_subkey_by_index = rpc_get_subkey_by_index,
.get_value_by_index = rpc_get_value_by_index,
@@ -396,9 +359,39 @@ static struct registry_operations reg_backend_rpc = {
.del_key = rpc_del_key,
.num_subkeys = rpc_num_subkeys,
.num_values = rpc_num_values,
- .list_available_hives = rpc_list_hives,
};
+WERROR reg_open_remote (struct registry_context **ctx, const char *user, const char *pass, const char *location)
+{
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+
+ *ctx = talloc_p(NULL, struct registry_context);
+
+ /* Default to local smbd if no connection is specified */
+ if (!location) {
+ location = talloc_strdup(ctx, "ncalrpc:");
+ }
+
+ status = dcerpc_pipe_connect(&p, location,
+ DCERPC_WINREG_UUID,
+ DCERPC_WINREG_VERSION,
+ lp_workgroup(),
+ user, pass);
+ (*ctx)->backend_data = p;
+
+ if(NT_STATUS_IS_ERR(status)) {
+ DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status)));
+ return ntstatus_to_werror(status);
+ }
+
+ (*ctx)->get_hive = rpc_get_hive;
+
+ talloc_set_destructor(*ctx, rpc_close);
+
+ return WERR_OK;
+}
+
NTSTATUS registry_rpc_init(void)
{
return registry_register(&reg_backend_rpc);
diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c
index 445d13a99c..a94ad86c2c 100644
--- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c
+++ b/source4/lib/registry/reg_backend_w95.c
@@ -180,14 +180,14 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr)
}
}
-static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **root)
+static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root)
{
CREG *creg;
DWORD creg_id, rgkn_id;
DWORD i;
DWORD offset;
- creg = talloc_p(mem_ctx, CREG);
+ creg = talloc_p(h, CREG);
memset(creg, 0, sizeof(CREG));
h->backend_data = creg;
@@ -234,7 +234,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct
}
#endif
- creg->rgdb_keys = talloc_array_p(mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb);
+ creg->rgdb_keys = talloc_array_p(h, RGDB_KEY **, creg->creg_hdr->num_rgdb);
offset = 0;
DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb));
@@ -250,7 +250,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct
}
- creg->rgdb_keys[i] = talloc_array_p(mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1);
+ creg->rgdb_keys[i] = talloc_array_p(h, 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);
@@ -259,7 +259,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct
}
/* First element in rgkn should be root key */
- *root = talloc_p(mem_ctx, struct registry_key);
+ *root = talloc_p(h, struct registry_key);
(*root)->name = NULL;
(*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR));
@@ -342,7 +342,7 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i
return WERR_OK;
}
-static struct registry_operations reg_backend_w95 = {
+static struct hive_operations reg_backend_w95 = {
.name = "w95",
.open_hive = w95_open_reg,
.get_value_by_index = w95_get_value_by_id,
diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine.c
index 249af27e13..8a3458b52c 100644
--- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c
+++ b/source4/lib/registry/reg_backend_wine.c
@@ -22,8 +22,17 @@
#include "lib/registry/common/registry.h"
#include "windows/registry.h"
+static WERROR wine_open_reg (struct registry_hive *h, struct registry_key **key)
+{
+ /* FIXME: Open h->location and mmap it */
+}
+
+
+
static REG_OPS reg_backend_wine = {
.name = "wine",
+ .open_hive = wine_open_reg,
+
};
NTSTATUS registry_wine_init(void)
@@ -31,3 +40,9 @@ NTSTATUS registry_wine_init(void)
register_backend("registry", &reg_backend_wine);
return NT_STATUS_OK;
}
+
+WERROR reg_open_wine(struct registry_key **ctx)
+{
+ /* FIXME: Open ~/.wine/system.reg, etc */
+ return WERR_NOT_SUPPORTED;
+}
diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c
new file mode 100644
index 0000000000..a19029524d
--- /dev/null
+++ b/source4/lib/registry/reg_samba.c
@@ -0,0 +1,62 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Jelmer Vernooij 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.
+*/
+
+#include "includes.h"
+#include "registry.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, struct registry_key **k)
+{
+ WERROR error;
+ const char *conf;
+ char *backend, *location;
+ const char *hivename = reg_get_hkey_name(hkey);
+
+ *k = NULL;
+
+ conf = lp_parm_string(-1, "registry", hivename);
+
+ if (!conf) {
+ return WERR_NOT_SUPPORTED;
+ }
+
+ backend = talloc_strdup(NULL, conf);
+ location = strchr(backend, ':');
+
+ if (location) {
+ *location = '\0';
+ location++;
+ }
+
+ error = reg_open_hive(ctx, backend, location, NULL, k);
+
+ talloc_destroy(backend);
+
+ return error;
+}
+
+WERROR reg_open_local (struct registry_context **ctx)
+{
+ *ctx = talloc_p(NULL, struct registry_context);
+ (*ctx)->get_hive = reg_samba_get_hive;
+
+ return WERR_OK;
+}
diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c
index 55c8f1e72f..fc2954b6af 100644
--- a/source4/lib/registry/tools/regdiff.c
+++ b/source4/lib/registry/tools/regdiff.c
@@ -113,21 +113,19 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey,
{
int opt;
poptContext pc;
- const char *backend1 = NULL, *backend2 = NULL;
- const char *location2;
- const char *credentials1= NULL, *credentials2 = NULL;
char *outputfile = NULL;
FILE *fd = stdout;
- struct registry_context *h1 = NULL, *h2;
+ struct registry_context *h1 = NULL, *h2 = NULL;
int from_null = 0;
int i;
WERROR error, error2;
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL},
- {"credentials", 'c', POPT_ARG_STRING, NULL, 'c', "credentials", NULL},
+ POPT_COMMON_CREDENTIALS
{"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL },
- {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" },
+ {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL", NULL },
+ {"remote", 'R', POPT_ARG_STRING, NULL, 0, "Connect to remote server" , NULL },
+ {"local", 'L', POPT_ARG_NONE, NULL, 0, "Open local registry", NULL },
POPT_TABLEEND
};
@@ -141,49 +139,24 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey,
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
while((opt = poptGetNextOpt(pc)) != -1) {
+ error = WERR_OK;
switch(opt) {
- case 'c':
- if(!credentials1 && !from_null) credentials1 = poptGetOptArg(pc);
- else if(!credentials2) credentials2 = poptGetOptArg(pc);
+ case 'L':
+ if (!h1 && !from_null) error = reg_open_local(&h1);
+ else if (!h2) error = reg_open_local(&h2);
break;
- case 'b':
- if(!backend1 && !from_null) backend1 = poptGetOptArg(pc);
- else if(!backend2) backend2 = poptGetOptArg(pc);
+ case 'R':
+ if (!h1 && !from_null) error = reg_open_remote(&h1, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc));
+ else if (!h2) error = reg_open_remote(&h2, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc));
break;
}
- }
- setup_logging(argv[0], True);
- if(!from_null) {
- const char *location1;
- location1 = poptGetArg(pc);
- if(!location1) {
- poptPrintUsage(pc, stderr, 0);
+ if (!W_ERROR_IS_OK(error)) {
+ fprintf(stderr, "Error: %s\n", win_errstr(error));
return 1;
}
-
- if(!backend1) backend1 = "rpc";
-
- 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;
- }
- }
-
- location2 = poptGetArg(pc);
- if(!location2) {
- poptPrintUsage(pc, stderr, 0);
- return 2;
- }
-
- if(!backend2) backend2 = "rpc";
-
- 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;
}
+ setup_logging(argv[0], True);
poptFreeContext(pc);
@@ -196,12 +169,25 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey,
}
fprintf(fd, "REGEDIT4\n\n");
- fprintf(fd, "; Generated using regdiff\n");
+ fprintf(fd, "; Generated using regdiff, part of Samba\n");
error2 = error = WERR_OK;
- for(i = 0; (!h1 || i < h1->num_hives) && i < h2->num_hives; i++) {
- writediff(h1?h1->hives[i]->root:NULL, h2->hives[i]->root, fd);
+ for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++) {
+ struct registry_key *r1, *r2;
+ error = reg_get_hive(h1, i, &r1);
+ if (!W_ERROR_IS_OK(error)) {
+ DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_hkey_name(i)));
+ continue;
+ }
+
+ error = reg_get_hive(h2, i, &r2);
+ if (!W_ERROR_IS_OK(error)) {
+ DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_hkey_name(i)));
+ continue;
+ }
+
+ writediff(r1, r2, fd);
}
fclose(fd);
diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c
index be60b96019..a4a4649c96 100644
--- a/source4/lib/registry/tools/regpatch.c
+++ b/source4/lib/registry/tools/regpatch.c
@@ -758,16 +758,14 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
{
int opt;
poptContext pc;
- const char *location;
- const char *credentials = NULL;
const char *patch;
- const char *backend = "rpc";
struct registry_context *h;
+ const char *remote = NULL;
WERROR error;
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL},
- {"credentials", 'c', POPT_ARG_STRING, &credentials, 'c', "credentials (user%password", NULL},
+ POPT_COMMON_CREDENTIALS
+ {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
POPT_TABLEEND
};
@@ -785,25 +783,22 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
setup_logging(argv[0], True);
- location = poptGetArg(pc);
- if(!location) {
- poptPrintUsage(pc, stderr, 0);
- return 1;
+ if (remote) {
+ error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote);
+ } else {
+ error = reg_open_local (&h);
}
- error = reg_open(&h, backend, location, credentials);
- if(!h) {
- fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend);
+ if (W_ERROR_IS_OK(error)) {
+ fprintf(stderr, "Error: %s\n", win_errstr(error));
return 1;
}
-
+
patch = poptGetArg(pc);
if(!patch) patch = "/dev/stdin";
poptFreeContext(pc);
nt_apply_reg_command_file(h, patch);
- talloc_destroy(h->mem_ctx);
-
return 0;
}
diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c
index f18b012720..3fd9dab268 100644
--- a/source4/lib/registry/tools/regshell.c
+++ b/source4/lib/registry/tools/regshell.c
@@ -164,15 +164,23 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *
static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
{
- int i;
- for(i = 0; i < cur->hive->reg_ctx->num_hives; i++) {
+ if (!cur->hive->reg_ctx) {
+ fprintf(stderr, "Only one hive loaded\n");
+ return cur;
+ }
- if(argc == 1) {
- 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;
- }
+ if (argc == 1) {
+ printf("%s\n", cur->hive->root->name);
+ } else {
+ struct registry_key *newroot;
+ WERROR error = reg_get_hive_by_name(cur->hive->reg_ctx, argv[1], &newroot);
+ if (W_ERROR_IS_OK(error)) {
+ return newroot;
+ } else {
+ fprintf(stderr, "Can't switch to hive %s: %s\n", cur->hive->root->name, win_errstr(error));
+ }
}
+
return NULL;
}
@@ -274,11 +282,7 @@ static char **reg_complete_command(const char *text, int end)
matches[0] = strdup(matches[1]);
break;
default:
- matches[0] = malloc(samelen+1);
- if (!matches[0])
- goto cleanup;
- strncpy(matches[0], matches[1], samelen);
- matches[0][samelen] = 0;
+ matches[0] = strndup(matches[1], samelen);
}
matches[count] = NULL;
return matches;
@@ -295,11 +299,11 @@ cleanup:
static char **reg_complete_key(const char *text, int end)
{
struct registry_key *subkey;
- int i, j = 0;
+ int i, j = 1;
+ int samelen = 0;
int len;
char **matches;
TALLOC_CTX *mem_ctx;
- /* Complete argument */
matches = malloc_array_p(char *, MAX_COMPLETIONS);
if (!matches) return NULL;
@@ -313,6 +317,12 @@ static char **reg_complete_key(const char *text, int end)
if(!strncmp(text, subkey->name, len)) {
matches[j] = strdup(subkey->name);
j++;
+
+ if (j == 1)
+ samelen = strlen(matches[j]);
+ else
+ while (strncmp(matches[j], matches[j-1], samelen) != 0)
+ samelen--;
}
} else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) {
break;
@@ -322,8 +332,20 @@ static char **reg_complete_key(const char *text, int end)
return NULL;
}
}
- matches[j] = NULL;
talloc_destroy(mem_ctx);
+
+ if (j == 1) { /* No matches at all */
+ SAFE_FREE(matches);
+ return NULL;
+ }
+
+ if (j == 2) { /* Exact match */
+ matches[0] = strdup(matches[1]);
+ } else {
+ matches[0] = strndup(matches[1], samelen);
+ }
+
+ matches[j] = NULL;
return matches;
}
@@ -341,18 +363,18 @@ static char **reg_completion(const char *text, int start, int end)
int main(int argc, char **argv)
{
int opt;
- const char *backend = "rpc";
- const char *credentials = NULL;
+ const char *backend = NULL;
struct registry_key *curkey = NULL;
poptContext pc;
WERROR error;
TALLOC_CTX *mem_ctx = talloc_init("cmd");
- struct registry_context *h;
+ const char *remote = NULL;
+ struct registry_context *h = NULL;
struct poptOption long_options[] = {
POPT_AUTOHELP
- POPT_COMMON_SAMBA
+ POPT_COMMON_CREDENTIALS
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
- {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL},
+ {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
POPT_TABLEEND
};
@@ -370,20 +392,31 @@ static char **reg_completion(const char *text, int start, int end)
setup_logging("regtree", True);
- error = reg_open(&h, backend, poptPeekArg(pc), credentials);
+ if (remote) {
+ error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote);
+ } else if (backend) {
+ error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey);
+ } else {
+ error = reg_open_local(&h);
+ }
+
if(!W_ERROR_IS_OK(error)) {
- fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend);
+ fprintf(stderr, "Unable to open registry\n");
return 1;
}
- poptFreeContext(pc);
-
- curkey = h->hives[0]->root;
+ if (h) {
+ /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */
+ reg_get_hive(h, HKEY_CLASSES_ROOT, &curkey);
+ }
+
+ poptFreeContext(pc);
+
while(True) {
char *line, *prompt;
- if(curkey->hive->name) {
- asprintf(&prompt, "%s:%s> ", curkey->hive->name, curkey->path);
+ if(curkey->hive->root->name) {
+ asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path);
} else {
asprintf(&prompt, "%s> ", curkey->path);
}
diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c
index ced7a00f94..8ff68229eb 100644
--- a/source4/lib/registry/tools/regtree.c
+++ b/source4/lib/registry/tools/regtree.c
@@ -36,7 +36,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
/* Hive name */
if(p->hive->root == p) {
- if(p->hive->name) printf("%s\n", p->hive->name); else printf("<No Name>\n");
+ if(p->hive->root->name) printf("%s\n", p->hive->root->name); else printf("<No Name>\n");
} else {
if(!p->name) printf("<No Name>\n");
if(fullpath) printf("%s\n", p->path);
@@ -73,17 +73,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
int main(int argc, char **argv)
{
int opt, i;
- const char *backend = "rpc";
- const char *credentials = NULL;
+ const char *backend = NULL;
+ const char *remote = NULL;
poptContext pc;
- struct registry_context *h;
+ struct registry_context *h = NULL;
+ struct registry_key *root = NULL;
WERROR error;
int fullpath = 0, no_values = 0;
struct poptOption long_options[] = {
POPT_AUTOHELP
+ POPT_COMMON_CREDENTIALS
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
{"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL},
- {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%password)", NULL},
+ {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL },
{"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL},
POPT_TABLEEND
};
@@ -102,7 +104,14 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
setup_logging("regtree", True);
- error = reg_open(&h, backend, poptPeekArg(pc), credentials);
+ if (remote) {
+ error = reg_open_remote(&h, cmdline_get_username(), cmdline_get_userpassword(), remote);
+ } else if (backend) {
+ error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root);
+ } else {
+ error = reg_open_local (&h);
+ }
+
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;
@@ -110,10 +119,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
poptFreeContext(pc);
error = WERR_OK;
-
- for(i = 0; i < h->num_hives; i++) {
- print_tree(0, h->hives[i]->root, fullpath, no_values);
- }
+ if (!h) {
+ print_tree(0, root, fullpath, no_values);
+ } else {
+ for(i = HKEY_CLASSES_ROOT; i < HKEY_PN; i++) {
+ error = reg_get_hive(h, i, &root);
+ if (!W_ERROR_IS_OK(error)) {
+ fprintf(stderr, "Skipping %s\n", reg_get_hkey_name(i));
+ continue;
+ }
+ print_tree(0, root, fullpath, no_values);
+ }
+ }
+
return 0;
}
diff --git a/source4/rpc_server/winreg/README b/source4/rpc_server/winreg/README
new file mode 100644
index 0000000000..7563843253
--- /dev/null
+++ b/source4/rpc_server/winreg/README
@@ -0,0 +1,3 @@
+This is the RPC server for the registry for Samba. It is basically
+a front-end for the registry library in lib/registry. See lib/registry/README for
+more details.
diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c
index 3e9341b122..dfe3be5d8a 100644
--- a/source4/rpc_server/winreg/rpc_winreg.c
+++ b/source4/rpc_server/winreg/rpc_winreg.c
@@ -28,40 +28,34 @@
enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
-static void winreg_destroy_hive(struct dcesrv_connection *c, struct dcesrv_handle *h)
+static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
{
- reg_close(((struct registry_key *)h->data)->hive->reg_ctx);
+ struct registry_context *ctx;
+ reg_open_local(&ctx);
+
+ dce_call->conn->private = ctx;
+
+ return NT_STATUS_OK;
}
-static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *hivename, struct policy_handle **outh)
+#define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
+
+static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t hkey, struct policy_handle **outh)
{
- struct registry_context *ctx;
+ struct registry_context *ctx = dce_call->conn->private;
struct dcesrv_handle *h;
WERROR error;
- const char *conf = lp_parm_string(-1, "registry", hivename);
- char *backend, *location;
-
- if (!conf) {
- return WERR_NOT_SUPPORTED;
- }
- backend = talloc_strdup(mem_ctx, conf);
- location = strchr(backend, ':');
+ h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY);
- if (location) {
- *location = '\0';
- location++;
+ error = reg_get_hive(ctx, hkey, (struct registry_key **)&h->data);
+ if (!W_ERROR_IS_OK(error)) {
+ return error;
}
-
- error = reg_open(&ctx, backend, location, NULL);
- if(!W_ERROR_IS_OK(error)) return error;
- h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY);
- h->data = ctx->hives[0]->root;
- SMB_ASSERT(h->data);
- h->destroy = winreg_destroy_hive;
*outh = &h->wire_handle;
- return WERR_OK;
+
+ return error;
}
#define func_winreg_OpenHive(k,n) static WERROR winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
@@ -69,15 +63,15 @@ static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *m
return winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
}
-func_winreg_OpenHive(HKCR,"HKEY_CLASSES_ROOT")
-func_winreg_OpenHive(HKCU,"HKEY_CURRENT_USER")
-func_winreg_OpenHive(HKLM,"HKEY_LOCAL_MACHINE")
-func_winreg_OpenHive(HKPD,"HKEY_PERFORMANCE_DATA")
-func_winreg_OpenHive(HKU,"HKEY_USERS")
-func_winreg_OpenHive(HKCC,"HKEY_CURRENT_CONFIG")
-func_winreg_OpenHive(HKDD,"HKEY_DYN_DATA")
-func_winreg_OpenHive(HKPT,"HKEY_PT")
-func_winreg_OpenHive(HKPN,"HKEY_PN")
+func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
+func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
+func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
+func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
+func_winreg_OpenHive(HKU,HKEY_USERS)
+func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
+func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
+func_winreg_OpenHive(HKPT,HKEY_PT)
+func_winreg_OpenHive(HKPN,HKEY_PN)
/*
winreg_CloseKey
diff --git a/source4/torture/rpc/winreg.c b/source4/torture/rpc/winreg.c
index 6f44034273..d500a89435 100644
--- a/source4/torture/rpc/winreg.c
+++ b/source4/torture/rpc/winreg.c
@@ -451,6 +451,7 @@ static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
struct winreg_InitiateSystemShutdown r;
NTSTATUS status;
+ init_winreg_String(&r.in.hostname, NULL);
init_winreg_String(&r.in.message, msg);
r.in.flags = 0;
r.in.timeout = timeout;