2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Volker Lendecke 2006
5 * Copyright (C) Michael Adam 2007-2008
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.
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.
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/>.
22 #include "system/filesys.h"
24 #include "reg_api_regf.h"
25 #include "reg_cachehook.h"
27 #include "reg_util_internal.h"
28 #include "reg_dispatcher.h"
31 #define DBGC_CLASS DBGC_REGISTRY
33 /*******************************************************************
34 Note: topkeypat is the *full* path that this *key will be
35 loaded into (including the name of the key)
36 ********************************************************************/
38 static WERROR
reg_load_tree(REGF_FILE
*regfile
, const char *topkeypath
,
42 struct registry_key_handle registry_key
;
43 struct regval_ctr
*values
;
44 struct regsubkey_ctr
*subkeys
;
47 WERROR result
= WERR_OK
;
49 /* initialize the struct registry_key_handle structure */
51 registry_key
.ops
= reghook_cache_find(topkeypath
);
52 if (!registry_key
.ops
) {
53 DEBUG(0, ("reg_load_tree: Failed to assign registry_ops "
54 "to [%s]\n", topkeypath
));
58 registry_key
.name
= talloc_strdup(regfile
->mem_ctx
, topkeypath
);
59 if (!registry_key
.name
) {
60 DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
64 /* now start parsing the values and subkeys */
66 result
= regsubkey_ctr_init(regfile
->mem_ctx
, &subkeys
);
67 W_ERROR_NOT_OK_RETURN(result
);
69 result
= regval_ctr_init(subkeys
, &values
);
70 W_ERROR_NOT_OK_RETURN(result
);
72 /* copy values into the struct regval_ctr */
74 for (i
=0; i
<key
->num_values
; i
++) {
75 regval_ctr_addvalue(values
, key
->values
[i
].valuename
,
78 (key
->values
[i
].data_size
& ~VK_DATA_IN_OFFSET
));
81 /* copy subkeys into the struct regsubkey_ctr */
83 key
->subkey_index
= 0;
84 while ((subkey
= regfio_fetch_subkey( regfile
, key
))) {
85 result
= regsubkey_ctr_addkey(subkeys
, subkey
->keyname
);
86 if (!W_ERROR_IS_OK(result
)) {
92 /* write this key and values out */
94 if (!store_reg_values(®istry_key
, values
)
95 || !store_reg_keys(®istry_key
, subkeys
))
97 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath
));
98 result
= WERR_REG_IO_FAILURE
;
101 TALLOC_FREE(subkeys
);
103 if (!W_ERROR_IS_OK(result
)) {
107 /* now continue to load each subkey registry tree */
109 key
->subkey_index
= 0;
110 while ((subkey
= regfio_fetch_subkey(regfile
, key
))) {
111 path
= talloc_asprintf(regfile
->mem_ctx
,
118 result
= reg_load_tree(regfile
, path
, subkey
);
119 if (!W_ERROR_IS_OK(result
)) {
127 /*******************************************************************
128 ********************************************************************/
130 static WERROR
restore_registry_key(struct registry_key_handle
*krecord
,
134 REGF_NK_REC
*rootkey
;
137 /* open the registry file....fail if the file already exists */
139 regfile
= regfio_open(fname
, (O_RDONLY
), 0);
140 if (regfile
== NULL
) {
141 DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
142 fname
, strerror(errno
)));
143 return ntstatus_to_werror(map_nt_error_from_unix(errno
));
146 /* get the rootkey from the regf file and then load the tree
147 via recursive calls */
149 if (!(rootkey
= regfio_rootkey(regfile
))) {
150 regfio_close(regfile
);
151 return WERR_REG_FILE_INVALID
;
154 result
= reg_load_tree(regfile
, krecord
->name
, rootkey
);
158 regfio_close(regfile
);
163 WERROR
reg_restorekey(struct registry_key
*key
, const char *fname
)
165 return restore_registry_key(key
->key
, fname
);
168 /********************************************************************
169 ********************************************************************/
171 static WERROR
reg_write_tree(REGF_FILE
*regfile
, const char *keypath
,
175 struct regval_ctr
*values
;
176 struct regsubkey_ctr
*subkeys
;
178 char *key_tmp
= NULL
;
179 char *keyname
, *parentpath
;
180 char *subkeypath
= NULL
;
182 struct registry_key_handle registry_key
;
183 WERROR result
= WERR_OK
;
184 struct security_descriptor
*sec_desc
= NULL
;
187 return WERR_GENERAL_FAILURE
;
191 return WERR_OBJECT_PATH_INVALID
;
194 /* split up the registry key path */
196 key_tmp
= talloc_strdup(regfile
->mem_ctx
, keypath
);
200 if (!reg_split_key(key_tmp
, &parentpath
, &keyname
)) {
201 return WERR_OBJECT_PATH_INVALID
;
205 keyname
= parentpath
;
208 /* we need a registry_key_handle object here to enumerate subkeys and values */
210 ZERO_STRUCT(registry_key
);
212 registry_key
.name
= talloc_strdup(regfile
->mem_ctx
, keypath
);
213 if (registry_key
.name
== NULL
) {
217 registry_key
.ops
= reghook_cache_find(registry_key
.name
);
218 if (registry_key
.ops
== NULL
) {
222 /* lookup the values and subkeys */
224 result
= regsubkey_ctr_init(regfile
->mem_ctx
, &subkeys
);
225 W_ERROR_NOT_OK_RETURN(result
);
227 result
= regval_ctr_init(subkeys
, &values
);
228 W_ERROR_NOT_OK_RETURN(result
);
230 fetch_reg_keys(®istry_key
, subkeys
);
231 fetch_reg_values(®istry_key
, values
);
233 result
= regkey_get_secdesc(regfile
->mem_ctx
, ®istry_key
, &sec_desc
);
234 if (!W_ERROR_IS_OK(result
)) {
238 /* write out this key */
240 key
= regfio_write_key(regfile
, keyname
, values
, subkeys
, sec_desc
,
243 result
= WERR_CAN_NOT_COMPLETE
;
247 /* write each one of the subkeys out */
249 num_subkeys
= regsubkey_ctr_numkeys(subkeys
);
250 for (i
=0; i
<num_subkeys
; i
++) {
251 subkeyname
= regsubkey_ctr_specific_key(subkeys
, i
);
252 subkeypath
= talloc_asprintf(regfile
->mem_ctx
, "%s\\%s",
253 keypath
, subkeyname
);
254 if (subkeypath
== NULL
) {
258 result
= reg_write_tree(regfile
, subkeypath
, key
);
259 if (!W_ERROR_IS_OK(result
))
263 DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath
));
266 TALLOC_FREE(subkeys
);
267 TALLOC_FREE(registry_key
.name
);
272 static WERROR
backup_registry_key(struct registry_key_handle
*krecord
,
278 /* open the registry file....fail if the file already exists */
280 regfile
= regfio_open(fname
, (O_RDWR
|O_CREAT
|O_EXCL
),
282 if (regfile
== NULL
) {
283 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
284 fname
, strerror(errno
) ));
285 return ntstatus_to_werror(map_nt_error_from_unix(errno
));
288 /* write the registry tree to the file */
290 result
= reg_write_tree(regfile
, krecord
->name
, NULL
);
294 regfio_close(regfile
);
299 WERROR
reg_savekey(struct registry_key
*key
, const char *fname
)
301 return backup_registry_key(key
->key
, fname
);