diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/registry/common/reg_display.c | 60 | ||||
-rw-r--r-- | source4/lib/registry/common/reg_interface.c | 70 | ||||
-rw-r--r-- | source4/lib/registry/common/reg_objects.c | 36 | ||||
-rw-r--r-- | source4/lib/registry/common/reg_util.c | 9 | ||||
-rw-r--r-- | source4/lib/registry/common/registry.h | 3 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_dir/reg_backend_dir.c | 28 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c | 37 |
7 files changed, 102 insertions, 141 deletions
diff --git a/source4/lib/registry/common/reg_display.c b/source4/lib/registry/common/reg_display.c deleted file mode 100644 index e12f4ba20e..0000000000 --- a/source4/lib/registry/common/reg_display.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - 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 index d40a855f89..b6b38e9b62 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -55,7 +55,6 @@ NTSTATUS registry_register(void *_function) 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) { @@ -74,6 +73,7 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo { struct reg_init_function_entry *entry; static BOOL reg_first_init = True; + TALLOC_CTX *mem_ctx; REG_HANDLE *ret; if(reg_first_init) { @@ -91,12 +91,14 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); return NULL; } - - ret = malloc(sizeof(REG_HANDLE)); + + mem_ctx = talloc_init(backend); + ret = talloc(mem_ctx, sizeof(REG_HANDLE)); ZERO_STRUCTP(ret); - ret->location = location?strdup(location):NULL; + ret->location = location?talloc_strdup(mem_ctx, location):NULL; ret->functions = entry->functions; ret->backend_data = NULL; + ret->mem_ctx = mem_ctx; if(!entry->functions->open_registry) { return ret; @@ -105,15 +107,19 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo if(entry->functions->open_registry(ret, location, try_full_load)) return ret; - SAFE_FREE(ret); + talloc_destroy(mem_ctx); return NULL; } -/* Open a key */ +/* Open a key + * First tries to use the open_key function from the backend + * then falls back to get_subkey_by_name and later get_subkey_by_index + */ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) { char *fullname; REG_KEY *ret = NULL; + TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); @@ -131,16 +137,23 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) while(curbegin && *curbegin) { if(curend)*curend = '\0'; curkey = reg_key_get_subkey_by_name(curkey, curbegin); - if(!curkey) return NULL; + if(!curkey) { + SAFE_FREE(orig); + return NULL; + } if(!curend) break; curbegin = curend + 1; curend = strchr(curbegin, '\\'); } + SAFE_FREE(orig); return curkey; } - asprintf(&fullname, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); + mem_ctx = talloc_init("mem_ctx"); + + fullname = talloc_asprintf(mem_ctx, "%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")); @@ -152,8 +165,10 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) if(ret) { ret->handle = parent->handle; ret->path = fullname; - } else - SAFE_FREE(fullname); + talloc_steal(mem_ctx, ret->mem_ctx, fullname); + } + + talloc_destroy(mem_ctx); return ret; } @@ -241,7 +256,7 @@ REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx) } if(ret && !ret->path) { - asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); ret->handle = key->handle; } @@ -270,7 +285,7 @@ REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name) } if(ret && !ret->path) { - asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); ret->handle = key->handle; } @@ -310,7 +325,9 @@ BOOL reg_key_del(REG_KEY *key) { if(key->handle->functions->del_key) { if(key->handle->functions->del_key(key)) { - free_cached_keys(key); + /* Invalidate cache */ + key->cache_subkeys = NULL; + key->cache_subkeys_count = 0; return True; } } @@ -356,7 +373,8 @@ BOOL reg_val_del(REG_VAL *val) } if(val->handle->functions->del_value(val)) { - free_cached_values(val->parent); + val->parent->cache_values = NULL; + val->parent->cache_values_count = 0; return True; } return False; @@ -398,7 +416,8 @@ BOOL reg_key_add_name(REG_KEY *parent, const char *name) } if(parent->handle->functions->add_key(parent, name)) { - free_cached_keys(parent); + parent->cache_subkeys = NULL; + parent->cache_subkeys_count = 0; return True; } return False; @@ -419,7 +438,8 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) new = val->handle->functions->add_value(val->parent, val->name, type, data, len); memcpy(val, new, sizeof(REG_VAL)); - free_cached_values(val->parent); + val->parent->cache_values = NULL; + val->parent->cache_values_count = 0; return True; } @@ -447,7 +467,7 @@ REG_KEY *reg_get_root(REG_HANDLE *h) if(ret) { ret->handle = h; - ret->path = strdup("\\"); + ret->path = talloc_strdup(ret->mem_ctx, "\\"); } return ret; @@ -462,19 +482,9 @@ REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value ret = key->handle->functions->add_value(key, name, type, value, vallen); ret->parent = key; ret->handle = key->handle; - free_cached_values(key); - return ret; -} -void free_cached_values(REG_KEY *key) -{ - free(key->cache_values); key->cache_values = NULL; + /* Invalidate the cache */ + key->cache_values = NULL; key->cache_values_count = 0; -} - - -void free_cached_keys(REG_KEY *key) -{ - free(key->cache_subkeys); key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; + return ret; } diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 8de0065da0..809829b3e8 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -35,11 +35,12 @@ REG_VAL* reg_val_dup( REG_VAL *val ) { REG_VAL *copy = NULL; + TALLOC_CTX *new_mem_ctx = talloc_init(val->name); if ( !val ) return NULL; - if ( !(copy = malloc( sizeof(REG_VAL) )) ) { + if ( !(copy = talloc( new_mem_ctx, sizeof(REG_VAL) )) ) { DEBUG(0,("dup_registry_value: malloc() failed!\n")); return NULL; } @@ -49,12 +50,13 @@ REG_VAL* reg_val_dup( REG_VAL *val ) memcpy( copy, val, sizeof(REG_VAL) ); if ( val->data_blk ) { - if ( !(copy->data_blk = memdup( val->data_blk, val->data_len )) ) { + if ( !(copy->data_blk = talloc_memdup( new_mem_ctx, val->data_blk, val->data_len )) ) { DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n", val->data_len)); SAFE_FREE( copy ); } } + copy->mem_ctx = new_mem_ctx; return copy; } @@ -71,8 +73,7 @@ void reg_val_free( REG_VAL *val ) if(val->handle->functions->free_val_backend_data) val->handle->functions->free_val_backend_data(val); - SAFE_FREE( val->data_blk ); - SAFE_FREE( val ); + talloc_destroy( val->mem_ctx ); return; } @@ -139,7 +140,6 @@ void reg_key_free(REG_KEY *key) 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) { @@ -147,12 +147,9 @@ void reg_key_free(REG_KEY *key) 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); + talloc_destroy(key->mem_ctx); } char *reg_val_get_path(REG_VAL *v) @@ -170,11 +167,14 @@ const char *reg_key_get_path(REG_KEY *k) /* 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)); + REG_KEY *r; + TALLOC_CTX *mem_ctx = talloc_init(path); + r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = h; - r->path = strdup(path); - r->name = strdup(strrchr(path, '\\')?strrchr(path,'\\')+1:path); + r->mem_ctx = mem_ctx; + r->path = talloc_strdup(mem_ctx, path); + r->name = talloc_strdup(mem_ctx, strrchr(path, '\\')?strrchr(path,'\\')+1:path); r->backend_data = data; r->ref = 1; return r; @@ -182,19 +182,25 @@ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) { - REG_KEY *r = malloc(sizeof(REG_KEY)); + REG_KEY *r; + TALLOC_CTX *mem_ctx = talloc_init(name); + r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = k->handle; - r->name = strdup(name); + r->name = talloc_strdup(mem_ctx, name); r->backend_data = data; + r->mem_ctx = mem_ctx; r->ref = 1; return r; } REG_VAL *reg_val_new(REG_KEY *parent, void *data) { - REG_VAL *r = malloc(sizeof(REG_VAL)); + REG_VAL *r; + TALLOC_CTX *mem_ctx = talloc_init("value"); + r = talloc(mem_ctx, sizeof(REG_VAL)); ZERO_STRUCTP(r); + r->mem_ctx = mem_ctx; r->handle = parent->handle; r->backend_data = data; r->ref = 1; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 2941c38cf4..060d053fc2 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -82,7 +82,7 @@ char *reg_val_data_string(REG_VAL *v) return ret; } -const char *reg_val_description(REG_VAL *val) +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):"<No Name>", str_regtype(reg_val_type(val)), ds); @@ -145,6 +145,9 @@ BOOL reg_split_path( char *path, char **base, char **new_path ) return True; } +/** + * Replace all \'s with /'s + */ char *reg_path_win2unix(char *path) { int i; @@ -153,7 +156,9 @@ char *reg_path_win2unix(char *path) } return path; } - +/** + * Replace all /'s with \'s + */ char *reg_path_unix2win(char *path) { int i; diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 4b29006217..3565a7a585 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -40,6 +40,7 @@ struct reg_key_s { int cache_values_count; REG_KEY **cache_subkeys; int cache_subkeys_count; + TALLOC_CTX *mem_ctx; int ref; }; @@ -52,6 +53,7 @@ struct reg_val_s { REG_HANDLE *handle; REG_KEY *parent; void *backend_data; + TALLOC_CTX *mem_ctx; int ref; }; @@ -107,6 +109,7 @@ struct reg_handle_s { REG_SUBTREE *subtrees; char *location; void *backend_data; + TALLOC_CTX *mem_ctx; }; struct reg_init_function_entry { diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 5fec782e95..9cb15cd285 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -28,7 +28,7 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name); path = reg_path_win2unix(path); ret = mkdir(path, 0700); - free(path); + SAFE_FREE(path); return (ret == 0); } @@ -41,22 +41,26 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) { DIR *d; char *fullpath; + REG_KEY *ret; + TALLOC_CTX *mem_ctx = talloc_init("tmp"); if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); return NULL; } - asprintf(&fullpath, "%s%s", h->location, name); + fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); d = opendir(fullpath); if(!d) { DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); - SAFE_FREE(fullpath); + talloc_destroy(mem_ctx); return NULL; } closedir(d); - - return reg_key_new_abs(name, h, fullpath); + ret = reg_key_new_abs(name, h, fullpath); + talloc_steal(mem_ctx, ret->mem_ctx, fullpath); + talloc_destroy(mem_ctx); + return ret; } static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) @@ -67,7 +71,7 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) REG_KEY **ar; DIR *d; (*count) = 0; - ar = malloc(sizeof(REG_KEY *) * max); + ar = talloc(k->mem_ctx, sizeof(REG_KEY *) * max); d = opendir(fullpath); @@ -78,8 +82,8 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { char *newfullpath; - asprintf(&newfullpath, "%s/%s", fullpath, e->d_name); - ar[(*count)] = reg_key_new_rel(e->d_name, k, newfullpath); + ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); + ar[(*count)]->backend_data = talloc_asprintf(ar[*count]->mem_ctx, "%s/%s", fullpath, e->d_name); if(ar[(*count)])(*count)++; if((*count) == max) { @@ -100,17 +104,12 @@ static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) { return True; } -static void dir_free(REG_KEY *k) -{ - free(k->backend_data); -} - static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) { REG_VAL *ret = reg_val_new(p, NULL); char *fullpath; FILE *fd; - ret->name = name?strdup(name):NULL; + ret->name = name?talloc_strdup(ret->mem_ctx, name):NULL; fullpath = reg_path_win2unix(strdup(reg_val_get_path(ret))); fd = fopen(fullpath, "w+"); @@ -134,7 +133,6 @@ static REG_OPS reg_backend_dir = { .del_key = reg_dir_del_key, .add_value = reg_dir_add_value, .del_value = reg_dir_del_value, - .free_key_backend_data = dir_free }; NTSTATUS reg_dir_init(void) diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 14da2f54e9..71d3361ce2 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -35,34 +35,35 @@ static BOOL reg_close_gconf(REG_HANDLE *h) static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name) { + REG_KEY *ret; char *fullpath = reg_path_win2unix(strdup(name)); /* Check if key exists */ if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { - free(fullpath); + SAFE_FREE(fullpath); return NULL; } - free(fullpath); + ret = reg_key_new_abs(name, h, NULL); + ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath); + SAFE_FREE(fullpath); - return reg_key_new_abs(name, h, NULL); + return ret; } static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) { GSList *entries; GSList *cur; - REG_VAL **ar = malloc(sizeof(REG_VAL *)); - char *fullpath = strdup(reg_key_get_path(p)); - fullpath = reg_path_win2unix(fullpath); + REG_VAL **ar = talloc(p->mem_ctx, sizeof(REG_VAL *)); + char *fullpath = p->backend_data; cur = entries = gconf_client_all_entries((GConfClient*)p->handle->backend_data, fullpath, NULL); - free(fullpath); (*count) = 0; while(cur) { GConfEntry *entry = cur->data; GConfValue *value = gconf_entry_get_value(entry); REG_VAL *newval = reg_val_new(p, NULL); - newval->name = strdup(strrchr(gconf_entry_get_key(entry), '/')+1); + newval->name = talloc_strdup(newval->mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); if(value) { switch(value->type) { case GCONF_VALUE_INVALID: @@ -71,26 +72,26 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) case GCONF_VALUE_STRING: newval->data_type = REG_SZ; - newval->data_blk = strdup(gconf_value_get_string(value)); + newval->data_blk = talloc_strdup(newval->mem_ctx, gconf_value_get_string(value)); newval->data_len = strlen(newval->data_blk); break; case GCONF_VALUE_INT: newval->data_type = REG_DWORD; - newval->data_blk = malloc(sizeof(long)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(long)); *((long *)newval->data_blk) = gconf_value_get_int(value); newval->data_len = sizeof(long); break; case GCONF_VALUE_FLOAT: - newval->data_blk = malloc(sizeof(double)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(double)); newval->data_type = REG_BINARY; *((double *)newval->data_blk) = gconf_value_get_float(value); newval->data_len = sizeof(double); break; case GCONF_VALUE_BOOL: - newval->data_blk = malloc(sizeof(BOOL)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(BOOL)); newval->data_type = REG_BINARY; *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); newval->data_len = sizeof(BOOL); @@ -104,7 +105,7 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) } else newval->data_type = REG_NONE; ar[(*count)] = newval; - ar = realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); + ar = talloc_realloc(p->mem_ctx, ar, sizeof(REG_VAL *) * ((*count)+2)); (*count)++; g_free(cur->data); cur = cur->next; @@ -120,14 +121,13 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) GSList *dirs; GSList *cur; REG_KEY **ar = malloc(sizeof(REG_KEY *)); - char *fullpath = strdup(reg_key_get_path(p)); - fullpath = reg_path_win2unix(fullpath); + char *fullpath = p->backend_data; cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); - free(fullpath); (*count) = 0; while(cur) { - ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle, NULL); + ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle,NULL); + ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, cur->data); ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+2)); (*count)++; g_free(cur->data); @@ -142,11 +142,10 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len) { GError *error = NULL; - char *keypath = reg_path_win2unix(strdup(reg_key_get_path(val->parent))); + char *keypath = val->backend_data; char *valpath; if(val->name)asprintf(&valpath, "%s/%s", keypath, val->name); else valpath = strdup(keypath); - free(keypath); switch(type) { case REG_SZ: |