summaryrefslogtreecommitdiff
path: root/source4/lib/registry/patchfile_preg.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/registry/patchfile_preg.c')
-rw-r--r--source4/lib/registry/patchfile_preg.c97
1 files changed, 84 insertions, 13 deletions
diff --git a/source4/lib/registry/patchfile_preg.c b/source4/lib/registry/patchfile_preg.c
index 0fa367bfcb..bb46495c19 100644
--- a/source4/lib/registry/patchfile_preg.c
+++ b/source4/lib/registry/patchfile_preg.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
Reading Registry.pol PReg registry files
- Copyright (C) Wilco Baan Hofman 2006
+ Copyright (C) Wilco Baan Hofman 2006-2008
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
@@ -23,9 +23,12 @@
#include "lib/registry/registry.h"
#include "system/filesys.h"
#include "param/param.h"
+#include "librpc/gen_ndr/winreg.h"
struct preg_data {
int fd;
+ TALLOC_CTX *ctx;
+ struct smb_iconv_convenience *ic;
};
static WERROR preg_read_utf16(struct smb_iconv_convenience *ic, int fd, char *c)
@@ -38,14 +41,22 @@ static WERROR preg_read_utf16(struct smb_iconv_convenience *ic, int fd, char *c)
push_codepoint(ic, c, v);
return WERR_OK;
}
-
-/* FIXME These functions need to be implemented */
-static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
+static WERROR preg_write_utf16(struct smb_iconv_convenience *ic, int fd, const char *string)
{
+ codepoint_t v;
+ uint16_t i;
+ size_t size;
+
+ for (i = 0; i < strlen(string); i+=size) {
+ v = next_codepoint(ic, &string[i], &size);
+ if (write(fd, &v, 2) < 2) {
+ return WERR_GENERAL_FAILURE;
+ }
+ }
return WERR_OK;
}
-
-static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
+/* PReg does not support adding keys. */
+static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
{
return WERR_OK;
}
@@ -54,24 +65,73 @@ static WERROR reg_preg_diff_set_value(void *_data, const char *key_name,
const char *value_name,
uint32_t value_type, DATA_BLOB value_data)
{
+ struct preg_data *data = _data;
+ uint32_t buf;
+
+ preg_write_utf16(data->ic, data->fd, "[");
+ preg_write_utf16(data->ic, data->fd, key_name);
+ preg_write_utf16(data->ic, data->fd, ";");
+ preg_write_utf16(data->ic, data->fd, value_name);
+ preg_write_utf16(data->ic, data->fd, ";");
+ SIVAL(&buf, 0, value_type);
+ write(data->fd, &buf, sizeof(uint32_t));
+ preg_write_utf16(data->ic, data->fd, ";");
+ SIVAL(&buf, 0, value_data.length);
+ write(data->fd, &buf, sizeof(uint32_t));
+ preg_write_utf16(data->ic, data->fd, ";");
+ write(data->fd, value_data.data, value_data.length);
+ preg_write_utf16(data->ic, data->fd, "]");
+
return WERR_OK;
}
+static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
+{
+ struct preg_data *data = _data;
+ char *parent_name;
+ DATA_BLOB blob;
+
+ parent_name = talloc_strndup(data->ctx, key_name, strrchr(key_name, '\\')-key_name);
+ blob.data = (void *)talloc_strndup(data->ctx, key_name+(strrchr(key_name, '\\')-key_name)+1,
+ strlen(key_name)-(strrchr(key_name, '\\')-key_name));
+ blob.length = strlen((char *)blob.data)+1;
+
+
+ /* FIXME: These values should be accumulated to be written at done(). */
+ return reg_preg_diff_set_value(data, parent_name, "**DeleteKeys", REG_SZ, blob);
+}
+
static WERROR reg_preg_diff_del_value(void *_data, const char *key_name,
const char *value_name)
{
- return WERR_OK;
+ struct preg_data *data = _data;
+ char *val;
+ DATA_BLOB blob;
+
+ val = talloc_asprintf(data->ctx, "**Del.%s", value_name);
+
+ blob.data = (void *)talloc(data->ctx, uint32_t);
+ *(uint32_t *)blob.data = 0;
+ blob.length = 4;
+ return reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob);
}
static WERROR reg_preg_diff_del_all_values(void *_data, const char *key_name)
{
- return WERR_OK;
+ struct preg_data *data = _data;
+ DATA_BLOB blob;
+
+ blob.data = (void *)talloc(data->ctx, uint32_t);
+ *(uint32_t *)blob.data = 0;
+ blob.length = 4;
+
+ return reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD, blob);
}
static WERROR reg_preg_diff_done(void *_data)
{
struct preg_data *data = (struct preg_data *)_data;
-
+
close(data->fd);
talloc_free(data);
return WERR_OK;
@@ -81,6 +141,7 @@ static WERROR reg_preg_diff_done(void *_data)
* Save registry diff
*/
_PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
+ struct smb_iconv_convenience *ic,
struct reg_diff_callbacks **callbacks,
void **callback_data)
{
@@ -95,18 +156,22 @@ _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
*callback_data = data;
if (filename) {
- data->fd = open(filename, O_CREAT, 0755);
- if (data->fd == -1) {
+ data->fd = open(filename, O_CREAT|O_WRONLY, 0755);
+ if (data->fd < 0) {
DEBUG(0, ("Unable to open %s\n", filename));
return WERR_BADFILE;
}
} else {
data->fd = STDOUT_FILENO;
}
- snprintf(preg_header.hdr, 4, "PReg");
+
+ strncpy(preg_header.hdr, "PReg", 4);
SIVAL(&preg_header, 4, 1);
write(data->fd, (uint8_t *)&preg_header,8);
+ data->ctx = ctx;
+ data->ic = ic;
+
*callbacks = talloc(ctx, struct reg_diff_callbacks);
(*callbacks)->add_key = reg_preg_diff_add_key;
@@ -149,6 +214,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
ret = WERR_GENERAL_FAILURE;
goto cleanup;
}
+ preg_header.version = IVAL(&preg_header.version, 0);
+
if (strncmp(preg_header.hdr, "PReg", 4) != 0) {
DEBUG(0, ("This file is not a valid preg registry file\n"));
ret = WERR_GENERAL_FAILURE;
@@ -177,7 +244,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
*buf_ptr != ';' && buf_ptr-buf < buf_size) {
buf_ptr++;
}
- key = talloc_asprintf(mem_ctx, "\\%s", buf);
+ buf[buf_ptr-buf] = '\0';
+ key = talloc_strdup(mem_ctx, buf);
/* Get the name */
buf_ptr = buf;
@@ -185,6 +253,7 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
*buf_ptr != ';' && buf_ptr-buf < buf_size) {
buf_ptr++;
}
+ buf[buf_ptr-buf] = '\0';
value_name = talloc_strdup(mem_ctx, buf);
/* Get the type */
@@ -193,6 +262,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
ret = WERR_GENERAL_FAILURE;
goto cleanup;
}
+ value_type = IVAL(&value_type, 0);
+
/* Read past delimiter */
buf_ptr = buf;
if (!(W_ERROR_IS_OK(preg_read_utf16(iconv_convenience, fd, buf_ptr)) &&