mirror of
https://github.com/samba-team/samba.git
synced 2025-10-31 12:23:52 +03:00
r10604: Put in the new registry "patchfile" code (similar to ldif
for LDB); not finished yet.
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
8e7c4c98a7
commit
b405b27ba4
@@ -538,7 +538,7 @@ static void on_value_activate(GtkTreeView *treeview, GtkTreePath *arg1,
|
||||
|
||||
gtk_widget_set_sensitive(entry_name, FALSE);
|
||||
gtk_entry_set_text(GTK_ENTRY(entry_name), value->name);
|
||||
gtk_entry_set_text(GTK_ENTRY(entry_value), reg_val_data_string(mem_ctx, value));
|
||||
gtk_entry_set_text(GTK_ENTRY(entry_value), reg_val_data_string(mem_ctx, value->data_type, &value->data));
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(entry_type), value->data_type);
|
||||
|
||||
result = gtk_dialog_run(addwin);
|
||||
@@ -547,7 +547,7 @@ static void on_value_activate(GtkTreeView *treeview, GtkTreePath *arg1,
|
||||
WERROR error;
|
||||
struct registry_value *val;
|
||||
|
||||
reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val);
|
||||
reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val->data_type, &val->data);
|
||||
|
||||
error = reg_val_set(current_key, gtk_entry_get_text(GTK_ENTRY(entry_name)), val->data_type, val->data);
|
||||
|
||||
@@ -568,7 +568,7 @@ static void on_set_value_activate(GtkMenuItem *menuitem, gpointer user_data)
|
||||
WERROR error;
|
||||
struct registry_value *val;
|
||||
|
||||
reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val);
|
||||
reg_string_to_val(mem_ctx,str_regtype(gtk_combo_box_get_active(GTK_COMBO_BOX(entry_type))), gtk_entry_get_text(GTK_ENTRY(entry_value)), &val->data_type, &val->data);
|
||||
|
||||
error = reg_val_set(current_key, gtk_entry_get_text(GTK_ENTRY(entry_name)), val->data_type, val->data);
|
||||
|
||||
@@ -636,7 +636,7 @@ static gboolean on_key_activate(GtkTreeSelection *selection,
|
||||
1,
|
||||
str_regtype(val->data_type),
|
||||
2,
|
||||
reg_val_data_string(mem_ctx, val),
|
||||
reg_val_data_string(mem_ctx, val->data_type, &val->data),
|
||||
3,
|
||||
val,
|
||||
-1);
|
||||
|
||||
@@ -135,6 +135,7 @@ struct rw_buffer;
|
||||
struct registry_context;
|
||||
struct registry_key;
|
||||
struct registry_value;
|
||||
struct reg_diff_file;
|
||||
|
||||
struct rap_NetShareEnum;
|
||||
struct rap_NetServerEnum2;
|
||||
|
||||
@@ -24,12 +24,11 @@ reg_backend_wine.c:
|
||||
regshell:
|
||||
- support for security descriptors
|
||||
|
||||
regdiff:
|
||||
- fix
|
||||
|
||||
gregedit.c:
|
||||
- support for editing values / adding values / deleting values
|
||||
- support for adding/deleting keys
|
||||
- support for security descriptors
|
||||
|
||||
- pass parsed paths around rather then strings (i.e. just a list of strings)
|
||||
- integrate various registry tools ?
|
||||
- finish new patchfile code
|
||||
|
||||
@@ -46,27 +46,27 @@ const char *str_regtype(int type)
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v)
|
||||
char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
if(v->data.length == 0) return talloc_strdup(mem_ctx, "");
|
||||
if(data->length == 0) return talloc_strdup(mem_ctx, "");
|
||||
|
||||
switch (v->data_type) {
|
||||
switch (type) {
|
||||
case REG_EXPAND_SZ:
|
||||
case REG_SZ:
|
||||
convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data.data, v->data.length, (void **)&ret);
|
||||
convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret);
|
||||
return ret;
|
||||
|
||||
case REG_BINARY:
|
||||
ret = data_blob_hex_string(mem_ctx, &v->data);
|
||||
ret = data_blob_hex_string(mem_ctx, data);
|
||||
return ret;
|
||||
|
||||
case REG_DWORD:
|
||||
if (*(int *)v->data.data == 0)
|
||||
if (*(int *)data->data == 0)
|
||||
return talloc_strdup(mem_ctx, "0");
|
||||
|
||||
return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data.data);
|
||||
return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data);
|
||||
|
||||
case REG_MULTI_SZ:
|
||||
/* FIXME */
|
||||
@@ -81,47 +81,51 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v)
|
||||
|
||||
char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val)
|
||||
{
|
||||
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));
|
||||
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->data_type, &val->data));
|
||||
}
|
||||
|
||||
BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value)
|
||||
BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
int i;
|
||||
*value = talloc(mem_ctx, struct registry_value);
|
||||
(*value)->data_type = -1;
|
||||
*type = -1;
|
||||
|
||||
/* Find the correct type */
|
||||
for (i = 0; reg_value_types[i].name; i++) {
|
||||
if (!strcmp(reg_value_types[i].name, type_str)) {
|
||||
(*value)->data_type = reg_value_types[i].id;
|
||||
*type = reg_value_types[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*value)->data_type == -1)
|
||||
if (*type == -1)
|
||||
return False;
|
||||
|
||||
/* Convert data appropriately */
|
||||
|
||||
switch ((*value)->data_type)
|
||||
switch (*type)
|
||||
{
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
(*value)->data.length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&(*value)->data.data);
|
||||
data->length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&data->data);
|
||||
break;
|
||||
|
||||
case REG_DWORD: {
|
||||
uint32_t tmp = strtol(data_str, NULL, 0);
|
||||
(*value)->data = data_blob_talloc(mem_ctx, &tmp, 4);
|
||||
*data = data_blob_talloc(mem_ctx, &tmp, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_NONE:
|
||||
ZERO_STRUCT((*value)->data);
|
||||
ZERO_STRUCT(data);
|
||||
break;
|
||||
|
||||
case REG_BINARY:
|
||||
*data = strhex_to_data_blob(data_str);
|
||||
talloc_steal(mem_ctx, data->data);
|
||||
break;
|
||||
|
||||
default:
|
||||
case REG_BINARY: /* FIXME */
|
||||
/* FIXME */
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
|
||||
@@ -83,7 +83,8 @@ INIT_OBJ_FILES = \
|
||||
lib/registry/common/reg_interface.o
|
||||
ADD_OBJ_FILES = \
|
||||
lib/registry/common/reg_util.o \
|
||||
lib/registry/reg_samba.o
|
||||
lib/registry/reg_samba.o \
|
||||
lib/registry/patchfile.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
LIBBASIC
|
||||
# End MODULE registry_ldb
|
||||
|
||||
@@ -138,4 +138,27 @@ struct reg_init_function_entry {
|
||||
struct reg_init_function_entry *prev, *next;
|
||||
};
|
||||
|
||||
struct reg_diff_value
|
||||
{
|
||||
char *name;
|
||||
enum { REG_DIFF_DEL_VAL, REG_DIFF_SET_VAL } changetype;
|
||||
uint32_t type;
|
||||
DATA_BLOB data;
|
||||
};
|
||||
|
||||
struct reg_diff_key
|
||||
{
|
||||
char *name;
|
||||
enum { REG_DIFF_CHANGE_KEY, REG_DIFF_DEL_KEY } changetype;
|
||||
uint32_t numvalues;
|
||||
struct reg_diff_value *values;
|
||||
};
|
||||
|
||||
struct reg_diff
|
||||
{
|
||||
char *format;
|
||||
uint32_t numkeys;
|
||||
struct reg_diff_key *keys;
|
||||
};
|
||||
|
||||
#endif /* _REGISTRY_H */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004
|
||||
Copyright (C) Jelmer Vernooij 2004-2005
|
||||
|
||||
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
|
||||
@@ -24,101 +24,15 @@
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
|
||||
static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out)
|
||||
{
|
||||
int i;
|
||||
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(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", 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_free(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;
|
||||
}
|
||||
|
||||
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", 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_free(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;
|
||||
}
|
||||
|
||||
|
||||
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) && data_blob_equal(&v1->data, &v2->data))
|
||||
|| W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
|
||||
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)) {
|
||||
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(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(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", v1->name);
|
||||
} else {
|
||||
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(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;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
poptContext pc;
|
||||
char *outputfile = NULL;
|
||||
FILE *fd = stdout;
|
||||
struct registry_context *h1 = NULL, *h2 = NULL;
|
||||
int from_null = 0;
|
||||
int i;
|
||||
WERROR error, error2;
|
||||
WERROR error;
|
||||
struct reg_diff *diff;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL },
|
||||
@@ -159,37 +73,13 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey,
|
||||
|
||||
poptFreeContext(pc);
|
||||
|
||||
if(outputfile) {
|
||||
fd = fopen(outputfile, "w+");
|
||||
if(!fd) {
|
||||
fprintf(stderr, "Unable to open '%s'\n", outputfile);
|
||||
return 1;
|
||||
}
|
||||
diff = reg_generate_diff(NULL, h1, h2);
|
||||
if (!diff) {
|
||||
fprintf(stderr, "Unable to generate diff between keys\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fd, "REGEDIT4\n\n");
|
||||
fprintf(fd, "; Generated using regdiff, part of Samba\n");
|
||||
|
||||
error2 = error = WERR_OK;
|
||||
|
||||
for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) {
|
||||
struct registry_key *r1, *r2;
|
||||
error = reg_get_predefined_key(h1, i, &r1);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i)));
|
||||
continue;
|
||||
}
|
||||
|
||||
error = reg_get_predefined_key(h2, i, &r2);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i)));
|
||||
continue;
|
||||
}
|
||||
|
||||
writediff(r1, r2, fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
reg_diff_save(diff, outputfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) 2002, Richard Sharpe, rsharpe@richardsharpe.com
|
||||
Copyright (C) 2004, Jelmer Vernooij, jelmer@samba.org
|
||||
Copyright (C) 2004-2005 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
|
||||
@@ -27,730 +26,6 @@
|
||||
#include "system/filesys.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
/*
|
||||
* Routines to parse a REGEDIT4 file
|
||||
*
|
||||
* The file consists of:
|
||||
*
|
||||
* REGEDIT4
|
||||
* \[[-]key-path\]\n
|
||||
* <value-spec>*
|
||||
*
|
||||
* Format:
|
||||
* [cmd:]name=type:value
|
||||
*
|
||||
* cmd = a|d|c|add|delete|change|as|ds|cs
|
||||
*
|
||||
* There can be more than one key-path and value-spec.
|
||||
*
|
||||
* Since we want to support more than one type of file format, we
|
||||
* construct a command-file structure that keeps info about the command file
|
||||
*/
|
||||
|
||||
#define FMT_UNREC -1
|
||||
#define FMT_REGEDIT4 0
|
||||
#define FMT_EDITREG1_1 1
|
||||
|
||||
#define FMT_STRING_REGEDIT4 "REGEDIT4"
|
||||
#define FMT_STRING_EDITREG1_0 "EDITREG1.0"
|
||||
|
||||
#define CMD_NONE 0
|
||||
#define CMD_ADD_KEY 1
|
||||
#define CMD_DEL_KEY 2
|
||||
|
||||
#define CMD_KEY 1
|
||||
#define CMD_VAL 2
|
||||
|
||||
typedef struct val_spec_list {
|
||||
struct val_spec_list *next;
|
||||
char *name;
|
||||
int type;
|
||||
char *val; /* Kept as a char string, really? */
|
||||
} VAL_SPEC_LIST;
|
||||
|
||||
typedef struct command_s {
|
||||
int cmd;
|
||||
char *key;
|
||||
int val_count;
|
||||
VAL_SPEC_LIST *val_spec_list, *val_spec_last;
|
||||
} CMD;
|
||||
|
||||
typedef struct cmd_line {
|
||||
int len, line_len;
|
||||
char *line;
|
||||
} CMD_LINE;
|
||||
|
||||
static void free_val_spec_list(VAL_SPEC_LIST *vl)
|
||||
{
|
||||
if (!vl) return;
|
||||
if (vl->name) free(vl->name);
|
||||
if (vl->val) free(vl->val);
|
||||
free(vl);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Some routines to handle lines of info in the command files
|
||||
*/
|
||||
static void skip_to_eol(int fd)
|
||||
{
|
||||
int rc;
|
||||
char ch = 0;
|
||||
|
||||
while ((rc = read(fd, &ch, 1)) == 1) {
|
||||
if (ch == 0x0A) return;
|
||||
}
|
||||
if (rc < 0) {
|
||||
DEBUG(0, ("Could not read file descriptor: %d, %s\n",
|
||||
fd, strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_cmd(CMD *cmd)
|
||||
{
|
||||
if (!cmd) return;
|
||||
|
||||
while (cmd->val_spec_list) {
|
||||
VAL_SPEC_LIST *tmp;
|
||||
|
||||
tmp = cmd->val_spec_list;
|
||||
cmd->val_spec_list = tmp->next;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
|
||||
}
|
||||
|
||||
static void free_cmd_line(CMD_LINE *cmd_line)
|
||||
{
|
||||
if (cmd_line) {
|
||||
if (cmd_line->line) free(cmd_line->line);
|
||||
free(cmd_line);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_line(struct cmd_line *cl)
|
||||
{
|
||||
char *pl;
|
||||
|
||||
if (!cl) return;
|
||||
|
||||
pl = smb_xmalloc(cl->line_len + 1);
|
||||
|
||||
strncpy(pl, cl->line, cl->line_len);
|
||||
pl[cl->line_len] = 0;
|
||||
|
||||
fprintf(stdout, "%s\n", pl);
|
||||
free(pl);
|
||||
}
|
||||
|
||||
#define INIT_ALLOC 10
|
||||
|
||||
/*
|
||||
* Read a line from the input file.
|
||||
* NULL returned when EOF and no chars read
|
||||
* Otherwise we return a cmd_line *
|
||||
* Exit if other errors
|
||||
*/
|
||||
static struct cmd_line *get_cmd_line(int fd)
|
||||
{
|
||||
CMD_LINE *cl = malloc_p(CMD_LINE);
|
||||
int i = 0, rc;
|
||||
uint8_t ch;
|
||||
|
||||
if (!cl)
|
||||
return NULL;
|
||||
|
||||
cl->len = INIT_ALLOC;
|
||||
|
||||
/*
|
||||
* Allocate some space for the line. We extend later if needed.
|
||||
*/
|
||||
|
||||
cl->line = (char *)smb_xmalloc(INIT_ALLOC);
|
||||
|
||||
/*
|
||||
* Now read in the chars to EOL. Don't store the EOL in the
|
||||
* line. What about CR?
|
||||
*/
|
||||
|
||||
while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') {
|
||||
if (ch == '\r') continue; /* skip CR */
|
||||
if (i == cl->len-1) {
|
||||
/*
|
||||
* Allocate some more memory
|
||||
*/
|
||||
if ((cl->line = realloc(cl->line, cl->len + INIT_ALLOC)) == NULL) {
|
||||
DEBUG(0, ("Unable to realloc space for line: %s\n",
|
||||
strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
cl->len += INIT_ALLOC;
|
||||
}
|
||||
cl->line[i] = ch;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* read 0 and we were at loc'n 0, return NULL */
|
||||
if (rc == 0 && i == 0) {
|
||||
free_cmd_line(cl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cl->line[i] = '\0';
|
||||
cl->line_len = i;
|
||||
|
||||
return cl;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_value: parse out a value. We pull it apart as:
|
||||
*
|
||||
* <value> ::= <value-name>=<type>:<value-string>
|
||||
*
|
||||
* <value-name> ::= char-string-without-spaces | '"' char-string '"'
|
||||
*
|
||||
* If it parsed OK, return the <value-name> as a string, and the
|
||||
* value type and value-string in parameters.
|
||||
*
|
||||
* The value name can be empty. There can only be one empty name in
|
||||
* a list of values. A value of - removes the value entirely.
|
||||
*/
|
||||
|
||||
static char *parse_name(char *nstr)
|
||||
{
|
||||
int len = 0, start = 0;
|
||||
if (!nstr) return NULL;
|
||||
|
||||
len = strlen(nstr);
|
||||
|
||||
while (len && nstr[len - 1] == ' ') len--;
|
||||
|
||||
nstr[len] = 0; /* Trim any spaces ... if there were none, doesn't matter */
|
||||
|
||||
/*
|
||||
* Beginning and end should be '"' or neither should be so
|
||||
*/
|
||||
if ((nstr[0] == '"' && nstr[len - 1] != '"') ||
|
||||
(nstr[0] != '"' && nstr[len - 1] == '"'))
|
||||
return NULL;
|
||||
|
||||
if (nstr[0] == '"') {
|
||||
start = 1;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
return strndup(&nstr[start], len);
|
||||
}
|
||||
|
||||
static int parse_value_type(char *tstr)
|
||||
{
|
||||
int len = strlen(tstr);
|
||||
|
||||
while (len && tstr[len - 1] == ' ') len--;
|
||||
tstr[len] = 0;
|
||||
|
||||
if (strcmp(tstr, "REG_DWORD") == 0)
|
||||
return REG_DWORD;
|
||||
else if (strcmp(tstr, "dword") == 0)
|
||||
return REG_DWORD;
|
||||
else if (strcmp(tstr, "REG_EXPAND_SZ") == 0)
|
||||
return REG_EXPAND_SZ;
|
||||
else if (strcmp(tstr, "REG_BIN") == 0)
|
||||
return REG_BINARY;
|
||||
else if (strcmp(tstr, "REG_SZ") == 0)
|
||||
return REG_SZ;
|
||||
else if (strcmp(tstr, "REG_MULTI_SZ") == 0)
|
||||
return REG_MULTI_SZ;
|
||||
else if (strcmp(tstr, "-") == 0)
|
||||
return REG_DELETE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *parse_val_str(char *vstr)
|
||||
{
|
||||
|
||||
return strndup(vstr, strlen(vstr));
|
||||
|
||||
}
|
||||
|
||||
static char *parse_value(struct cmd_line *cl, int *vtype, char **val)
|
||||
{
|
||||
char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL;
|
||||
|
||||
if (!cl || !vtype || !val) return NULL;
|
||||
if (!cl->line[0]) return NULL;
|
||||
|
||||
p1 = strdup(cl->line);
|
||||
/* FIXME: Better return codes etc ... */
|
||||
if (!p1) return NULL;
|
||||
p2 = strchr(p1, '=');
|
||||
if (!p2) return NULL;
|
||||
|
||||
*p2 = 0; p2++; /* Split into two strings at p2 */
|
||||
|
||||
/* Now, parse the name ... */
|
||||
|
||||
nstr = parse_name(p1);
|
||||
if (!nstr) goto error;
|
||||
|
||||
/* Now, split the remainder and parse on type and val ... */
|
||||
|
||||
tstr = p2;
|
||||
while (*tstr == ' ') tstr++; /* Skip leading white space */
|
||||
p2 = strchr(p2, ':');
|
||||
|
||||
if (p2) {
|
||||
*p2 = 0; p2++; /* split on the : */
|
||||
}
|
||||
|
||||
*vtype = parse_value_type(tstr);
|
||||
|
||||
if (!vtype) goto error;
|
||||
|
||||
if (!p2 || !*p2) return nstr;
|
||||
|
||||
/* Now, parse the value string. It should return a newly malloc'd string */
|
||||
|
||||
while (*p2 == ' ') p2++; /* Skip leading space */
|
||||
vstr = parse_val_str(p2);
|
||||
|
||||
if (!vstr) goto error;
|
||||
|
||||
*val = vstr;
|
||||
|
||||
return nstr;
|
||||
|
||||
error:
|
||||
if (p1) free(p1);
|
||||
if (nstr) free(nstr);
|
||||
if (vstr) free(vstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse out a key. Look for a correctly formatted key [...]
|
||||
* and whether it is a delete or add? A delete is signalled
|
||||
* by a - in front of the key.
|
||||
* Assumes that there are no leading and trailing spaces
|
||||
*/
|
||||
|
||||
static char *parse_key(struct cmd_line *cl, int *cmd)
|
||||
{
|
||||
int start = 1;
|
||||
char *tmp;
|
||||
|
||||
if (cl->line[0] != '[' ||
|
||||
cl->line[cl->line_len - 1] != ']') return NULL;
|
||||
if (cl->line_len == 2) return NULL;
|
||||
*cmd = CMD_ADD_KEY;
|
||||
if (cl->line[1] == '-') {
|
||||
if (cl->line_len == 3) return NULL;
|
||||
start = 2;
|
||||
*cmd = CMD_DEL_KEY;
|
||||
}
|
||||
tmp = smb_xmalloc(cl->line_len - 1 - start + 1);
|
||||
strncpy(tmp, &cl->line[start], cl->line_len - 1 - start);
|
||||
tmp[cl->line_len - 1 - start] = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a line to determine if we have a key or a value
|
||||
* We only check for key or val ...
|
||||
*/
|
||||
|
||||
static int parse_line(struct cmd_line *cl)
|
||||
{
|
||||
|
||||
if (!cl || cl->len == 0) return 0;
|
||||
|
||||
if (cl->line[0] == '[') /* No further checking for now */
|
||||
return CMD_KEY;
|
||||
else
|
||||
return CMD_VAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We seek to offset 0, read in the required number of bytes,
|
||||
* and compare to the correct value.
|
||||
* We then seek back to the original location
|
||||
*/
|
||||
static int regedit4_file_type(int fd)
|
||||
{
|
||||
int cur_ofs = 0;
|
||||
char desc[9];
|
||||
|
||||
cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */
|
||||
if (cur_ofs < 0) {
|
||||
DEBUG(0, ("Unable to get current offset: (%d) %s\n", cur_ofs, strerror(errno)));
|
||||
exit(1); /* FIXME */
|
||||
}
|
||||
|
||||
if (cur_ofs) {
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
if (read(fd, desc, 8) < 8) {
|
||||
DEBUG(0, ("Unable to read command file format\n"));
|
||||
exit(2); /* FIXME */
|
||||
}
|
||||
|
||||
desc[8] = 0;
|
||||
|
||||
if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) {
|
||||
if (cur_ofs) {
|
||||
lseek(fd, cur_ofs, SEEK_SET);
|
||||
} else {
|
||||
skip_to_eol(fd);
|
||||
}
|
||||
return FMT_REGEDIT4;
|
||||
}
|
||||
|
||||
return FMT_UNREC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run though the data in the line and strip anything after a comment
|
||||
* char.
|
||||
*/
|
||||
static void strip_comment(struct cmd_line *cl)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!cl) return;
|
||||
|
||||
for (i = 0; i < cl->line_len; i++) {
|
||||
if (cl->line[i] == ';') {
|
||||
cl->line[i] = '\0';
|
||||
cl->line_len = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a command ... This consists of possibly multiple lines:
|
||||
* [key]
|
||||
* values*
|
||||
* possibly Empty line
|
||||
*
|
||||
* value ::= <value-name>=<value-type>':'<value-string>
|
||||
* <value-name> is some path, possibly enclosed in quotes ...
|
||||
* We alctually look for the next key to terminate a previous key
|
||||
* if <value-type> == '-', then it is a delete type.
|
||||
*/
|
||||
static CMD *regedit4_get_cmd(int fd)
|
||||
{
|
||||
struct command_s *cmd = NULL;
|
||||
struct cmd_line *cl = NULL;
|
||||
struct val_spec_list *vl = NULL;
|
||||
|
||||
cmd = malloc_p(struct command_s);
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
cmd->cmd = CMD_NONE;
|
||||
cmd->key = NULL;
|
||||
cmd->val_count = 0;
|
||||
cmd->val_spec_list = cmd->val_spec_last = NULL;
|
||||
while ((cl = get_cmd_line(fd))) {
|
||||
|
||||
/*
|
||||
* If it is an empty command line, and we already have a key
|
||||
* then exit from here ... FIXME: Clean up the parser
|
||||
*/
|
||||
|
||||
if (cl->line_len == 0 && cmd->key) {
|
||||
free_cmd_line(cl);
|
||||
break;
|
||||
}
|
||||
|
||||
strip_comment(cl); /* remove anything beyond a comment char */
|
||||
trim_string(cl->line, " \t", " \t");
|
||||
|
||||
if (!cl->line[0]) { /* An empty line */
|
||||
free_cmd_line(cl);
|
||||
}
|
||||
else { /* Else, non-empty ... */
|
||||
/*
|
||||
* Parse out the bits ...
|
||||
*/
|
||||
switch (parse_line(cl)) {
|
||||
case CMD_KEY:
|
||||
if ((cmd->key = parse_key(cl, &cmd->cmd)) == NULL) {
|
||||
DEBUG(0, ("Error parsing key from line: "));
|
||||
print_line(cl);
|
||||
DEBUG(0, ("\n"));
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_VAL:
|
||||
/*
|
||||
* We need to add the value stuff to the list
|
||||
* There could be a \ on the end which we need to
|
||||
* handle at some time
|
||||
*/
|
||||
vl = malloc_p(struct val_spec_list);
|
||||
if (!vl)
|
||||
return NULL;
|
||||
vl->next = NULL;
|
||||
vl->val = NULL;
|
||||
vl->name = parse_value(cl, &vl->type, &vl->val);
|
||||
if (!vl->name) goto error;
|
||||
if (cmd->val_spec_list == NULL) {
|
||||
cmd->val_spec_list = cmd->val_spec_last = vl;
|
||||
}
|
||||
else {
|
||||
cmd->val_spec_last->next = vl;
|
||||
cmd->val_spec_last = vl;
|
||||
}
|
||||
cmd->val_count++;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG(0, ("Unrecognized line in command file: \n"));
|
||||
print_line(cl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!cmd->cmd) goto error; /* End of file ... */
|
||||
|
||||
return cmd;
|
||||
|
||||
error:
|
||||
if (vl) free(vl);
|
||||
if (cmd) free_cmd(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int regedit4_exec_cmd(CMD *cmd)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int editreg_1_0_file_type(int fd)
|
||||
{
|
||||
int cur_ofs = 0;
|
||||
char desc[11];
|
||||
|
||||
cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */
|
||||
if (cur_ofs < 0) {
|
||||
DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno)));
|
||||
exit(1); /* FIXME */
|
||||
}
|
||||
|
||||
if (cur_ofs) {
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
if (read(fd, desc, 10) < 10) {
|
||||
DEBUG(0, ("Unable to read command file format\n"));
|
||||
exit(2); /* FIXME */
|
||||
}
|
||||
|
||||
desc[10] = 0;
|
||||
|
||||
if (strcmp(desc, FMT_STRING_EDITREG1_0) == 0) {
|
||||
lseek(fd, cur_ofs, SEEK_SET);
|
||||
return FMT_REGEDIT4;
|
||||
}
|
||||
|
||||
return FMT_UNREC;
|
||||
}
|
||||
|
||||
static CMD *editreg_1_0_get_cmd(int fd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int editreg_1_0_exec_cmd(CMD *cmd)
|
||||
{
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct command_ops_s {
|
||||
int type;
|
||||
int (*file_type)(int fd);
|
||||
CMD *(*get_cmd)(int fd);
|
||||
int (*exec_cmd)(CMD *cmd);
|
||||
} CMD_OPS;
|
||||
|
||||
static CMD_OPS default_cmd_ops[] = {
|
||||
{0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd},
|
||||
{1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd},
|
||||
{-1, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
typedef struct command_file_s {
|
||||
char *name;
|
||||
int type, fd;
|
||||
CMD_OPS cmd_ops;
|
||||
} CMD_FILE;
|
||||
|
||||
/*
|
||||
* Create a new command file structure
|
||||
*/
|
||||
|
||||
static CMD_FILE *cmd_file_create(const char *file)
|
||||
{
|
||||
CMD_FILE *tmp;
|
||||
struct stat sbuf;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* Let's check if the file exists ...
|
||||
* No use creating the cmd_file structure if the file does not exist
|
||||
*/
|
||||
|
||||
if (stat(file, &sbuf) < 0) { /* Not able to access file */
|
||||
DEBUG(0,("Stat on %s failed\n", file));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmp = malloc_p(CMD_FILE);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Let's fill in some of the fields;
|
||||
*/
|
||||
|
||||
tmp->name = strdup(file);
|
||||
|
||||
if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) {
|
||||
DEBUG(0,("Error opening %s\n", file));
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, try to find the format by indexing through the table
|
||||
*/
|
||||
while (default_cmd_ops[i].type != -1) {
|
||||
if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) {
|
||||
tmp->cmd_ops = default_cmd_ops[i];
|
||||
return tmp;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got here, return NULL, as we could not figure out the type
|
||||
* of command file.
|
||||
*
|
||||
* What about errors?
|
||||
*/
|
||||
|
||||
free(tmp);
|
||||
DEBUG(0,("Unknown type\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract commands from the command file, and execute them.
|
||||
* We pass a table of command callbacks for that
|
||||
*/
|
||||
|
||||
/* FIXME */
|
||||
|
||||
/*
|
||||
* Main code from here on ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* key print function here ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sec Desc print functions
|
||||
*/
|
||||
|
||||
char *str_type(uint8_t type);
|
||||
|
||||
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;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file");
|
||||
struct registry_key *tmp = NULL;
|
||||
WERROR error;
|
||||
cmd_file = cmd_file_create(cmd_file_name);
|
||||
|
||||
while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) {
|
||||
|
||||
/*
|
||||
* Now, apply the requests to the tree ...
|
||||
*/
|
||||
switch (cmd->cmd) {
|
||||
case CMD_ADD_KEY:
|
||||
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_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) {
|
||||
DEBUG(0, ("Error adding new key '%s'\n", cmd->key));
|
||||
continue;
|
||||
}
|
||||
modified = True;
|
||||
}
|
||||
|
||||
while (cmd->val_count) {
|
||||
VAL_SPEC_LIST *val = cmd->val_spec_list;
|
||||
|
||||
if (val->type == REG_DELETE) {
|
||||
error = reg_del_value(tmp, val->name);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error removing value '%s'\n", val->name));
|
||||
}
|
||||
modified = True;
|
||||
} else {
|
||||
DATA_BLOB blob;
|
||||
blob.data = (uint8_t *)val->val;
|
||||
blob.length = strlen(val->val);
|
||||
if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, blob))) {
|
||||
DEBUG(0, ("Error adding new value '%s'\n", val->name));
|
||||
continue;
|
||||
}
|
||||
modified = True;
|
||||
}
|
||||
|
||||
cmd->val_spec_list = val->next;
|
||||
free_val_spec_list(val);
|
||||
cmd->val_count--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CMD_DEL_KEY:
|
||||
/*
|
||||
* Any value does not matter ...
|
||||
* Find the key if it exists, and delete it ...
|
||||
*/
|
||||
|
||||
error = reg_key_del_abs(r, cmd->key);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to delete key '%s'\n", cmd->key));
|
||||
continue;
|
||||
}
|
||||
modified = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free_cmd(cmd);
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
@@ -758,6 +33,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
|
||||
const char *patch;
|
||||
struct registry_context *h;
|
||||
const char *remote = NULL;
|
||||
struct reg_diff *diff;
|
||||
WERROR error;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
@@ -786,10 +62,15 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd
|
||||
}
|
||||
|
||||
patch = poptGetArg(pc);
|
||||
if(!patch) patch = "/dev/stdin";
|
||||
poptFreeContext(pc);
|
||||
|
||||
nt_apply_reg_command_file(h, patch);
|
||||
diff = reg_diff_load(NULL, patch);
|
||||
if (!diff) {
|
||||
fprintf(stderr, "Unable to load registry patch from `%s'\n", patch);
|
||||
return 1;
|
||||
}
|
||||
|
||||
reg_diff_apply(diff, h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context
|
||||
fprintf(stderr, "Usage: set value-name type value\n");
|
||||
} else {
|
||||
struct registry_value *val;
|
||||
if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val)) {
|
||||
if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val->data_type, &val->data)) {
|
||||
WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error setting value: %s\n", win_errstr(error));
|
||||
@@ -140,7 +140,7 @@ static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_conte
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value));
|
||||
printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context
|
||||
}
|
||||
|
||||
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));
|
||||
printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user