/* * 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 . */ #include "includes.h" #include "reg_parse.h" #include "reg_import.h" #include "registry.h" #include "registry/reg_objects.h" #include /* 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%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) ®_parse_callback_key; ret->val_del = (reg_parse_callback_val_del_t) ®_parse_callback_val_del; ret->comment = (reg_parse_callback_comment_t) ®_parse_callback_comment; ret->data = p; switch (cb.setval_type) { case BLOB: assert(cb.setval.blob != NULL); ret->val = (reg_parse_callback_val_t) ®_parse_callback_val; break; case REGISTRY_VALUE: assert(cb.setval.registry_value != NULL); ret->val = (reg_parse_callback_val_t) ®_parse_callback_val_registry_value; break; case REGVAL_BLOB: assert(cb.setval.regval_blob != NULL); ret->val = (reg_parse_callback_val_t) ®_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; }