summaryrefslogtreecommitdiffstats
path: root/source3/registry/reg_import.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
commit4f5791ebd03eaec1c7da0865a383175b05102712 (patch)
tree8ce7b00f7a76baa386372422adebbe64510812d4 /source3/registry/reg_import.c
parentInitial commit. (diff)
downloadsamba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz
samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/registry/reg_import.c')
-rw-r--r--source3/registry/reg_import.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/source3/registry/reg_import.c b/source3/registry/reg_import.c
new file mode 100644
index 0000000..aef8645
--- /dev/null
+++ b/source3/registry/reg_import.c
@@ -0,0 +1,314 @@
+/*
+ * Samba Unix/Linux SMB client library
+ * Adapter to use reg_parse with the registry api
+ *
+ * Copyright (C) Gregor Beck 2010
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "reg_parse.h"
+#include "reg_import.h"
+#include "registry.h"
+#include "registry/reg_objects.h"
+#include <assert.h>
+
+/* Debuglevel for tracing */
+static const int TL = 2;
+
+struct reg_import {
+ struct reg_parse_callback reg_parse_callback;
+ struct reg_import_callback call;
+ void *open_key;
+};
+
+static int reg_parse_callback_key(struct reg_import *cb_private,
+ const char *key[], size_t n, bool del);
+
+static int reg_parse_callback_val(struct reg_import *cb_private,
+ const char *name, uint32_t type,
+ const uint8_t *data, size_t len);
+
+static int reg_parse_callback_val_registry_value(struct reg_import *cb_private,
+ const char *name,
+ uint32_t type,
+ const uint8_t *data,
+ size_t len);
+
+static int reg_parse_callback_val_regval_blob(struct reg_import *cb_private,
+ const char *name, uint32_t type,
+ const uint8_t *data,
+ size_t len);
+
+static int reg_parse_callback_val_del(struct reg_import *cb_private,
+ const char *name);
+
+static int reg_parse_callback_comment(struct reg_import *cb_private,
+ const char *txt);
+
+
+/*******************************************************************************/
+
+int reg_parse_callback_key(struct reg_import *p,
+ const char *key[], size_t n, bool del)
+{
+ WERROR werr = WERR_OK;
+
+ DEBUG(TL, ("%s: %s\n", __FUNCTION__, key[0]));
+
+ if (p->open_key != NULL) {
+ werr = p->call.closekey(p->call.data, p->open_key);
+ p->open_key = NULL;
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("closekey failed: %s\n", win_errstr(werr)));
+ }
+ }
+
+ if (del) {
+ werr = p->call.deletekey(p->call.data, NULL, key[0]);
+ if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
+ /* the key didn't exist, treat as success */
+ werr = WERR_OK;
+ }
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("deletekey %s failed: %s\n",
+ key[0], win_errstr(werr)));
+ }
+ } else {
+ bool existing;
+ werr = p->call.createkey(p->call.data, NULL, key[0],
+ &p->open_key, &existing);
+ if (W_ERROR_IS_OK(werr)) {
+ DEBUG(TL, ("createkey %s %s\n",
+ existing ? "opened" : "created", key[0]));
+ } else {
+ DEBUG(0, ("createkey %s failed: %s\n",
+ key[0], win_errstr(werr)));
+ }
+ }
+
+ return W_ERROR_IS_OK(werr) ? 0 : -1;
+}
+
+#define DEBUG_ADD_HEX(LEV, PTR, LEN) \
+ do { \
+ int i; \
+ const unsigned char* ptr = (const unsigned char*)PTR; \
+ for (i=0; i<LEN; i++) { \
+ DEBUGADD(LEV, ("'%c'(%02x)%s", \
+ isprint(ptr[i]) ? ptr[i] : '.', \
+ (unsigned)ptr[i], \
+ ((i+1 < LEN) && (i+1)%8) \
+ ? ", " : "\n")); \
+ } \
+ } while(0)
+
+/*----------------------------------------------------------------------------*/
+int reg_parse_callback_val(struct reg_import *p,
+ const char *name, uint32_t type,
+ const uint8_t *data, size_t len)
+{
+ WERROR werr = WERR_OK;
+
+ DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
+ DEBUG_ADD_HEX(TL, data, len);
+
+ werr = p->call.setval.blob(p->call.data, p->open_key, name, type,
+ data, len);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("setval %s failed: %s\n",
+ name, win_errstr(werr)));
+ }
+
+ return W_ERROR_IS_OK(werr) ? 0 : -1;
+}
+
+/*----------------------------------------------------------------------------*/
+int reg_parse_callback_val_registry_value(struct reg_import *p,
+ const char *name, uint32_t type,
+ const uint8_t *data, size_t len)
+{
+ WERROR werr = WERR_OK;
+ struct registry_value val = {
+ .type = type,
+ .data = data_blob_talloc(p, data, len),
+ };
+
+ DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
+ DEBUG_ADD_HEX(TL, data, len);
+
+ werr = p->call.setval.registry_value(p->call.data, p->open_key,
+ name, &val);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("setval %s failed: %s\n",
+ name, win_errstr(werr)));
+ }
+
+ data_blob_free(&val.data);
+ return W_ERROR_IS_OK(werr) ? 0 : -1;
+}
+
+/*----------------------------------------------------------------------------*/
+int reg_parse_callback_val_regval_blob(struct reg_import *p,
+ const char *name, uint32_t type,
+ const uint8_t *data, size_t len)
+{
+ WERROR werr = WERR_OK;
+ void* mem_ctx = talloc_new(p);
+ struct regval_blob *v = NULL;
+
+ DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
+ DEBUG_ADD_HEX(TL, data, len);
+
+ v = regval_compose(mem_ctx, name, type, data, len);
+ if (v == NULL) {
+ DEBUG(0, ("regval_compose %s failed\n", name));
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ werr = p->call.setval.regval_blob(p->call.data, p->open_key, v);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("setval %s failed: %s\n",
+ name, win_errstr(werr)));
+ }
+
+done:
+ talloc_free(mem_ctx);
+
+ return W_ERROR_IS_OK(werr) ? 0 : -1;
+}
+
+
+/*----------------------------------------------------------------------------*/
+
+int reg_parse_callback_val_del(struct reg_import *p,
+ const char *name)
+{
+ WERROR werr = WERR_OK;
+
+ DEBUG(TL, ("%s: %s\n", __FUNCTION__, name));
+
+ werr = p->call.deleteval(p->call.data, p->open_key, name);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("deleteval %s failed: %s\n",
+ name, win_errstr(werr)));
+ }
+
+ return W_ERROR_IS_OK(werr) ? 0 : -1;
+}
+
+
+int reg_parse_callback_comment(struct reg_import *cb_private,
+ const char *txt)
+{
+ DEBUG(TL, ("%s: %s\n", __FUNCTION__, txt));
+ return 0;
+}
+
+/******************************************************************************/
+static WERROR nop_callback_open(void* private_data,
+ void* parent,
+ const char* name,
+ void** key)
+{
+ return WERR_OK;
+}
+
+static WERROR nop_callback_close(void* private_data, void* key)
+{
+ return WERR_OK;
+}
+
+static WERROR nop_callback_create(void* private_data,
+ void* parent,
+ const char* name,
+ void** key,
+ bool* existing)
+{
+ return WERR_OK;
+}
+
+
+static WERROR nop_callback_del(void* private_data,
+ void* parent,
+ const char* name)
+{
+ return WERR_OK;
+}
+
+struct reg_parse_callback *reg_import_adapter(TALLOC_CTX *talloc_ctx,
+ struct reg_import_callback cb)
+{
+ struct reg_parse_callback *ret;
+ struct reg_import *p = talloc_zero(talloc_ctx, struct reg_import);
+ if (p == NULL) {
+ goto fail;
+ }
+ if (cb.openkey == NULL) {
+ cb.openkey = (reg_import_callback_openkey_t)&nop_callback_open;
+ }
+ if (cb.closekey == NULL) {
+ cb.closekey =
+ (reg_import_callback_closekey_t)&nop_callback_close;
+ }
+ if (cb.createkey == NULL) {
+ cb.createkey =
+ (reg_import_callback_createkey_t)&nop_callback_create;
+ }
+ if (cb.deletekey == NULL) {
+ cb.deletekey =
+ (reg_import_callback_deletekey_t)&nop_callback_del;
+
+ }
+ if (cb.deleteval == NULL) {
+ cb.deleteval =
+ (reg_import_callback_deleteval_t)&nop_callback_del;
+ }
+
+ p->call = cb;
+
+ ret = &p->reg_parse_callback;
+ ret->key = (reg_parse_callback_key_t) &reg_parse_callback_key;
+ ret->val_del = (reg_parse_callback_val_del_t) &reg_parse_callback_val_del;
+ ret->comment = (reg_parse_callback_comment_t) &reg_parse_callback_comment;
+ ret->data = p;
+
+ switch (cb.setval_type) {
+ case BLOB:
+ assert(cb.setval.blob != NULL);
+ ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val;
+ break;
+ case REGISTRY_VALUE:
+ assert(cb.setval.registry_value != NULL);
+ ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val_registry_value;
+ break;
+ case REGVAL_BLOB:
+ assert(cb.setval.regval_blob != NULL);
+ ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val_regval_blob;
+ break;
+ case NONE:
+ ret->val = NULL;
+ break;
+ default:
+ assert(false);
+ }
+
+ assert((struct reg_parse_callback *)p == ret);
+ return ret;
+fail:
+ talloc_free(p);
+ return NULL;
+}