s4-torture: smb2 copychunk data integrity checks
[Samba/gbeck.git] / source3 / registry / reg_api_regf.c
blob97eab03a7069a8978a64e82862b71ab3da3b7799
1 /*
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/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "registry.h"
24 #include "reg_api_regf.h"
25 #include "reg_cachehook.h"
26 #include "regfio.h"
27 #include "reg_util_internal.h"
28 #include "reg_dispatcher.h"
30 #undef DBGC_CLASS
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,
39 REGF_NK_REC *key)
41 REGF_NK_REC *subkey;
42 struct registry_key_handle registry_key;
43 struct regval_ctr *values;
44 struct regsubkey_ctr *subkeys;
45 int i;
46 char *path = NULL;
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));
55 return WERR_BADFILE;
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"));
61 return WERR_NOMEM;
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,
76 key->values[i].type,
77 key->values[i].data,
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)) {
87 TALLOC_FREE(subkeys);
88 return result;
92 /* write this key and values out */
94 if (!store_reg_values(&registry_key, values)
95 || !store_reg_keys(&registry_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)) {
104 return 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,
112 "%s\\%s",
113 topkeypath,
114 subkey->keyname);
115 if (path == NULL) {
116 return WERR_NOMEM;
118 result = reg_load_tree(regfile, path, subkey);
119 if (!W_ERROR_IS_OK(result)) {
120 break;
124 return result;
127 /*******************************************************************
128 ********************************************************************/
130 static WERROR restore_registry_key(struct registry_key_handle *krecord,
131 const char *fname)
133 REGF_FILE *regfile;
134 REGF_NK_REC *rootkey;
135 WERROR result;
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);
156 /* cleanup */
158 regfio_close(regfile);
160 return result;
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,
172 REGF_NK_REC *parent)
174 REGF_NK_REC *key;
175 struct regval_ctr *values;
176 struct regsubkey_ctr *subkeys;
177 int i, num_subkeys;
178 char *key_tmp = NULL;
179 char *keyname, *parentpath;
180 char *subkeypath = NULL;
181 char *subkeyname;
182 struct registry_key_handle registry_key;
183 WERROR result = WERR_OK;
184 struct security_descriptor *sec_desc = NULL;
186 if (!regfile) {
187 return WERR_GENERAL_FAILURE;
190 if (!keypath) {
191 return WERR_OBJECT_PATH_INVALID;
194 /* split up the registry key path */
196 key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
197 if (!key_tmp) {
198 return WERR_NOMEM;
200 if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
201 return WERR_OBJECT_PATH_INVALID;
204 if (!keyname) {
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) {
214 return WERR_NOMEM;
217 registry_key.ops = reghook_cache_find(registry_key.name);
218 if (registry_key.ops == NULL) {
219 return WERR_BADFILE;
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(&registry_key, subkeys);
231 fetch_reg_values(&registry_key, values);
233 result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
234 if (!W_ERROR_IS_OK(result)) {
235 goto done;
238 /* write out this key */
240 key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
241 parent);
242 if (key == NULL) {
243 result = WERR_CAN_NOT_COMPLETE;
244 goto done;
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) {
255 result = WERR_NOMEM;
256 goto done;
258 result = reg_write_tree(regfile, subkeypath, key);
259 if (!W_ERROR_IS_OK(result))
260 goto done;
263 DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
265 done:
266 TALLOC_FREE(subkeys);
267 TALLOC_FREE(registry_key.name);
269 return result;
272 static WERROR backup_registry_key(struct registry_key_handle *krecord,
273 const char *fname)
275 REGF_FILE *regfile;
276 WERROR result;
278 /* open the registry file....fail if the file already exists */
280 regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
281 (S_IRUSR|S_IWUSR));
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);
292 /* cleanup */
294 regfio_close(regfile);
296 return result;
299 WERROR reg_savekey(struct registry_key *key, const char *fname)
301 return backup_registry_key(key->key, fname);