• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/registry/
1/*
2 *  Unix SMB/CIFS implementation.
3 *  Virtual Windows Registry Layer
4 *  Copyright (C) Volker Lendecke 2006
5 *  Copyright (C) Michael Adam 2007-2008
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; either version 3 of the License, or
10 *  (at your option) any later version.
11 *
12 *  This program is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *  GNU General Public License for more details.
16 *
17 *  You should have received a copy of the GNU General Public License
18 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21/* Attempt to wrap the existing API in a more winreg.idl-like way */
22
23/*
24 * Here is a list of winreg.idl functions and corresponding implementations
25 * provided here:
26 *
27 * 0x00		winreg_OpenHKCR
28 * 0x01		winreg_OpenHKCU
29 * 0x02		winreg_OpenHKLM
30 * 0x03		winreg_OpenHKPD
31 * 0x04		winreg_OpenHKU
32 * 0x05		winreg_CloseKey
33 * 0x06		winreg_CreateKey			reg_createkey
34 * 0x07		winreg_DeleteKey			reg_deletekey
35 * 0x08		winreg_DeleteValue			reg_deletevalue
36 * 0x09		winreg_EnumKey				reg_enumkey
37 * 0x0a		winreg_EnumValue			reg_enumvalue
38 * 0x0b		winreg_FlushKey
39 * 0x0c		winreg_GetKeySecurity			reg_getkeysecurity
40 * 0x0d		winreg_LoadKey
41 * 0x0e		winreg_NotifyChangeKeyValue
42 * 0x0f		winreg_OpenKey				reg_openkey
43 * 0x10		winreg_QueryInfoKey			reg_queryinfokey
44 * 0x11		winreg_QueryValue			reg_queryvalue
45 * 0x12		winreg_ReplaceKey
46 * 0x13		winreg_RestoreKey			reg_restorekey
47 * 0x14		winreg_SaveKey				reg_savekey
48 * 0x15		winreg_SetKeySecurity			reg_setkeysecurity
49 * 0x16		winreg_SetValue				reg_setvalue
50 * 0x17		winreg_UnLoadKey
51 * 0x18		winreg_InitiateSystemShutdown
52 * 0x19		winreg_AbortSystemShutdown
53 * 0x1a		winreg_GetVersion			reg_getversion
54 * 0x1b		winreg_OpenHKCC
55 * 0x1c		winreg_OpenHKDD
56 * 0x1d		winreg_QueryMultipleValues
57 * 0x1e		winreg_InitiateSystemShutdownEx
58 * 0x1f		winreg_SaveKeyEx
59 * 0x20		winreg_OpenHKPT
60 * 0x21		winreg_OpenHKPN
61 * 0x22		winreg_QueryMultipleValues2
62 *
63 */
64
65#include "includes.h"
66#include "regfio.h"
67
68#undef DBGC_CLASS
69#define DBGC_CLASS DBGC_REGISTRY
70
71
72/**********************************************************************
73 * Helper functions
74 **********************************************************************/
75
76static WERROR fill_value_cache(struct registry_key *key)
77{
78	if (key->values != NULL) {
79		if (!reg_values_need_update(key->key, key->values)) {
80			return WERR_OK;
81		}
82	}
83
84	if (!(key->values = TALLOC_ZERO_P(key, struct regval_ctr))) {
85		return WERR_NOMEM;
86	}
87	if (fetch_reg_values(key->key, key->values) == -1) {
88		TALLOC_FREE(key->values);
89		return WERR_BADFILE;
90	}
91
92	return WERR_OK;
93}
94
95static WERROR fill_subkey_cache(struct registry_key *key)
96{
97	WERROR werr;
98
99	if (key->subkeys != NULL) {
100		if (!reg_subkeys_need_update(key->key, key->subkeys)) {
101			return WERR_OK;
102		}
103	}
104
105	werr = regsubkey_ctr_init(key, &(key->subkeys));
106	W_ERROR_NOT_OK_RETURN(werr);
107
108	if (fetch_reg_keys(key->key, key->subkeys) == -1) {
109		TALLOC_FREE(key->subkeys);
110		return WERR_NO_MORE_ITEMS;
111	}
112
113	return WERR_OK;
114}
115
116static int regkey_destructor(struct registry_key_handle *key)
117{
118	return regdb_close();
119}
120
121static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
122				   struct registry_key *parent,
123				   const char *name,
124				   const struct nt_user_token *token,
125				   uint32 access_desired,
126				   struct registry_key **pregkey)
127{
128	WERROR     	result = WERR_OK;
129	struct registry_key *regkey;
130	struct registry_key_handle *key;
131	struct regsubkey_ctr	*subkeys = NULL;
132
133	DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
134
135	SMB_ASSERT(strchr(name, '\\') == NULL);
136
137	if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) ||
138	    !(regkey->token = dup_nt_token(regkey, token)) ||
139	    !(regkey->key = TALLOC_ZERO_P(regkey, struct registry_key_handle)))
140	{
141		result = WERR_NOMEM;
142		goto done;
143	}
144
145	if ( !(W_ERROR_IS_OK(result = regdb_open())) ) {
146		goto done;
147	}
148
149	key = regkey->key;
150	talloc_set_destructor(key, regkey_destructor);
151
152	/* initialization */
153
154	key->type = REG_KEY_GENERIC;
155
156	if (name[0] == '\0') {
157		/*
158		 * Open a copy of the parent key
159		 */
160		if (!parent) {
161			result = WERR_BADFILE;
162			goto done;
163		}
164		key->name = talloc_strdup(key, parent->key->name);
165	}
166	else {
167		/*
168		 * Normal subkey open
169		 */
170		key->name = talloc_asprintf(key, "%s%s%s",
171					    parent ? parent->key->name : "",
172					    parent ? "\\": "",
173					    name);
174	}
175
176	if (key->name == NULL) {
177		result = WERR_NOMEM;
178		goto done;
179	}
180
181	/* Tag this as a Performance Counter Key */
182
183	if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
184		key->type = REG_KEY_HKPD;
185
186	/* Look up the table of registry I/O operations */
187
188	if ( !(key->ops = reghook_cache_find( key->name )) ) {
189		DEBUG(0,("reg_open_onelevel: Failed to assign "
190			 "registry_ops to [%s]\n", key->name ));
191		result = WERR_BADFILE;
192		goto done;
193	}
194
195	/* check if the path really exists; failed is indicated by -1 */
196	/* if the subkey count failed, bail out */
197
198	result = regsubkey_ctr_init(key, &subkeys);
199	if (!W_ERROR_IS_OK(result)) {
200		goto done;
201	}
202
203	if ( fetch_reg_keys( key, subkeys ) == -1 )  {
204		result = WERR_BADFILE;
205		goto done;
206	}
207
208	TALLOC_FREE( subkeys );
209
210	if ( !regkey_access_check( key, access_desired, &key->access_granted,
211				   token ) ) {
212		result = WERR_ACCESS_DENIED;
213		goto done;
214	}
215
216	*pregkey = regkey;
217	result = WERR_OK;
218
219done:
220	if ( !W_ERROR_IS_OK(result) ) {
221		TALLOC_FREE(regkey);
222	}
223
224	return result;
225}
226
227WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
228		    uint32 desired_access,
229		    const struct nt_user_token *token,
230		    struct registry_key **pkey)
231{
232	SMB_ASSERT(hive != NULL);
233	SMB_ASSERT(hive[0] != '\0');
234	SMB_ASSERT(strchr(hive, '\\') == NULL);
235
236	return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
237				    pkey);
238}
239
240
241/**********************************************************************
242 * The API functions
243 **********************************************************************/
244
245WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
246		   const char *name, uint32 desired_access,
247		   struct registry_key **pkey)
248{
249	struct registry_key *direct_parent = parent;
250	WERROR err;
251	char *p, *path, *to_free;
252	size_t len;
253
254	if (!(path = SMB_STRDUP(name))) {
255		return WERR_NOMEM;
256	}
257	to_free = path;
258
259	len = strlen(path);
260
261	if ((len > 0) && (path[len-1] == '\\')) {
262		path[len-1] = '\0';
263	}
264
265	while ((p = strchr(path, '\\')) != NULL) {
266		char *name_component;
267		struct registry_key *tmp;
268
269		if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
270			err = WERR_NOMEM;
271			goto error;
272		}
273
274		err = regkey_open_onelevel(mem_ctx, direct_parent,
275					   name_component, parent->token,
276					   KEY_ENUMERATE_SUB_KEYS, &tmp);
277		SAFE_FREE(name_component);
278
279		if (!W_ERROR_IS_OK(err)) {
280			goto error;
281		}
282		if (direct_parent != parent) {
283			TALLOC_FREE(direct_parent);
284		}
285
286		direct_parent = tmp;
287		path = p+1;
288	}
289
290	err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
291				   desired_access, pkey);
292 error:
293	if (direct_parent != parent) {
294		TALLOC_FREE(direct_parent);
295	}
296	SAFE_FREE(to_free);
297	return err;
298}
299
300WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
301		   uint32 idx, char **name, NTTIME *last_write_time)
302{
303	WERROR err;
304
305	if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) {
306		return WERR_ACCESS_DENIED;
307	}
308
309	if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
310		return err;
311	}
312
313	if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
314		return WERR_NO_MORE_ITEMS;
315	}
316
317	if (!(*name = talloc_strdup(mem_ctx,
318			regsubkey_ctr_specific_key(key->subkeys, idx))))
319	{
320		return WERR_NOMEM;
321	}
322
323	if (last_write_time) {
324		*last_write_time = 0;
325	}
326
327	return WERR_OK;
328}
329
330WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
331		     uint32 idx, char **pname, struct registry_value **pval)
332{
333	struct registry_value *val;
334	WERROR err;
335
336	if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
337		return WERR_ACCESS_DENIED;
338	}
339
340	if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
341		return err;
342	}
343
344	if (idx >= key->values->num_values) {
345		return WERR_NO_MORE_ITEMS;
346	}
347
348	err = registry_pull_value(mem_ctx, &val,
349				  key->values->values[idx]->type,
350				  key->values->values[idx]->data_p,
351				  key->values->values[idx]->size,
352				  key->values->values[idx]->size);
353	if (!W_ERROR_IS_OK(err)) {
354		return err;
355	}
356
357	if (pname
358	    && !(*pname = talloc_strdup(
359			 mem_ctx, key->values->values[idx]->valuename))) {
360		SAFE_FREE(val);
361		return WERR_NOMEM;
362	}
363
364	*pval = val;
365	return WERR_OK;
366}
367
368WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
369		      const char *name, struct registry_value **pval)
370{
371	WERROR err;
372	uint32 i;
373
374	if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
375		return WERR_ACCESS_DENIED;
376	}
377
378	if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
379		return err;
380	}
381
382	for (i=0; i<key->values->num_values; i++) {
383		if (strequal(key->values->values[i]->valuename, name)) {
384			return reg_enumvalue(mem_ctx, key, i, NULL, pval);
385		}
386	}
387
388	return WERR_BADFILE;
389}
390
391WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
392			uint32_t *max_subkeylen, uint32_t *max_subkeysize,
393			uint32_t *num_values, uint32_t *max_valnamelen,
394			uint32_t *max_valbufsize, uint32_t *secdescsize,
395			NTTIME *last_changed_time)
396{
397	uint32 i, max_size;
398	size_t max_len;
399	TALLOC_CTX *mem_ctx;
400	WERROR err;
401	struct security_descriptor *secdesc;
402
403	if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
404		return WERR_ACCESS_DENIED;
405	}
406
407	if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
408	    !W_ERROR_IS_OK(fill_value_cache(key))) {
409		return WERR_BADFILE;
410	}
411
412	max_len = 0;
413	for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
414		max_len = MAX(max_len,
415			strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
416	}
417
418	*num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
419	*max_subkeylen = max_len;
420	*max_subkeysize = 0;	/* Class length? */
421
422	max_len = 0;
423	max_size = 0;
424	for (i=0; i<key->values->num_values; i++) {
425		max_len = MAX(max_len,
426			      strlen(key->values->values[i]->valuename));
427		max_size = MAX(max_size, key->values->values[i]->size);
428	}
429
430	*num_values = key->values->num_values;
431	*max_valnamelen = max_len;
432	*max_valbufsize = max_size;
433
434	if (!(mem_ctx = talloc_new(key))) {
435		return WERR_NOMEM;
436	}
437
438	err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
439	if (!W_ERROR_IS_OK(err)) {
440		TALLOC_FREE(mem_ctx);
441		return err;
442	}
443
444	*secdescsize = ndr_size_security_descriptor(secdesc, NULL, 0);
445	TALLOC_FREE(mem_ctx);
446
447	*last_changed_time = 0;
448
449	return WERR_OK;
450}
451
452WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
453		     const char *subkeypath, uint32 desired_access,
454		     struct registry_key **pkey,
455		     enum winreg_CreateAction *paction)
456{
457	struct registry_key *key = parent;
458	struct registry_key *create_parent;
459	TALLOC_CTX *mem_ctx;
460	char *path, *end;
461	WERROR err;
462
463	/*
464	 * We must refuse to handle subkey-paths containing
465	 * a '/' character because at a lower level, after
466	 * normalization, '/' is treated as a key separator
467	 * just like '\\'.
468	 */
469	if (strchr(subkeypath, '/') != NULL) {
470		return WERR_INVALID_PARAM;
471	}
472
473	if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
474
475	if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
476		err = WERR_NOMEM;
477		goto done;
478	}
479
480	while ((end = strchr(path, '\\')) != NULL) {
481		struct registry_key *tmp;
482		enum winreg_CreateAction action;
483
484		*end = '\0';
485
486		err = reg_createkey(mem_ctx, key, path,
487				    KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
488		if (!W_ERROR_IS_OK(err)) {
489			goto done;
490		}
491
492		if (key != parent) {
493			TALLOC_FREE(key);
494		}
495
496		key = tmp;
497		path = end+1;
498	}
499
500	/*
501	 * At this point, "path" contains the one-element subkey of "key". We
502	 * can try to open it.
503	 */
504
505	err = reg_openkey(ctx, key, path, desired_access, pkey);
506	if (W_ERROR_IS_OK(err)) {
507		if (paction != NULL) {
508			*paction = REG_OPENED_EXISTING_KEY;
509		}
510		goto done;
511	}
512
513	if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
514		/*
515		 * Something but "notfound" has happened, so bail out
516		 */
517		goto done;
518	}
519
520	/*
521	 * We have to make a copy of the current key, as we opened it only
522	 * with ENUM_SUBKEY access.
523	 */
524
525	err = reg_openkey(mem_ctx, key, "", KEY_CREATE_SUB_KEY,
526			  &create_parent);
527	if (!W_ERROR_IS_OK(err)) {
528		goto done;
529	}
530
531	/*
532	 * Actually create the subkey
533	 */
534
535	err = fill_subkey_cache(create_parent);
536	if (!W_ERROR_IS_OK(err)) goto done;
537
538	err = create_reg_subkey(key->key, path);
539	W_ERROR_NOT_OK_GOTO_DONE(err);
540
541	/*
542	 * Now open the newly created key
543	 */
544
545	err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
546	if (W_ERROR_IS_OK(err) && (paction != NULL)) {
547		*paction = REG_CREATED_NEW_KEY;
548	}
549
550 done:
551	TALLOC_FREE(mem_ctx);
552	return err;
553}
554
555WERROR reg_deletekey(struct registry_key *parent, const char *path)
556{
557	WERROR err;
558	char *name, *end;
559	struct registry_key *tmp_key, *key;
560	TALLOC_CTX *mem_ctx = talloc_stackframe();
561
562	name = talloc_strdup(mem_ctx, path);
563	if (name == NULL) {
564		err = WERR_NOMEM;
565		goto done;
566	}
567
568	/* check if the key has subkeys */
569	err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
570	W_ERROR_NOT_OK_GOTO_DONE(err);
571
572	err = fill_subkey_cache(key);
573	W_ERROR_NOT_OK_GOTO_DONE(err);
574
575	if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
576		err = WERR_ACCESS_DENIED;
577		goto done;
578	}
579
580	/* no subkeys - proceed with delete */
581	end = strrchr(name, '\\');
582	if (end != NULL) {
583		*end = '\0';
584
585		err = reg_openkey(mem_ctx, parent, name,
586				  KEY_CREATE_SUB_KEY, &tmp_key);
587		W_ERROR_NOT_OK_GOTO_DONE(err);
588
589		parent = tmp_key;
590		name = end+1;
591	}
592
593	if (name[0] == '\0') {
594		err = WERR_INVALID_PARAM;
595		goto done;
596	}
597
598	err = delete_reg_subkey(parent->key, name);
599
600done:
601	TALLOC_FREE(mem_ctx);
602	return err;
603}
604
605WERROR reg_setvalue(struct registry_key *key, const char *name,
606		    const struct registry_value *val)
607{
608	WERROR err;
609	DATA_BLOB value_data;
610	int res;
611
612	if (!(key->key->access_granted & KEY_SET_VALUE)) {
613		return WERR_ACCESS_DENIED;
614	}
615
616	if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
617		return err;
618	}
619
620	err = registry_push_value(key, val, &value_data);
621	if (!W_ERROR_IS_OK(err)) {
622		return err;
623	}
624
625	res = regval_ctr_addvalue(key->values, name, val->type,
626				  (char *)value_data.data, value_data.length);
627	TALLOC_FREE(value_data.data);
628
629	if (res == 0) {
630		TALLOC_FREE(key->values);
631		return WERR_NOMEM;
632	}
633
634	if (!store_reg_values(key->key, key->values)) {
635		TALLOC_FREE(key->values);
636		return WERR_REG_IO_FAILURE;
637	}
638
639	return WERR_OK;
640}
641
642static WERROR reg_value_exists(struct registry_key *key, const char *name)
643{
644	int i;
645
646	for (i=0; i<key->values->num_values; i++) {
647		if (strequal(key->values->values[i]->valuename, name)) {
648			return WERR_OK;
649		}
650	}
651
652	return WERR_BADFILE;
653}
654
655WERROR reg_deletevalue(struct registry_key *key, const char *name)
656{
657	WERROR err;
658
659	if (!(key->key->access_granted & KEY_SET_VALUE)) {
660		return WERR_ACCESS_DENIED;
661	}
662
663	if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
664		return err;
665	}
666
667	err = reg_value_exists(key, name);
668	if (!W_ERROR_IS_OK(err)) {
669		return err;
670	}
671
672	regval_ctr_delvalue(key->values, name);
673
674	if (!store_reg_values(key->key, key->values)) {
675		TALLOC_FREE(key->values);
676		return WERR_REG_IO_FAILURE;
677	}
678
679	return WERR_OK;
680}
681
682WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
683			  struct security_descriptor **psecdesc)
684{
685	return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
686}
687
688WERROR reg_setkeysecurity(struct registry_key *key,
689			  struct security_descriptor *psecdesc)
690{
691	return regkey_set_secdesc(key->key, psecdesc);
692}
693
694WERROR reg_getversion(uint32_t *version)
695{
696	if (version == NULL) {
697		return WERR_INVALID_PARAM;
698	}
699
700	*version = 0x00000005; /* Windows 2000 registry API version */
701	return WERR_OK;
702}
703
704/*******************************************************************
705 Note: topkeypat is the *full* path that this *key will be
706 loaded into (including the name of the key)
707 ********************************************************************/
708
709static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
710			    REGF_NK_REC *key)
711{
712	REGF_NK_REC *subkey;
713	struct registry_key_handle registry_key;
714	struct regval_ctr *values;
715	struct regsubkey_ctr *subkeys;
716	int i;
717	char *path = NULL;
718	WERROR result = WERR_OK;
719
720	/* initialize the struct registry_key_handle structure */
721
722	registry_key.ops = reghook_cache_find(topkeypath);
723	if (!registry_key.ops) {
724		DEBUG(0, ("reg_load_tree: Failed to assign registry_ops "
725			  "to [%s]\n", topkeypath));
726		return WERR_BADFILE;
727	}
728
729	registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
730	if (!registry_key.name) {
731		DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
732		return WERR_NOMEM;
733	}
734
735	/* now start parsing the values and subkeys */
736
737	result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
738	W_ERROR_NOT_OK_RETURN(result);
739
740	values = TALLOC_ZERO_P(subkeys, struct regval_ctr);
741	if (values == NULL) {
742		return WERR_NOMEM;
743	}
744
745	/* copy values into the struct regval_ctr */
746
747	for (i=0; i<key->num_values; i++) {
748		regval_ctr_addvalue(values, key->values[i].valuename,
749				    key->values[i].type,
750				    (char*)key->values[i].data,
751				    (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
752	}
753
754	/* copy subkeys into the struct regsubkey_ctr */
755
756	key->subkey_index = 0;
757	while ((subkey = regfio_fetch_subkey( regfile, key ))) {
758		result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
759		if (!W_ERROR_IS_OK(result)) {
760			TALLOC_FREE(subkeys);
761			return result;
762		}
763	}
764
765	/* write this key and values out */
766
767	if (!store_reg_values(&registry_key, values)
768	    || !store_reg_keys(&registry_key, subkeys))
769	{
770		DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
771		result = WERR_REG_IO_FAILURE;
772	}
773
774	TALLOC_FREE(subkeys);
775
776	if (!W_ERROR_IS_OK(result)) {
777		return result;
778	}
779
780	/* now continue to load each subkey registry tree */
781
782	key->subkey_index = 0;
783	while ((subkey = regfio_fetch_subkey(regfile, key))) {
784		path = talloc_asprintf(regfile->mem_ctx,
785				       "%s\\%s",
786				       topkeypath,
787				       subkey->keyname);
788		if (path == NULL) {
789			return WERR_NOMEM;
790		}
791		result = reg_load_tree(regfile, path, subkey);
792		if (!W_ERROR_IS_OK(result)) {
793			break;
794		}
795	}
796
797	return result;
798}
799
800/*******************************************************************
801 ********************************************************************/
802
803static WERROR restore_registry_key(struct registry_key_handle *krecord,
804				   const char *fname)
805{
806	REGF_FILE *regfile;
807	REGF_NK_REC *rootkey;
808	WERROR result;
809
810	/* open the registry file....fail if the file already exists */
811
812	regfile = regfio_open(fname, (O_RDONLY), 0);
813	if (regfile == NULL) {
814		DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
815			  fname, strerror(errno)));
816		return ntstatus_to_werror(map_nt_error_from_unix(errno));
817	}
818
819	/* get the rootkey from the regf file and then load the tree
820	   via recursive calls */
821
822	if (!(rootkey = regfio_rootkey(regfile))) {
823		regfio_close(regfile);
824		return WERR_REG_FILE_INVALID;
825	}
826
827	result = reg_load_tree(regfile, krecord->name, rootkey);
828
829	/* cleanup */
830
831	regfio_close(regfile);
832
833	return result;
834}
835
836WERROR reg_restorekey(struct registry_key *key, const char *fname)
837{
838	return restore_registry_key(key->key, fname);
839}
840
841/********************************************************************
842********************************************************************/
843
844static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
845			     REGF_NK_REC *parent)
846{
847	REGF_NK_REC *key;
848	struct regval_ctr *values;
849	struct regsubkey_ctr *subkeys;
850	int i, num_subkeys;
851	char *key_tmp = NULL;
852	char *keyname, *parentpath;
853	char *subkeypath = NULL;
854	char *subkeyname;
855	struct registry_key_handle registry_key;
856	WERROR result = WERR_OK;
857	SEC_DESC *sec_desc = NULL;
858
859	if (!regfile) {
860		return WERR_GENERAL_FAILURE;
861	}
862
863	if (!keypath) {
864		return WERR_OBJECT_PATH_INVALID;
865	}
866
867	/* split up the registry key path */
868
869	key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
870	if (!key_tmp) {
871		return WERR_NOMEM;
872	}
873	if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
874		return WERR_OBJECT_PATH_INVALID;
875	}
876
877	if (!keyname) {
878		keyname = parentpath;
879	}
880
881	/* we need a registry_key_handle object here to enumerate subkeys and values */
882
883	ZERO_STRUCT(registry_key);
884
885	registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
886	if (registry_key.name == NULL) {
887		return WERR_NOMEM;
888	}
889
890	registry_key.ops = reghook_cache_find(registry_key.name);
891	if (registry_key.ops == NULL) {
892		return WERR_BADFILE;
893	}
894
895	/* lookup the values and subkeys */
896
897	result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
898	W_ERROR_NOT_OK_RETURN(result);
899
900	values = TALLOC_ZERO_P(subkeys, struct regval_ctr);
901	if (values == NULL) {
902		return WERR_NOMEM;
903	}
904
905	fetch_reg_keys(&registry_key, subkeys);
906	fetch_reg_values(&registry_key, values);
907
908	result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
909	if (!W_ERROR_IS_OK(result)) {
910		goto done;
911	}
912
913	/* write out this key */
914
915	key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
916			       parent);
917	if (key == NULL) {
918		result = WERR_CAN_NOT_COMPLETE;
919		goto done;
920	}
921
922	/* write each one of the subkeys out */
923
924	num_subkeys = regsubkey_ctr_numkeys(subkeys);
925	for (i=0; i<num_subkeys; i++) {
926		subkeyname = regsubkey_ctr_specific_key(subkeys, i);
927		subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
928					     keypath, subkeyname);
929		if (subkeypath == NULL) {
930			result = WERR_NOMEM;
931			goto done;
932		}
933		result = reg_write_tree(regfile, subkeypath, key);
934		if (!W_ERROR_IS_OK(result))
935			goto done;
936	}
937
938	DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
939
940done:
941	TALLOC_FREE(subkeys);
942	TALLOC_FREE(registry_key.name);
943
944	return result;
945}
946
947static WERROR backup_registry_key(struct registry_key_handle *krecord,
948				  const char *fname)
949{
950	REGF_FILE *regfile;
951	WERROR result;
952
953	/* open the registry file....fail if the file already exists */
954
955	regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
956			      (S_IRUSR|S_IWUSR));
957	if (regfile == NULL) {
958		DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
959			 fname, strerror(errno) ));
960		return ntstatus_to_werror(map_nt_error_from_unix(errno));
961	}
962
963	/* write the registry tree to the file  */
964
965	result = reg_write_tree(regfile, krecord->name, NULL);
966
967	/* cleanup */
968
969	regfio_close(regfile);
970
971	return result;
972}
973
974WERROR reg_savekey(struct registry_key *key, const char *fname)
975{
976	return backup_registry_key(key->key, fname);
977}
978
979/**********************************************************************
980 * Higher level utility functions
981 **********************************************************************/
982
983WERROR reg_deleteallvalues(struct registry_key *key)
984{
985	WERROR err;
986	int i;
987
988	if (!(key->key->access_granted & KEY_SET_VALUE)) {
989		return WERR_ACCESS_DENIED;
990	}
991
992	if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
993		return err;
994	}
995
996	for (i=0; i<key->values->num_values; i++) {
997		regval_ctr_delvalue(key->values, key->values->values[i]->valuename);
998	}
999
1000	if (!store_reg_values(key->key, key->values)) {
1001		TALLOC_FREE(key->values);
1002		return WERR_REG_IO_FAILURE;
1003	}
1004
1005	return WERR_OK;
1006}
1007
1008/*
1009 * Utility function to open a complete registry path including the hive prefix.
1010 */
1011
1012WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1013		     uint32 desired_access, const struct nt_user_token *token,
1014		     struct registry_key **pkey)
1015{
1016	struct registry_key *hive, *key;
1017	char *path, *p;
1018	WERROR err;
1019
1020	if (!(path = SMB_STRDUP(orig_path))) {
1021		return WERR_NOMEM;
1022	}
1023
1024	p = strchr(path, '\\');
1025
1026	if ((p == NULL) || (p[1] == '\0')) {
1027		/*
1028		 * No key behind the hive, just return the hive
1029		 */
1030
1031		err = reg_openhive(mem_ctx, path, desired_access, token,
1032				   &hive);
1033		if (!W_ERROR_IS_OK(err)) {
1034			SAFE_FREE(path);
1035			return err;
1036		}
1037		SAFE_FREE(path);
1038		*pkey = hive;
1039		return WERR_OK;
1040	}
1041
1042	*p = '\0';
1043
1044	err = reg_openhive(mem_ctx, path, KEY_ENUMERATE_SUB_KEYS, token,
1045			   &hive);
1046	if (!W_ERROR_IS_OK(err)) {
1047		SAFE_FREE(path);
1048		return err;
1049	}
1050
1051	err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
1052
1053	TALLOC_FREE(hive);
1054	SAFE_FREE(path);
1055
1056	if (!W_ERROR_IS_OK(err)) {
1057		return err;
1058	}
1059
1060	*pkey = key;
1061	return WERR_OK;
1062}
1063
1064/*
1065 * Utility function to delete a registry key with all its subkeys.
1066 * Note that reg_deletekey returns ACCESS_DENIED when called on a
1067 * key that has subkeys.
1068 */
1069static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
1070					       struct registry_key *parent,
1071					       const char *path,
1072					       bool del_key)
1073{
1074	TALLOC_CTX *mem_ctx = NULL;
1075	WERROR werr = WERR_OK;
1076	struct registry_key *key;
1077	char *subkey_name = NULL;
1078	uint32 i;
1079
1080	mem_ctx = talloc_new(ctx);
1081	if (mem_ctx == NULL) {
1082		werr = WERR_NOMEM;
1083		goto done;
1084	}
1085
1086	/* recurse through subkeys first */
1087	werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
1088	if (!W_ERROR_IS_OK(werr)) {
1089		goto done;
1090	}
1091
1092	werr = fill_subkey_cache(key);
1093	W_ERROR_NOT_OK_GOTO_DONE(werr);
1094
1095	/*
1096	 * loop from top to bottom for perfomance:
1097	 * this way, we need to rehash the regsubkey containers less
1098	 */
1099	for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
1100		subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
1101		werr = reg_deletekey_recursive_internal(mem_ctx, key,
1102					subkey_name,
1103					true);
1104		W_ERROR_NOT_OK_GOTO_DONE(werr);
1105	}
1106
1107	if (del_key) {
1108		/* now delete the actual key */
1109		werr = reg_deletekey(parent, path);
1110	}
1111
1112done:
1113	TALLOC_FREE(mem_ctx);
1114	return werr;
1115}
1116
1117static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx,
1118					    struct registry_key *parent,
1119					    const char *path,
1120					    bool del_key)
1121{
1122	WERROR werr;
1123
1124	werr = regdb_transaction_start();
1125	if (!W_ERROR_IS_OK(werr)) {
1126		DEBUG(0, ("reg_deletekey_recursive_trans: "
1127			  "error starting transaction: %s\n",
1128			  win_errstr(werr)));
1129		return werr;
1130	}
1131
1132	werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key);
1133
1134	if (!W_ERROR_IS_OK(werr)) {
1135		DEBUG(1, (__location__ " failed to delete key '%s' from key "
1136			  "'%s': %s\n", path, parent->key->name,
1137			  win_errstr(werr)));
1138		werr = regdb_transaction_cancel();
1139		if (!W_ERROR_IS_OK(werr)) {
1140			DEBUG(0, ("reg_deletekey_recursive_trans: "
1141				  "error cancelling transaction: %s\n",
1142				  win_errstr(werr)));
1143		}
1144	} else {
1145		werr = regdb_transaction_commit();
1146		if (!W_ERROR_IS_OK(werr)) {
1147			DEBUG(0, ("reg_deletekey_recursive_trans: "
1148				  "error committing transaction: %s\n",
1149				  win_errstr(werr)));
1150		}
1151	}
1152
1153	return werr;
1154}
1155
1156WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
1157			       struct registry_key *parent,
1158			       const char *path)
1159{
1160	return reg_deletekey_recursive_trans(ctx, parent, path, true);
1161}
1162
1163WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
1164				   struct registry_key *parent,
1165				   const char *path)
1166{
1167	return reg_deletekey_recursive_trans(ctx, parent, path, false);
1168}
1169
1170#if 0
1171/* these two functions are unused. */
1172
1173/**
1174 * Utility function to create a registry key without opening the hive
1175 * before. Assumes the hive already exists.
1176 */
1177
1178WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path,
1179		       uint32 desired_access,
1180		       const struct nt_user_token *token,
1181		       enum winreg_CreateAction *paction,
1182		       struct registry_key **pkey)
1183{
1184	struct registry_key *hive;
1185	char *path, *p;
1186	WERROR err;
1187
1188	if (!(path = SMB_STRDUP(orig_path))) {
1189		return WERR_NOMEM;
1190	}
1191
1192	p = strchr(path, '\\');
1193
1194	if ((p == NULL) || (p[1] == '\0')) {
1195		/*
1196		 * No key behind the hive, just return the hive
1197		 */
1198
1199		err = reg_openhive(mem_ctx, path, desired_access, token,
1200				   &hive);
1201		if (!W_ERROR_IS_OK(err)) {
1202			SAFE_FREE(path);
1203			return err;
1204		}
1205		SAFE_FREE(path);
1206		*pkey = hive;
1207		*paction = REG_OPENED_EXISTING_KEY;
1208		return WERR_OK;
1209	}
1210
1211	*p = '\0';
1212
1213	err = reg_openhive(mem_ctx, path,
1214			   (strchr(p+1, '\\') != NULL) ?
1215			   KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
1216			   token, &hive);
1217	if (!W_ERROR_IS_OK(err)) {
1218		SAFE_FREE(path);
1219		return err;
1220	}
1221
1222	err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction);
1223	SAFE_FREE(path);
1224	TALLOC_FREE(hive);
1225	return err;
1226}
1227
1228/*
1229 * Utility function to create a registry key without opening the hive
1230 * before. Will not delete a hive.
1231 */
1232
1233WERROR reg_delete_path(const struct nt_user_token *token,
1234		       const char *orig_path)
1235{
1236	struct registry_key *hive;
1237	char *path, *p;
1238	WERROR err;
1239
1240	if (!(path = SMB_STRDUP(orig_path))) {
1241		return WERR_NOMEM;
1242	}
1243
1244	p = strchr(path, '\\');
1245
1246	if ((p == NULL) || (p[1] == '\0')) {
1247		SAFE_FREE(path);
1248		return WERR_INVALID_PARAM;
1249	}
1250
1251	*p = '\0';
1252
1253	err = reg_openhive(NULL, path,
1254			   (strchr(p+1, '\\') != NULL) ?
1255			   KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY,
1256			   token, &hive);
1257	if (!W_ERROR_IS_OK(err)) {
1258		SAFE_FREE(path);
1259		return err;
1260	}
1261
1262	err = reg_deletekey(hive, p+1);
1263	SAFE_FREE(path);
1264	TALLOC_FREE(hive);
1265	return err;
1266}
1267#endif /* #if 0 */
1268