r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
[bbaumbach/samba-autobuild/.git] / source4 / lib / registry / common / reg_interface.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Transparent registry backend handling
4    Copyright (C) Jelmer Vernooij                        2003-2004.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "dlinklist.h"
23 #include "registry.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_REGISTRY
27
28 /* List of available backends */
29 static struct reg_init_function_entry *backends = NULL;
30
31 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
32
33 /* Register new backend */
34 NTSTATUS registry_register(const void *_hive_ops)  
35 {
36         const struct hive_operations *hive_ops = _hive_ops;
37         struct reg_init_function_entry *entry = backends;
38
39         DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
40
41         /* Check for duplicates */
42         if (reg_find_backend_entry(hive_ops->name)) {
43                 DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
44                 return NT_STATUS_OBJECT_NAME_COLLISION;
45         }
46
47         entry = talloc(talloc_autofree_context(), struct reg_init_function_entry);
48         entry->hive_functions = hive_ops;
49
50         DLIST_ADD(backends, entry);
51         DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
52         return NT_STATUS_OK;
53 }
54
55 /* Find a backend in the list of available backends */
56 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
57 {
58         struct reg_init_function_entry *entry;
59
60         entry = backends;
61
62         while(entry) {
63                 if (strcmp(entry->hive_functions->name, name) == 0) return entry;
64                 entry = entry->next;
65         }
66
67         return NULL;
68 }
69
70 /* Check whether a certain backend is present */
71 BOOL reg_has_backend(const char *backend)
72 {
73         return reg_find_backend_entry(backend) != NULL?True:False;
74 }
75
76 static struct {
77         uint32_t handle;
78         const char *name;
79 } predef_names[] = 
80 {
81         {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
82         {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
83         {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
84         {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
85         {HKEY_USERS, "HKEY_USERS" },
86         {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
87         {HKEY_DYN_DATA, "HKEY_DYN_DATA" },
88         {HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
89         {HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
90         { 0, NULL }
91 };
92
93 int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys)
94 {
95         int i;
96         *predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(predef_names));
97         *hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(predef_names));
98
99         for (i = 0; predef_names[i].name; i++) {
100                 (*predefs)[i] = talloc_strdup(mem_ctx, predef_names[i].name);
101                 (*hkeys)[i] = predef_names[i].handle;
102         }
103
104         return i;
105 }
106
107 const char *reg_get_predef_name(uint32_t hkey)
108 {
109         int i;
110         for (i = 0; predef_names[i].name; i++) {
111                 if (predef_names[i].handle == hkey) return predef_names[i].name;
112         }
113
114         return NULL;
115 }
116
117 WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
118 {
119         int i;
120         
121         for (i = 0; predef_names[i].name; i++) {
122                 if (!strcasecmp(predef_names[i].name, name)) return reg_get_predefined_key(ctx, predef_names[i].handle, key);
123         }
124
125         DEBUG(1, ("No predefined key with name '%s'\n", name));
126         
127         return WERR_BADFILE;
128 }
129
130 WERROR reg_close (struct registry_context *ctx)
131 {
132         talloc_free(ctx);
133
134         return WERR_OK;
135 }
136
137 WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
138 {
139         WERROR ret = ctx->get_predefined_key(ctx, hkey, key);
140
141         if (W_ERROR_IS_OK(ret)) {
142                 (*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey));
143                 (*key)->path = ""; 
144         }
145
146         return ret;
147 }
148
149 /* Open a registry file/host/etc */
150 WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root)
151 {
152         struct registry_hive *rethive;
153         struct registry_key *retkey = NULL;
154         struct reg_init_function_entry *entry;
155         WERROR werr;
156
157         entry = reg_find_backend_entry(backend);
158         
159         if (!entry) {
160                 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
161                 return WERR_GENERAL_FAILURE;
162         }
163
164         if(!entry->hive_functions || !entry->hive_functions->open_hive) {
165                 return WERR_NOT_SUPPORTED;
166         }
167         
168         rethive = talloc(parent_ctx, struct registry_hive);
169         rethive->location = location?talloc_strdup(rethive, location):NULL;
170         rethive->functions = entry->hive_functions;
171         rethive->backend_data = NULL;
172
173         werr = entry->hive_functions->open_hive(rethive, &retkey);
174
175         if(!W_ERROR_IS_OK(werr)) {
176                 return werr;
177         }
178
179         if(!retkey) {
180                 DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
181                 return WERR_GENERAL_FAILURE;
182         }
183
184         rethive->root = retkey;
185
186         retkey->hive = rethive;
187         retkey->name = NULL;
188         retkey->path = talloc_strdup(retkey, "");
189         
190         *root = retkey;
191
192         return WERR_OK;
193 }
194
195 /* Open a key 
196  * First tries to use the open_key function from the backend
197  * then falls back to get_subkey_by_name and later get_subkey_by_index 
198  */
199 WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
200 {
201         WERROR error;
202
203         if(!parent) {
204                 DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
205                 return WERR_INVALID_PARAM;
206         }
207
208         if(!parent->hive->functions->open_key && 
209            (parent->hive->functions->get_subkey_by_name || 
210            parent->hive->functions->get_subkey_by_index)) {
211                 char *orig = strdup(name), 
212                          *curbegin = orig, 
213                          *curend = strchr(orig, '\\');
214                 struct registry_key *curkey = parent;
215
216                 while(curbegin && *curbegin) {
217                         if(curend)*curend = '\0';
218                         error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
219                         if(!W_ERROR_IS_OK(error)) {
220                                 SAFE_FREE(orig);
221                                 return error;
222                         }
223                         if(!curend) break;
224                         curbegin = curend + 1;
225                         curend = strchr(curbegin, '\\');
226                 }
227                 SAFE_FREE(orig);
228
229                 *result = curkey;
230                 
231                 return WERR_OK;
232         }
233
234         if(!parent->hive->functions->open_key) {
235                 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
236                 return WERR_NOT_SUPPORTED;
237         }
238
239         error = parent->hive->functions->open_key(mem_ctx, parent, name, result);
240
241         if(!W_ERROR_IS_OK(error)) return error;
242                 
243         (*result)->hive = parent->hive;
244         (*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
245         (*result)->hive = parent->hive;
246
247         return WERR_OK;
248 }
249
250 WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val)
251 {
252         if(!key) return WERR_INVALID_PARAM;
253
254         if(key->hive->functions->get_value_by_index) {
255                 WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
256                 if(!W_ERROR_IS_OK(status)) 
257                         return status;
258         } else {
259                 return WERR_NOT_SUPPORTED;
260         }
261         
262         return WERR_OK;
263 }
264
265 WERROR reg_key_num_subkeys(struct registry_key *key, int *count)
266 {
267         if(!key) return WERR_INVALID_PARAM;
268         
269         if(key->hive->functions->num_subkeys) {
270                 return key->hive->functions->num_subkeys(key, count);
271         }
272
273         if(key->hive->functions->get_subkey_by_index) {
274                 int i;
275                 WERROR error;
276                 struct registry_key *dest = NULL;
277                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
278                 
279                 for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
280                 talloc_free(mem_ctx);
281
282                 *count = i;
283                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
284                 return error;
285         }
286
287         return WERR_NOT_SUPPORTED;
288 }
289
290 WERROR reg_key_num_values(struct registry_key *key, int *count)
291 {
292         
293         if(!key) return WERR_INVALID_PARAM;
294
295         if (key->hive->functions->num_values) {
296                 return key->hive->functions->num_values(key, count);
297         }
298
299         if(key->hive->functions->get_value_by_index) {
300                 int i;
301                 WERROR error;
302                 struct registry_value *dest;
303                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
304                 
305                 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
306                 talloc_free(mem_ctx);
307
308                 *count = i;
309                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
310                 return error;
311         }
312
313         return WERR_NOT_SUPPORTED;
314 }
315
316 WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey)
317 {
318         if(!key) return WERR_INVALID_PARAM;
319
320         if(key->hive->functions->get_subkey_by_index) {
321                 WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
322                 if(!NT_STATUS_IS_OK(status)) return status;
323         } else {
324                 return WERR_NOT_SUPPORTED;
325         }
326
327         if(key->hive->root == key) 
328                 (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
329         else 
330                 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
331
332         (*subkey)->hive = key->hive;
333         return WERR_OK;;
334 }
335
336 WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey)
337 {
338         int i;
339         WERROR error = WERR_OK;
340
341         if(!key) return WERR_INVALID_PARAM;
342
343         if(key->hive->functions->get_subkey_by_name) {
344                 error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
345         } else if(key->hive->functions->open_key) {
346                 error = key->hive->functions->open_key(mem_ctx, key, name, subkey);
347         } else if(key->hive->functions->get_subkey_by_index) {
348                 for(i = 0; W_ERROR_IS_OK(error); i++) {
349                         error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
350                         if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) {
351                                 break;
352                         }
353                 }
354
355                 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
356                         error = WERR_DEST_NOT_FOUND;
357         } else {
358                 return WERR_NOT_SUPPORTED;
359         }
360
361         if(!W_ERROR_IS_OK(error)) return error;
362
363         (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
364         (*subkey)->hive = key->hive;
365
366         return WERR_OK; 
367 }
368
369 WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val)
370 {
371         int i;
372         WERROR error = WERR_OK;
373
374         if(!key) return WERR_INVALID_PARAM;
375
376         if(key->hive->functions->get_value_by_name) {
377                 error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
378         } else {
379                 for(i = 0; W_ERROR_IS_OK(error); i++) {
380                         error = reg_key_get_value_by_index(mem_ctx, key, i, val);
381                         if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) {
382                                 break;
383                         }
384                 }
385         }
386
387         if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
388                 return error;
389         
390         return WERR_OK;
391 }
392
393 WERROR reg_key_del(struct registry_key *parent, const char *name)
394 {
395         WERROR error;
396         if(!parent) return WERR_INVALID_PARAM;
397         
398         
399         if(!parent->hive->functions->del_key)
400                 return WERR_NOT_SUPPORTED;
401         
402         error = parent->hive->functions->del_key(parent, name);
403         if(!W_ERROR_IS_OK(error)) return error;
404
405         return WERR_OK;
406 }
407
408 WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey)
409 {
410         WERROR error;
411         
412         if (!parent) return WERR_INVALID_PARAM;
413         
414         if (!parent->hive->functions->add_key) {
415                 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
416                 return WERR_NOT_SUPPORTED;
417         }
418
419         error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
420
421         if(!W_ERROR_IS_OK(error)) return error;
422         
423         (*newkey)->hive = parent->hive;
424         (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name);
425
426         return WERR_OK;
427 }
428
429 WERROR reg_val_set(struct registry_key *key, const char *value, uint32 type, void *data, int len)
430 {
431         /* A 'real' set function has preference */
432         if (key->hive->functions->set_value) 
433                 return key->hive->functions->set_value(key, value, type, data, len);
434
435         DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
436         return WERR_NOT_SUPPORTED;
437 }
438
439
440
441 WERROR reg_del_value(struct registry_key *key, const char *valname)
442 {
443         WERROR ret = WERR_OK;
444         if(!key->hive->functions->del_value)
445                 return WERR_NOT_SUPPORTED;
446
447         ret = key->hive->functions->del_value(key, valname);
448
449         if(!W_ERROR_IS_OK(ret)) return ret;
450
451         return ret;
452 }
453
454 WERROR reg_save (struct registry_context *ctx, const char *location)
455 {
456         return WERR_NOT_SUPPORTED;
457 }
458
459 WERROR reg_key_flush(struct registry_key *key)
460 {
461         if (!key) {
462                 return WERR_INVALID_PARAM;
463         }
464         
465         if (key->hive->functions->flush_key) {
466                 return key->hive->functions->flush_key(key);
467         }
468         
469         /* No need for flushing, apparently */
470         return WERR_OK;
471 }
472
473 WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint32 *max_subkeysize)
474 {
475         int i = 0; 
476         struct registry_key *subkey;
477         WERROR error;
478         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
479
480         *max_subkeylen = *max_subkeysize = 0;
481
482         do {
483                 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
484
485                 if (W_ERROR_IS_OK(error)) {
486                         *max_subkeysize = MAX(*max_subkeysize, 0xFF);
487                         *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
488                 }
489
490                 i++;
491         } while (W_ERROR_IS_OK(error));
492
493         talloc_free(mem_ctx);
494
495         return WERR_OK;
496 }
497
498 WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint32 *max_valbufsize)
499 {
500         int i = 0; 
501         struct registry_value *value;
502         WERROR error;
503         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
504
505         *max_valnamelen = *max_valbufsize = 0;
506
507         do {
508                 error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
509
510                 if (W_ERROR_IS_OK(error)) {
511                         if (value->name) {
512                                 *max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
513                         }
514                         *max_valbufsize = MAX(*max_valbufsize, value->data_len);
515                 }
516
517                 i++;
518         } while (W_ERROR_IS_OK(error));
519
520         talloc_free(mem_ctx);
521
522         return WERR_OK;
523 }