From c424c2b857fe08587eb81a5c5e3625545119d1c2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Apr 2004 16:24:08 +0000 Subject: r20: Add the registry library. Still needs a lot of work, see source/lib/registry/TODO for details. (This used to be commit 7cab3a00d7b4b1d95a3bfa6b28f318b4aaa5d493) --- source4/lib/registry/common/reg_display.c | 60 ++++ source4/lib/registry/common/reg_interface.c | 423 ++++++++++++++++++++++++++++ source4/lib/registry/common/reg_objects.c | 202 +++++++++++++ source4/lib/registry/common/reg_util.c | 164 +++++++++++ source4/lib/registry/common/registry.h | 121 ++++++++ 5 files changed, 970 insertions(+) create mode 100644 source4/lib/registry/common/reg_display.c create mode 100644 source4/lib/registry/common/reg_interface.c create mode 100644 source4/lib/registry/common/reg_objects.c create mode 100644 source4/lib/registry/common/reg_util.c create mode 100644 source4/lib/registry/common/registry.h (limited to 'source4/lib/registry/common') diff --git a/source4/lib/registry/common/reg_display.c b/source4/lib/registry/common/reg_display.c new file mode 100644 index 0000000000..e12f4ba20e --- /dev/null +++ b/source4/lib/registry/common/reg_display.c @@ -0,0 +1,60 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Gerald Carter 2001 + Copyright (C) Tim Potter 2000 + Copyright (C) Jelmer Vernooij 2004 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +void display_reg_value(REG_VAL *value) +{ + pstring text; + + switch(reg_val_type(value)) { + case REG_DWORD: + printf("%s: REG_DWORD: 0x%08x\n", reg_val_name(value), + *((uint32 *) reg_val_data_blk(value))); + break; + case REG_SZ: + rpcstr_pull(text, reg_val_data_blk(value), sizeof(text), reg_val_size(value), + STR_TERMINATE); + printf("%s: REG_SZ: %s\n", reg_val_name(value), text); + break; + case REG_BINARY: + printf("%s: REG_BINARY: unknown length value not displayed\n", + reg_val_name(value)); + break; + case REG_MULTI_SZ: { + uint16 *curstr = (uint16 *) reg_val_data_blk(value); + uint8 *start = reg_val_data_blk(value); + printf("%s: REG_MULTI_SZ:\n", reg_val_name(value)); + while ((*curstr != 0) && + ((uint8 *) curstr < start + reg_val_size(value))) { + rpcstr_pull(text, curstr, sizeof(text), -1, + STR_TERMINATE); + printf(" %s\n", text); + curstr += strlen(text) + 1; + } + } + break; + default: + printf("%s: unknown type %d\n", reg_val_name(value), reg_val_type(value)); + } + +} diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c new file mode 100644 index 0000000000..dc49dab4c1 --- /dev/null +++ b/source4/lib/registry/common/reg_interface.c @@ -0,0 +1,423 @@ +/* + Unix SMB/CIFS implementation. + Transparent registry backend handling + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +/* List of available backends */ +static struct reg_init_function_entry *backends = NULL; + +static struct reg_init_function_entry *reg_find_backend_entry(const char *name); + +/* Register new backend */ +NTSTATUS registry_register(void *_function) +{ + REG_OPS *functions = _function; + struct reg_init_function_entry *entry = backends; + + if (!functions || !functions->name) { + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(5,("Attempting to register registry backend %s\n", functions->name)); + + /* Check for duplicates */ + if (reg_find_backend_entry(functions->name)) { + DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = malloc(sizeof(struct reg_init_function_entry)); + entry->functions = functions; + + DLIST_ADD(backends, entry); + DEBUG(5,("Successfully added registry backend '%s'\n", functions->name)); + return NT_STATUS_OK; +} + + +/* Find a backend in the list of available backends */ +static struct reg_init_function_entry *reg_find_backend_entry(const char *name) +{ + struct reg_init_function_entry *entry = backends; + + while(entry) { + if (strcmp(entry->functions->name, name)==0) return entry; + entry = entry->next; + } + + return NULL; +} + +/* Open a registry file/host/etc */ +REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_load) +{ + struct reg_init_function_entry *entry; + static BOOL reg_first_init = True; + REG_HANDLE *ret; + + if(reg_first_init) { + if (!NT_STATUS_IS_OK(register_subsystem("registry", registry_register))) { + return False; + } + + static_init_reg; + reg_first_init = False; + } + + entry = reg_find_backend_entry(backend); + + if (!entry) { + DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); + return NULL; + } + + ret = malloc(sizeof(REG_HANDLE)); + ZERO_STRUCTP(ret); + ret->location = location?strdup(location):NULL; + ret->functions = entry->functions; + ret->backend_data = NULL; + + if(!entry->functions->open_registry) { + return ret; + } + + if(entry->functions->open_registry(ret, location, try_full_load)) + return ret; + + SAFE_FREE(ret); + return NULL; +} + +/* Open a key */ +REG_KEY *reg_open_key(REG_KEY *parent, const char *name) +{ + char *fullname; + REG_KEY *ret = NULL; + + if(!parent) { + DEBUG(0, ("Invalid parent key specified")); + return NULL; + } + + if(!parent->handle->functions->open_key && + (parent->handle->functions->get_subkey_by_name || + parent->handle->functions->get_subkey_by_index)) { + char *orig = strdup(name), + *curbegin = orig, + *curend = strchr(orig, '\\'); + REG_KEY *curkey = parent; + + while(curbegin && *curbegin) { + if(curend)*curend = '\0'; + curkey = reg_key_get_subkey_by_name(curkey, curbegin); + if(!curkey) return NULL; + if(!curend) break; + curbegin = curend + 1; + curend = strchr(curbegin, '\\'); + } + + return curkey; + } + + asprintf(&fullname, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); + + if(!parent->handle->functions->open_key) { + DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); + return NULL; + } + + ret = parent->handle->functions->open_key(parent->handle, fullname); + + if(ret) { + ret->handle = parent->handle; + ret->path = fullname; + } else + SAFE_FREE(fullname); + + return ret; +} + +REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx) +{ + REG_VAL *ret; + + if(!key) return NULL; + + if(!key->handle->functions->get_value_by_index) { + if(!key->cache_values) + key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); + + if(idx < key->cache_values_count && idx >= 0) { + ret = reg_val_dup(key->cache_values[idx]); + } else { + return NULL; + } + } else { + ret = key->handle->functions->get_value_by_index(key, idx); + } + + if(ret) { + ret->parent = key; + ret->handle = key->handle; + } + + return ret; +} + +int reg_key_num_subkeys(REG_KEY *key) +{ + if(!key->handle->functions->num_subkeys) { + if(!key->cache_subkeys) + key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + + return key->cache_subkeys_count; + } + + return key->handle->functions->num_subkeys(key); +} + +int reg_key_num_values(REG_KEY *key) +{ + + if(!key) return 0; + + if(!key->handle->functions->num_values) { + if(!key->handle->functions->fetch_values) { + DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); + return 0; + } + + if(!key->cache_values) + key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); + + return key->cache_values_count; + } + + + return key->handle->functions->num_values(key); +} + +REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx) +{ + REG_KEY *ret = NULL; + + if(!key) return NULL; + + if(!key->handle->functions->get_subkey_by_index) { + if(!key->cache_subkeys) + key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + + if(idx < key->cache_subkeys_count) { + ret = reg_key_dup(key->cache_subkeys[idx]); + } else { + /* No such key ! */ + return NULL; + } + } else { + ret = key->handle->functions->get_subkey_by_index(key, idx); + } + + if(ret && !ret->path) { + asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->handle = key->handle; + } + + return ret; +} + +REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name) +{ + int i, max; + REG_KEY *ret = NULL; + + if(!key) return NULL; + + if(key->handle->functions->get_subkey_by_name) { + ret = key->handle->functions->get_subkey_by_name(key,name); + } else { + max = reg_key_num_subkeys(key); + for(i = 0; i < max; i++) { + REG_KEY *v = reg_key_get_subkey_by_index(key, i); + if(v && !strcmp(v->name, name)) { + ret = v; + break; + } + reg_key_free(v); + } + } + + if(ret && !ret->path) { + asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->handle = key->handle; + } + + return ret; +} + +REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name) +{ + int i, max; + REG_VAL *ret = NULL; + + if(!key) return NULL; + + if(key->handle->functions->get_value_by_name) { + ret = key->handle->functions->get_value_by_name(key,name); + } else { + max = reg_key_num_values(key); + for(i = 0; i < max; i++) { + REG_VAL *v = reg_key_get_value_by_index(key, i); + if(v && StrCaseCmp(v->name, name)) { + ret = v; + break; + } + reg_val_free(v); + } + } + + if(ret) { + ret->parent = key; + ret->handle = key->handle; + } + + return ret; +} + +BOOL reg_key_del(REG_KEY *key) +{ + if(key->handle->functions->del_key) + return key->handle->functions->del_key(key); + + return False; +} + +BOOL reg_sync(REG_HANDLE *h, const char *location) +{ + if(!h->functions->sync) + return True; + + return h->functions->sync(h, location); +} + +BOOL reg_key_del_recursive(REG_KEY *key) +{ + BOOL succeed = True; + int i; + + /* Delete all values for specified key */ + for(i = 0; i < reg_key_num_values(key); i++) { + if(!reg_val_del(reg_key_get_value_by_index(key, i))) + succeed = False; + } + + /* Delete all keys below this one */ + for(i = 0; i < reg_key_num_subkeys(key); i++) { + if(!reg_key_del_recursive(reg_key_get_subkey_by_index(key, i))) + succeed = False; + } + + if(succeed)reg_key_del(key); + + return succeed; +} + +BOOL reg_val_del(REG_VAL *val) +{ + if (!val->handle->functions->del_value) { + DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); + return False; + } + + return val->handle->functions->del_value(val); +} + +BOOL reg_key_add_name(REG_KEY *parent, const char *name) +{ + if (!parent->handle->functions->add_key) { + DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); + return False; + } + + return parent->handle->functions->add_key(parent, name); +} + +BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) +{ + /* A 'real' update function has preference */ + if (val->handle->functions->update_value) + return val->handle->functions->update_value(val, type, data, len); + + /* Otherwise, just remove and add again */ + if (val->handle->functions->add_value && + val->handle->functions->del_value) { + REG_VAL *new; + if(!val->handle->functions->del_value(val)) + return False; + + new = val->handle->functions->add_value(val->parent, val->name, type, data, len); + memcpy(val, new, sizeof(REG_VAL)); + return True; + } + + DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); + return False; +} + +void reg_free(REG_HANDLE *h) +{ + if(!h->functions->close_registry) return; + + h->functions->close_registry(h); +} + +REG_KEY *reg_get_root(REG_HANDLE *h) +{ + REG_KEY *ret = NULL; + if(h->functions->open_root_key) { + ret = h->functions->open_root_key(h); + } else if(h->functions->open_key) { + ret = h->functions->open_key(h, "\\"); + } else { + DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name)); + } + + if(ret) { + ret->handle = h; + ret->path = strdup("\\"); + } + + return ret; +} + +REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +{ + REG_VAL *ret; + if(!key->handle->functions->add_value) + return NULL; + + ret = key->handle->functions->add_value(key, name, type, value, vallen); + ret->parent = key; + ret->handle = key->handle; + return ret; +} diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c new file mode 100644 index 0000000000..911dc15c8e --- /dev/null +++ b/source4/lib/registry/common/reg_objects.c @@ -0,0 +1,202 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2002. + * Copyright (C) Jelmer Vernooij 2003-2004. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of registry frontend view functions. */ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/*********************************************************************** + allocate memory for and duplicate a REG_VAL. + This is malloc'd memory so the caller should free it when done + **********************************************************************/ + +REG_VAL* reg_val_dup( REG_VAL *val ) +{ + REG_VAL *copy = NULL; + + if ( !val ) + return NULL; + + if ( !(copy = malloc( sizeof(REG_VAL) )) ) { + DEBUG(0,("dup_registry_value: malloc() failed!\n")); + return NULL; + } + + /* copy all the non-pointer initial data */ + + memcpy( copy, val, sizeof(REG_VAL) ); + if ( val->data_blk ) + { + if ( !(copy->data_blk = memdup( val->data_blk, val->data_len )) ) { + DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n", + val->data_len)); + SAFE_FREE( copy ); + } + } + + return copy; +} + +/********************************************************************** + free the memory allocated to a REG_VAL + *********************************************************************/ + +void reg_val_free( REG_VAL *val ) +{ + if ( !val ) + return; + + if(val->handle->functions->free_val_backend_data) + val->handle->functions->free_val_backend_data(val); + + SAFE_FREE( val->data_blk ); + SAFE_FREE( val ); + + return; +} + +/********************************************************************** + *********************************************************************/ + +uint8* reg_val_data_blk( REG_VAL *val ) +{ + return val->data_blk; +} + +/********************************************************************** + *********************************************************************/ + +int reg_val_size( REG_VAL *val ) +{ + return val->data_len; +} + +/********************************************************************** + *********************************************************************/ + +char *reg_val_name( REG_VAL *val ) +{ + return val->name; +} + +/********************************************************************** + *********************************************************************/ + +uint32 reg_val_type( REG_VAL *val ) +{ + return val->data_type; +} + +/********************************************************************** + *********************************************************************/ + +char *reg_key_name( REG_KEY *key ) +{ + return key->name; +} + +REG_KEY *reg_key_dup(REG_KEY *key) +{ + key->ref++; + return key; +} + +void reg_key_free(REG_KEY *key) +{ + if(!key) + return; + + key->ref--; + if(key->ref) return; + + if(key->handle->functions->free_key_backend_data) + key->handle->functions->free_key_backend_data(key); + + if(key->cache_values) { + int i; + for(i = 0; i < key->cache_values_count; i++) { + reg_val_free(key->cache_values[i]); + } + SAFE_FREE(key->cache_values); + } + + if(key->cache_subkeys) { + int i; + for(i = 0; i < key->cache_subkeys_count; i++) { + reg_key_free(key->cache_subkeys[i]); + } + SAFE_FREE(key->cache_subkeys); + } + + SAFE_FREE(key->path); + SAFE_FREE(key->name); + SAFE_FREE(key); +} + +char *reg_val_get_path(REG_VAL *v) +{ + /* FIXME */ + return NULL; +} + +char *reg_key_get_path(REG_KEY *k) +{ + SMB_REG_ASSERT(k); + return k->path; +} + +/* For use by the backends _ONLY_ */ +REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) +{ + REG_KEY *r = malloc(sizeof(REG_KEY)); + ZERO_STRUCTP(r); + r->handle = h; + r->path = strdup(path); + r->name = strdup(strrchr(path, '\\')?strrchr(path,'\\')+1:path); + r->backend_data = data; + r->ref = 1; + return r; +} + +REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) +{ + REG_KEY *r = malloc(sizeof(REG_KEY)); + ZERO_STRUCTP(r); + r->handle = k->handle; + r->name = strdup(name); + r->backend_data = data; + r->ref = 1; + return r; +} + +REG_VAL *reg_val_new(REG_KEY *parent, void *data) +{ + REG_VAL *r = malloc(sizeof(REG_VAL)); + ZERO_STRUCTP(r); + r->handle = parent->handle; + r->backend_data = data; + r->ref = 1; + return r; +} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c new file mode 100644 index 0000000000..2941c38cf4 --- /dev/null +++ b/source4/lib/registry/common/reg_util.c @@ -0,0 +1,164 @@ +/* + Unix SMB/CIFS implementation. + Transparent registry backend handling + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +/* Return string description of registry value type */ +const char *str_regtype(int type) +{ + switch(type) { + case REG_SZ: return "STRING"; + case REG_DWORD: return "DWORD"; + case REG_BINARY: return "BINARY"; + } + return "Unknown"; +} + +char *reg_val_data_string(REG_VAL *v) +{ + char *asciip; + char *ret = NULL; + int i; + + if(reg_val_size(v) == 0) return strdup(""); + + switch (reg_val_type(v)) { + case REG_SZ: + /* FIXME: Convert to ascii */ + return strdup(reg_val_data_blk(v)); + + case REG_EXPAND_SZ: + return strdup(reg_val_data_blk(v)); + + case REG_BINARY: + ret = malloc(reg_val_size(v) * 3 + 2); + asciip = ret; + for (i=0; i 0) + *asciip = ' '; asciip++; + } + *asciip = '\0'; + return ret; + break; + + case REG_DWORD: + if (*(int *)reg_val_data_blk(v) == 0) + ret = strdup("0"); + else + asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v)); + break; + + case REG_MULTI_SZ: + /* FIXME */ + break; + + default: + return 0; + break; + } + + return ret; +} + +const char *reg_val_description(REG_VAL *val) +{ + char *ret, *ds = reg_val_data_string(val); + asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"", str_regtype(reg_val_type(val)), ds); + free(ds); + return ret; +} + +BOOL reg_val_set_string(REG_VAL *val, char *str) +{ + /* FIXME */ + return False; +} + +REG_VAL *reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname) +{ + REG_KEY *k = reg_key_get_subkey_by_name(key, subname); + if(!k) return NULL; + + return reg_key_get_value_by_name(k, valname); +} + +BOOL reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len) +{ + REG_KEY *k = reg_key_get_subkey_by_name(key, subname); + REG_VAL *v; + if(!k) return False; + + v = reg_key_get_value_by_name(k, valname); + if(!v) return False; + + return reg_val_update(v, type, data, real_len); +} + +/*********************************************************************** + Utility function for splitting the base path of a registry path off + by setting base and new_path to the apprapriate offsets withing the + path. + + WARNING!! Does modify the original string! + ***********************************************************************/ + +BOOL reg_split_path( char *path, char **base, char **new_path ) +{ + char *p; + + *new_path = *base = NULL; + + if ( !path) + return False; + + *base = path; + + p = strchr( path, '\\' ); + + if ( p ) { + *p = '\0'; + *new_path = p+1; + } + + return True; +} + +char *reg_path_win2unix(char *path) +{ + int i; + for(i = 0; path[i]; i++) { + if(path[i] == '\\') path[i] = '/'; + } + return path; +} + +char *reg_path_unix2win(char *path) +{ + int i; + for(i = 0; path[i]; i++) { + if(path[i] == '/') path[i] = '\\'; + } + return path; +} diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h new file mode 100644 index 0000000000..4b29006217 --- /dev/null +++ b/source4/lib/registry/common/registry.h @@ -0,0 +1,121 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + This file contains the _internal_ structs for the registry + subsystem. Backends and the subsystem itself are the only + files that need to include this file. + Copyright (C) Gerald Carter 2002. + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */ +#define _REGISTRY_REGISTRY_H + +#define REGISTRY_INTERFACE_VERSION 1 + +/* structure to store the registry handles */ +struct reg_key_s { + char *name; /* Name of the key */ + char *path; /* Full path to the key */ + smb_ucs2_t *class_name; /* Name of key class */ + NTTIME last_mod; /* Time last modified */ + SEC_DESC *security; + REG_HANDLE *handle; + void *backend_data; + REG_VAL **cache_values; + int cache_values_count; + REG_KEY **cache_subkeys; + int cache_subkeys_count; + int ref; +}; + +struct reg_val_s { + char *name; + int has_name; + int data_type; + int data_len; + void *data_blk; /* Might want a separate block */ + REG_HANDLE *handle; + REG_KEY *parent; + void *backend_data; + int ref; +}; + +/* + * Container for function pointers to enumeration routines + * for virtual registry view + */ + +struct reg_ops_s { + const char *name; + BOOL (*open_registry) (REG_HANDLE *, const char *location, BOOL try_complete_load); + BOOL (*sync)(REG_HANDLE *, const char *location); + BOOL (*close_registry) (REG_HANDLE *); + + /* Either implement these */ + REG_KEY *(*open_root_key) (REG_HANDLE *); + int (*num_subkeys) (REG_KEY *); + int (*num_values) (REG_KEY *); + REG_KEY *(*get_subkey_by_index) (REG_KEY *, int idx); + REG_KEY *(*get_subkey_by_name) (REG_KEY *, const char *name); + REG_VAL *(*get_value_by_index) (REG_KEY *, int idx); + REG_VAL *(*get_value_by_name) (REG_KEY *, const char *name); + + /* Or these */ + REG_KEY *(*open_key) (REG_HANDLE *, const char *name); + BOOL (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); + BOOL (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); + + /* Key management */ + BOOL (*add_key)(REG_KEY *, const char *name); + BOOL (*del_key)(REG_KEY *); + + /* Value management */ + REG_VAL *(*add_value)(REG_KEY *, const char *name, int type, void *data, int len); + BOOL (*del_value)(REG_VAL *); + + /* If update is not available, value will first be deleted and then added + * again */ + BOOL (*update_value)(REG_VAL *, int type, void *data, int len); + + void (*free_key_backend_data) (REG_KEY *); + void (*free_val_backend_data) (REG_VAL *); +}; + +typedef struct reg_sub_tree_s { + char *path; + REG_HANDLE *handle; + struct reg_sub_tree_s *prev, *next; +} REG_SUBTREE; + +struct reg_handle_s { + REG_OPS *functions; + REG_SUBTREE *subtrees; + char *location; + void *backend_data; +}; + +struct reg_init_function_entry { + /* Function to create a member of the pdb_methods list */ + REG_OPS *functions; + struct reg_init_function_entry *prev, *next; +}; + +/* Used internally */ +#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} + +#endif /* _REGISTRY_H */ -- cgit