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