diff options
Diffstat (limited to 'source4/lib/registry/patchfile_preg.c')
-rw-r--r-- | source4/lib/registry/patchfile_preg.c | 97 |
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..c2bc8d10b3 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"); + + memcpy(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)) && |