From 5e687d79533684949deb9bd9bc86f88eab4ae310 Mon Sep 17 00:00:00 2001 From: Wilco Baan Hofman Date: Tue, 15 Apr 2008 19:57:29 +0200 Subject: [PATCH] Fix PReg write support. Add tests for patch files (.REG and PReg). (This used to be commit 497977c36c621a4820be51cbcb7b78eac1e292b7) --- source4/lib/registry/patchfile.c | 23 ++++++++++- source4/lib/registry/patchfile_preg.c | 72 ++++++++++++++++++++++++++++++----- source4/lib/registry/registry.h | 1 + source4/lib/registry/tests/diff.c | 19 +++++---- 4 files changed, 97 insertions(+), 18 deletions(-) diff --git a/source4/lib/registry/patchfile.c b/source4/lib/registry/patchfile.c index eaeef341bba..0ede3106f00 100644 --- a/source4/lib/registry/patchfile.c +++ b/source4/lib/registry/patchfile.c @@ -320,12 +320,33 @@ static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name) { struct registry_context *ctx = (struct registry_context *)_ctx; struct registry_key *tmp; + char *buf, *buf_ptr; WERROR error; + /* Recursively create the path */ + buf = talloc_strdup(ctx, key_name); + buf_ptr = buf; + + while (*buf_ptr++ != '\0' ) { + if (*buf_ptr == '\\') { + *buf_ptr = '\0'; + error = reg_key_add_abs(ctx, ctx, buf, 0, NULL, &tmp); + + if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) && + !W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error adding new key '%s': %s\n", + key_name, win_errstr(error))); + return error; + } + *buf_ptr++ = '\\'; + } + } + + /* Add the key */ error = reg_key_add_abs(ctx, ctx, key_name, 0, NULL, &tmp); if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) && - !W_ERROR_IS_OK(error)) { + !W_ERROR_IS_OK(error)) { DEBUG(0, ("Error adding new key '%s': %s\n", key_name, win_errstr(error))); return error; diff --git a/source4/lib/registry/patchfile_preg.c b/source4/lib/registry/patchfile_preg.c index a28096517c6..ea41a9e21bb 100644 --- a/source4/lib/registry/patchfile_preg.c +++ b/source4/lib/registry/patchfile_preg.c @@ -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,25 +41,69 @@ 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) { - return WERR_NOT_SUPPORTED; + 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_NOT_SUPPORTED; + return WERR_OK; } 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) { - return WERR_NOT_SUPPORTED; + 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, + 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(). */ + reg_preg_diff_set_value(_data, parent_name, "**DeleteKeys", REG_SZ, blob); + + return WERR_OK; +} + +/* FIXME These functions need to be implemented */ static WERROR reg_preg_diff_del_value(void *_data, const char *key_name, const char *value_name) { @@ -81,6 +128,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) { @@ -103,10 +151,14 @@ _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename, } else { data->fd = STDOUT_FILENO; } + 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; @@ -179,7 +231,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; @@ -187,6 +240,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 */ diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index 573379aff50..6a98a606336 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -493,6 +493,7 @@ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename, struct reg_diff_callbacks **callbacks, void **callback_data); WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename, + struct smb_iconv_convenience *ic, struct reg_diff_callbacks **callbacks, void **callback_data); WERROR reg_generate_diff_key(struct registry_key *oldkey, diff --git a/source4/lib/registry/tests/diff.c b/source4/lib/registry/tests/diff.c index da623421244..4bd868ea513 100644 --- a/source4/lib/registry/tests/diff.c +++ b/source4/lib/registry/tests/diff.c @@ -24,6 +24,7 @@ #include "lib/registry/registry.h" #include "torture/torture.h" #include "librpc/gen_ndr/winreg.h" +#include "param/param.h" struct diff_tcase_data { struct registry_context *r1_ctx; @@ -56,13 +57,12 @@ static bool test_generate_diff(struct torture_context *tctx, void *tcase_data) static bool test_diff_load(struct torture_context *tctx, void *tcase_data) { struct diff_tcase_data *td = tcase_data; - struct smb_iconv_convenience *iconv_convenience; + struct smb_iconv_convenience *ic; struct reg_diff_callbacks *callbacks; void *data; WERROR error; - iconv_convenience = smb_iconv_convenience_init(tctx, "CP850", "UTF-8", 1); - + ic = lp_iconv_convenience(tctx->lp_ctx); error = reg_diff_load(td->filename, iconv_convenience, callbacks, data); torture_assert_werr_ok(tctx, error, "reg_diff_load"); @@ -244,13 +244,16 @@ static bool diff_setup_tcase(struct torture_context *tctx, void **data) static bool diff_setup_preg_tcase (struct torture_context *tctx, void **data) { struct diff_tcase_data *td; + struct smb_iconv_convenience *ic; WERROR error; diff_setup_tcase(tctx, data); td = *data; - + + ic = lp_iconv_convenience(tctx->lp_ctx); + td->filename = talloc_asprintf(tctx, "%s/test.pol", td->tempdir); - error = reg_preg_diff_save(tctx, td->filename, &td->callbacks, &td->callback_data); + error = reg_preg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data); torture_assert_werr_ok(tctx, error, "reg_preg_diff_save"); return true; @@ -259,16 +262,16 @@ static bool diff_setup_preg_tcase (struct torture_context *tctx, void **data) static bool diff_setup_dotreg_tcase (struct torture_context *tctx, void **data) { struct diff_tcase_data *td; - struct smb_iconv_convenience *iconv_convenience; + struct smb_iconv_convenience *ic; WERROR error; diff_setup_tcase(tctx, data); td = *data; - iconv_convenience = smb_iconv_convenience_init(tctx, "CP850", "UTF-8", 1); + ic = lp_iconv_convenience(tctx->lp_ctx); td->filename = talloc_asprintf(tctx, "%s/test.reg", td->tempdir); - error = reg_dotreg_diff_save(tctx, td->filename, iconv_convenience, &td->callbacks, &td->callback_data); + error = reg_dotreg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data); torture_assert_werr_ok(tctx, error, "reg_dotreg_diff_save"); return true; -- 2.11.4.GIT