r3586: Fix some of the issues with the module init functions.
[samba.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 #define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name))
34
35 /* Register new backend */
36 NTSTATUS registry_register(const void *_function)  
37 {
38         const struct registry_operations *functions = _function;
39         struct reg_init_function_entry *entry = backends;
40
41         if (!functions || !functions->name) {
42                 DEBUG(0, ("Invalid arguments while registering registry backend\n"));
43                 return NT_STATUS_INVALID_PARAMETER;
44         }
45
46         DEBUG(5,("Attempting to register registry backend %s\n", functions->name));
47
48         /* Check for duplicates */
49         if (reg_find_backend_entry(functions->name)) {
50                 DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name));
51                 return NT_STATUS_OBJECT_NAME_COLLISION;
52         }
53
54         entry = malloc(sizeof(struct reg_init_function_entry));
55         entry->functions = functions;
56
57         DLIST_ADD(backends, entry);
58         DEBUG(5,("Successfully added registry backend '%s'\n", functions->name));
59         return NT_STATUS_OK;
60 }
61
62 NTSTATUS registry_init(void)
63 {
64         NTSTATUS status;
65         
66         status = register_subsystem("registry", registry_register);
67         if (NT_STATUS_IS_ERR(status)) {
68                 DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status)));
69                 return status;
70         }
71
72         registry_init_static_modules;
73
74         return NT_STATUS_OK;
75 }
76
77 /* Find a backend in the list of available backends */
78 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
79 {
80         struct reg_init_function_entry *entry;
81
82         entry = backends;
83
84         while(entry) {
85                 if (strcmp(entry->functions->name, name) == 0) return entry;
86                 entry = entry->next;
87         }
88
89         return NULL;
90 }
91
92 /* Check whether a certain backend is present */
93 BOOL reg_has_backend(const char *backend)
94 {
95         return reg_find_backend_entry(backend) != NULL?True:False;
96 }
97
98 WERROR reg_create(struct registry_context **_ret)
99 {
100         TALLOC_CTX *mem_ctx;
101         struct registry_context *ret;
102         mem_ctx = talloc_init("registry handle");
103         ret = talloc(mem_ctx, sizeof(struct registry_context));
104         ret->mem_ctx = mem_ctx;
105         ZERO_STRUCTP(ret);      
106         *_ret = ret;
107         return WERR_OK;
108 }
109
110 WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives)
111 {
112         struct reg_init_function_entry *entry;
113         
114         entry = reg_find_backend_entry(backend);
115         
116         if (!entry) {
117                 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
118                 return WERR_GENERAL_FAILURE;
119         }
120
121         if(!entry->functions->list_available_hives) {
122                 return WERR_NOT_SUPPORTED;
123         }
124
125         return entry->functions->list_available_hives(mem_ctx, location, credentials, hives);
126 }
127
128 WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials)
129 {
130         WERROR error = reg_create(ret), reterror = WERR_NO_MORE_ITEMS;
131         char **hives;
132         int i, j;
133         TALLOC_CTX *mem_ctx = talloc_init("reg_open");
134
135         if(!W_ERROR_IS_OK(error)) return error;
136
137         error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives);
138
139         if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) {
140                 return reg_import_hive(*ret, backend, location, credentials, NULL);
141         }
142            
143         if(!W_ERROR_IS_OK(error)) return error;
144
145         j = 0;
146         for(i = 0; hives[i]; i++)
147         {
148                 error = reg_import_hive(*ret, backend, location, credentials, hives[i]);
149                 if (W_ERROR_IS_OK(error)) { 
150                         reterror = WERR_OK;
151                         (*ret)->hives[j]->name = talloc_strdup((*ret)->mem_ctx, hives[i]);
152                         j++;
153                 } else if (!W_ERROR_IS_OK(reterror)) reterror = error;
154         }
155
156         return reterror;
157 }
158
159 WERROR reg_close (struct registry_context *ctx)
160 {
161         int i;
162         for (i = 0; i < ctx->num_hives; i++) {
163                 if (ctx->hives[i]->functions->close_hive) {
164                         ctx->hives[i]->functions->close_hive(ctx->hives[i]);
165                 }
166         }
167         talloc_destroy(ctx);
168
169         return WERR_OK;
170 }
171
172 /* Open a registry file/host/etc */
173 WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename)
174 {
175         struct registry_hive *ret;
176         TALLOC_CTX *mem_ctx;
177         struct reg_init_function_entry *entry;
178         WERROR werr;
179
180         entry = reg_find_backend_entry(backend);
181         
182         if (!entry) {
183                 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
184                 return WERR_GENERAL_FAILURE;
185         }
186
187         if(!entry->functions->open_hive) {
188                 return WERR_NOT_SUPPORTED;
189         }
190         
191         
192         mem_ctx = h->mem_ctx;
193         ret = talloc_p(mem_ctx, struct registry_hive);
194         ret->location = location?talloc_strdup(mem_ctx, location):NULL;
195         ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL;
196         ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL;
197         ret->functions = entry->functions;
198         ret->backend_data = NULL;
199         ret->reg_ctx = h;
200         ret->name = NULL;
201
202         werr = entry->functions->open_hive(mem_ctx, ret, &ret->root);
203
204         if(!W_ERROR_IS_OK(werr)) return werr;
205         
206         if(!ret->root) {
207                 DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
208                 return WERR_GENERAL_FAILURE;
209         }
210
211         ret->root->hive = ret;
212         ret->root->name = NULL;
213         ret->root->path = talloc_strdup(mem_ctx, "");
214
215         /* Add hive to context */
216         h->num_hives++;
217         h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives);
218         h->hives[h->num_hives-1] = ret;
219
220         return WERR_OK;
221 }
222
223 /* Open a key by name (including the hive name!) */
224 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
225 {
226         struct registry_key *hive;
227         WERROR error;
228         int hivelength;
229         char *hivename;
230
231         if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
232         else hivelength = strlen(name);
233
234         hivename = strndup(name, hivelength);
235         error = reg_get_hive(handle, hivename, &hive);
236         SAFE_FREE(hivename);
237
238         if(!W_ERROR_IS_OK(error)) {
239                 return error;
240         }
241
242         return reg_open_key(mem_ctx, hive, name, result);
243 }
244
245 /* Open a key 
246  * First tries to use the open_key function from the backend
247  * then falls back to get_subkey_by_name and later get_subkey_by_index 
248  */
249 WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
250 {
251         char *fullname;
252         WERROR error;
253
254         if(!parent) {
255                 DEBUG(0, ("Invalid parent key specified"));
256                 return WERR_INVALID_PARAM;
257         }
258
259         if(!parent->hive->functions->open_key && 
260            (parent->hive->functions->get_subkey_by_name || 
261            parent->hive->functions->get_subkey_by_index)) {
262                 char *orig = strdup(name), 
263                          *curbegin = orig, 
264                          *curend = strchr(orig, '\\');
265                 struct registry_key *curkey = parent;
266
267                 while(curbegin && *curbegin) {
268                         if(curend)*curend = '\0';
269                         error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
270                         if(!W_ERROR_IS_OK(error)) {
271                                 SAFE_FREE(orig);
272                                 return error;
273                         }
274                         if(!curend) break;
275                         curbegin = curend + 1;
276                         curend = strchr(curbegin, '\\');
277                 }
278                 SAFE_FREE(orig);
279
280                 *result = curkey;
281                 
282                 return WERR_OK;
283         }
284
285         if(!parent->hive->functions->open_key) {
286                 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
287                 return WERR_NOT_SUPPORTED;
288         }
289
290         fullname = reg_make_path(mem_ctx, parent, name);
291
292         error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result);
293
294         if(!W_ERROR_IS_OK(error)) return error;
295                 
296         (*result)->hive = parent->hive;
297         (*result)->path = fullname;
298         (*result)->hive = parent->hive;
299
300         return WERR_OK;
301 }
302
303 WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val)
304 {
305         if(!key) return WERR_INVALID_PARAM;
306
307         if(key->hive->functions->get_value_by_index) {
308                 WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
309                 if(!W_ERROR_IS_OK(status)) 
310                         return status;
311         } else {
312                 return WERR_NOT_SUPPORTED;
313         }
314         
315         (*val)->parent = key;
316         (*val)->hive = key->hive;
317         return WERR_OK;
318 }
319
320 WERROR reg_key_num_subkeys(struct registry_key *key, int *count)
321 {
322         if(!key) return WERR_INVALID_PARAM;
323         
324         if(key->hive->functions->num_subkeys) {
325                 return key->hive->functions->num_subkeys(key, count);
326         }
327
328         if(key->hive->functions->get_subkey_by_index) {
329                 int i;
330                 WERROR error;
331                 struct registry_key *dest;
332                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
333                 
334                 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
335                 talloc_destroy(mem_ctx);
336
337                 *count = i;
338                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
339                 return error;
340         }
341
342         return WERR_NOT_SUPPORTED;
343 }
344
345 WERROR reg_key_num_values(struct registry_key *key, int *count)
346 {
347         
348         if(!key) return WERR_INVALID_PARAM;
349
350         if (key->hive->functions->num_values) {
351                 return key->hive->functions->num_values(key, count);
352         }
353
354         if(key->hive->functions->get_value_by_index) {
355                 int i;
356                 WERROR error;
357                 struct registry_value *dest;
358                 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
359                 
360                 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
361                 talloc_destroy(mem_ctx);
362
363                 *count = i;
364                 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
365                 return error;
366         }
367
368         return WERR_NOT_SUPPORTED;
369 }
370
371 WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey)
372 {
373         if(!key) return WERR_INVALID_PARAM;
374
375         if(key->hive->functions->get_subkey_by_index) {
376                 WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
377                 if(!NT_STATUS_IS_OK(status)) return status;
378         } else {
379                 return WERR_NOT_SUPPORTED;
380         }
381
382         if(key->hive->root == key) 
383                 (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
384         else 
385                 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
386
387         (*subkey)->hive = key->hive;
388         return WERR_OK;;
389 }
390
391 WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey)
392 {
393         int i;
394         WERROR error = WERR_OK;
395
396         if(!key) return WERR_INVALID_PARAM;
397
398         if(key->hive->functions->get_subkey_by_name) {
399                 error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
400         } else if(key->hive->functions->open_key) {
401                 error = key->hive->functions->open_key(mem_ctx, key->hive, talloc_asprintf(mem_ctx, "%s\\%s", key->path, name), subkey);
402         } else if(key->hive->functions->get_subkey_by_index) {
403                 for(i = 0; W_ERROR_IS_OK(error); i++) {
404                         error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
405                         if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) {
406                                 return error;
407                         }
408                 }
409         } else {
410                 return WERR_NOT_SUPPORTED;
411         }
412
413         if(!W_ERROR_IS_OK(error)) return error;
414
415         (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
416         (*subkey)->hive = key->hive;
417
418         return WERR_OK; 
419 }
420
421 WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val)
422 {
423         int i;
424         WERROR error = WERR_OK;
425
426         if(!key) return WERR_INVALID_PARAM;
427
428         if(key->hive->functions->get_value_by_name) {
429                 error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
430         } else {
431                 for(i = 0; W_ERROR_IS_OK(error); i++) {
432                         error = reg_key_get_value_by_index(mem_ctx, key, i, val);
433                         if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) {
434                                 break;
435                         }
436                 }
437         }
438
439         if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
440                 return error;
441         
442         (*val)->parent = key;
443         (*val)->hive = key->hive;
444         
445         return WERR_OK;
446 }
447
448 WERROR reg_key_del(struct registry_key *key)
449 {
450         WERROR error;
451         if(!key) return WERR_INVALID_PARAM;
452         
453         
454         if(!key->hive->functions->del_key)
455                 return WERR_NOT_SUPPORTED;
456         
457         error = key->hive->functions->del_key(key);
458         if(!W_ERROR_IS_OK(error)) return error;
459
460         return WERR_OK;
461 }
462
463 WERROR reg_key_del_recursive(struct registry_key *key)
464 {
465         WERROR error = WERR_OK;
466         int i;
467
468         TALLOC_CTX *mem_ctx = talloc_init("del_recursive");
469         
470         /* Delete all values for specified key */
471         for(i = 0; W_ERROR_IS_OK(error); i++) {
472                 struct registry_value *val;
473                 error = reg_key_get_value_by_index(mem_ctx, key, i, &val);
474                 if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) 
475                 {
476                         talloc_destroy(mem_ctx);                        
477                         return error;
478                 }
479
480                 if(W_ERROR_IS_OK(error)) {
481                         error = reg_del_value(val);
482                         if(!W_ERROR_IS_OK(error)) {
483                                 talloc_destroy(mem_ctx);
484                                 return error;
485                         }
486                 }
487         }
488
489         error = WERR_OK;
490
491         /* Delete all keys below this one */
492         for(i = 0; W_ERROR_IS_OK(error); i++) {
493                 struct registry_key *subkey;
494
495                 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
496                 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
497
498                 error = reg_key_del_recursive(subkey);
499                 if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; }
500         }
501
502         talloc_destroy(mem_ctx);
503         return reg_key_del(key);
504 }
505
506 WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name)
507 {
508         struct registry_key *hive;
509         WERROR error;
510         int hivelength;
511         char *hivename;
512
513         if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name;
514         else hivelength = strlen(name);
515
516         hivename = strndup(name, hivelength);
517         error = reg_get_hive(handle, hivename, &hive);
518         SAFE_FREE(hivename);
519
520         if(!W_ERROR_IS_OK(error)) return error;
521
522         return reg_key_add_name_recursive(hive, name);
523 }
524
525 WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path)
526 {
527         struct registry_key *cur, *prevcur = parent;
528         WERROR error = WERR_OK;
529         char *dups, *begin, *end;
530         TALLOC_CTX *mem_ctx = talloc_init("add_recursive");
531
532         begin = dups = strdup(path);
533
534         while(1) { 
535                 end = strchr(begin, '\\');
536                 if(end) *end = '\0';
537                 
538                 error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur);
539
540                 /* Key is not there, add it */
541                 if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
542                         error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur);
543                         if(!W_ERROR_IS_OK(error)) break;
544                 }
545
546                 if(!W_ERROR_IS_OK(error)) {
547                         if(end) *end = '\\';
548                         break;
549                 }
550                 
551                 if(!end) { 
552                         error = WERR_OK; 
553                         break; 
554                 }
555
556                 *end = '\\';
557                 begin = end+1;
558                 prevcur = cur;
559         }
560         SAFE_FREE(dups);
561         talloc_destroy(mem_ctx);
562         return error;
563 }
564
565 WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey)
566 {
567         WERROR error;
568         
569         if (!parent) return WERR_INVALID_PARAM;
570         
571         if (!parent->hive->functions->add_key) {
572                 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
573                 return WERR_NOT_SUPPORTED;
574         }
575
576         error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
577
578         if(!W_ERROR_IS_OK(error)) return error;
579         
580         (*newkey)->hive = parent->hive;
581         (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name);
582
583         return WERR_OK;
584 }
585
586 WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len)
587 {
588         /* A 'real' set function has preference */
589         if (key->hive->functions->set_value) 
590                 return key->hive->functions->set_value(key, value, type, data, len);
591
592         DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
593         return WERR_NOT_SUPPORTED;
594 }
595
596 WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) 
597 {
598         int i;
599         for(i = 0; i < h->num_hives; i++)
600         {
601                 if(!strcmp(h->hives[i]->name, name)) {
602                         *key = h->hives[i]->root;
603                         return WERR_OK;
604                 }
605         }
606
607         return WERR_NO_MORE_ITEMS;
608 }
609
610 WERROR reg_del_value(struct registry_value *val)
611 {
612         WERROR ret = WERR_OK;
613         if(!val->hive->functions->del_value)
614                 return WERR_NOT_SUPPORTED;
615
616         ret = val->hive->functions->del_value(val);
617
618         if(!W_ERROR_IS_OK(ret)) return ret;
619
620         return ret;
621 }
622
623 WERROR reg_save (struct registry_context *ctx, const char *location)
624 {
625         return WERR_NOT_SUPPORTED;
626 }
627
628 WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent)
629 {
630         char *parent_name;
631         char *last;
632         struct registry_key *root;
633         WERROR error;
634
635         parent_name = strdup(key->path);
636         last = strrchr(parent_name, '\\');
637
638         if(!last) {
639                 SAFE_FREE(parent_name);
640                 return WERR_FOOBAR;
641         }
642         *last = '\0';
643
644         error = reg_open_key(mem_ctx, root, parent_name, parent);
645         SAFE_FREE(parent_name);
646         return error;
647 }
648
649 WERROR reg_key_flush(struct registry_key *key)
650 {
651         if (!key) {
652                 return WERR_INVALID_PARAM;
653         }
654         
655         if (key->hive->functions->flush_key) {
656                 return key->hive->functions->flush_key(key);
657         }
658         
659         /* No need for flushing, apparently */
660         return WERR_OK;
661 }
662
663 WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint32 *max_subkeysize)
664 {
665         int i = 0; 
666         struct registry_key *subkey;
667         WERROR error;
668         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
669
670         *max_subkeylen = *max_subkeysize = 0;
671
672         do {
673                 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
674
675                 if (W_ERROR_IS_OK(error)) {
676                         *max_subkeysize = MAX(*max_subkeysize, 0xFF);
677                         *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
678                 }
679
680                 i++;
681         } while (W_ERROR_IS_OK(error));
682
683         talloc_destroy(mem_ctx);
684
685         return WERR_OK;
686 }
687
688 WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint32 *max_valbufsize)
689 {
690         int i = 0; 
691         struct registry_value *value;
692         WERROR error;
693         TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
694
695         *max_valnamelen = *max_valbufsize = 0;
696
697         do {
698                 error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
699
700                 if (W_ERROR_IS_OK(error)) {
701                         if (value->name) {
702                                 *max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
703                         }
704                         *max_valbufsize = MAX(*max_valbufsize, value->data_len);
705                 }
706
707                 i++;
708         } while (W_ERROR_IS_OK(error));
709
710         talloc_destroy(mem_ctx);
711
712         return WERR_OK;
713 }