/*
* 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;
}