s3:registry: move reg_api_regf prototypes to their own header file.
[amitay/samba.git] / source3 / registry / reg_api_regf.c
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 #include "includes.h"
22 #include "registry.h"
23 #include "reg_api_regf.h"
24 #include "reg_cachehook.h"
25 #include "regfio.h"
26 #include "reg_util_internal.h"
27 #include "reg_dispatcher.h"
28 #include "reg_objects.h"
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_REGISTRY
32
33 /*******************************************************************
34  Note: topkeypat is the *full* path that this *key will be
35  loaded into (including the name of the key)
36  ********************************************************************/
37
38 static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
39                             REGF_NK_REC *key)
40 {
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;
48
49         /* initialize the struct registry_key_handle structure */
50
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;
56         }
57
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;
62         }
63
64         /* now start parsing the values and subkeys */
65
66         result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
67         W_ERROR_NOT_OK_RETURN(result);
68
69         result = regval_ctr_init(subkeys, &values);
70         W_ERROR_NOT_OK_RETURN(result);
71
72         /* copy values into the struct regval_ctr */
73
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));
79         }
80
81         /* copy subkeys into the struct regsubkey_ctr */
82
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;
89                 }
90         }
91
92         /* write this key and values out */
93
94         if (!store_reg_values(&registry_key, values)
95             || !store_reg_keys(&registry_key, subkeys))
96         {
97                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
98                 result = WERR_REG_IO_FAILURE;
99         }
100
101         TALLOC_FREE(subkeys);
102
103         if (!W_ERROR_IS_OK(result)) {
104                 return result;
105         }
106
107         /* now continue to load each subkey registry tree */
108
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;
117                 }
118                 result = reg_load_tree(regfile, path, subkey);
119                 if (!W_ERROR_IS_OK(result)) {
120                         break;
121                 }
122         }
123
124         return result;
125 }
126
127 /*******************************************************************
128  ********************************************************************/
129
130 static WERROR restore_registry_key(struct registry_key_handle *krecord,
131                                    const char *fname)
132 {
133         REGF_FILE *regfile;
134         REGF_NK_REC *rootkey;
135         WERROR result;
136
137         /* open the registry file....fail if the file already exists */
138
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));
144         }
145
146         /* get the rootkey from the regf file and then load the tree
147            via recursive calls */
148
149         if (!(rootkey = regfio_rootkey(regfile))) {
150                 regfio_close(regfile);
151                 return WERR_REG_FILE_INVALID;
152         }
153
154         result = reg_load_tree(regfile, krecord->name, rootkey);
155
156         /* cleanup */
157
158         regfio_close(regfile);
159
160         return result;
161 }
162
163 WERROR reg_restorekey(struct registry_key *key, const char *fname)
164 {
165         return restore_registry_key(key->key, fname);
166 }
167
168 /********************************************************************
169 ********************************************************************/
170
171 static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
172                              REGF_NK_REC *parent)
173 {
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;
185
186         if (!regfile) {
187                 return WERR_GENERAL_FAILURE;
188         }
189
190         if (!keypath) {
191                 return WERR_OBJECT_PATH_INVALID;
192         }
193
194         /* split up the registry key path */
195
196         key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
197         if (!key_tmp) {
198                 return WERR_NOMEM;
199         }
200         if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
201                 return WERR_OBJECT_PATH_INVALID;
202         }
203
204         if (!keyname) {
205                 keyname = parentpath;
206         }
207
208         /* we need a registry_key_handle object here to enumerate subkeys and values */
209
210         ZERO_STRUCT(registry_key);
211
212         registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
213         if (registry_key.name == NULL) {
214                 return WERR_NOMEM;
215         }
216
217         registry_key.ops = reghook_cache_find(registry_key.name);
218         if (registry_key.ops == NULL) {
219                 return WERR_BADFILE;
220         }
221
222         /* lookup the values and subkeys */
223
224         result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
225         W_ERROR_NOT_OK_RETURN(result);
226
227         result = regval_ctr_init(subkeys, &values);
228         W_ERROR_NOT_OK_RETURN(result);
229
230         fetch_reg_keys(&registry_key, subkeys);
231         fetch_reg_values(&registry_key, values);
232
233         result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
234         if (!W_ERROR_IS_OK(result)) {
235                 goto done;
236         }
237
238         /* write out this key */
239
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;
245         }
246
247         /* write each one of the subkeys out */
248
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;
257                 }
258                 result = reg_write_tree(regfile, subkeypath, key);
259                 if (!W_ERROR_IS_OK(result))
260                         goto done;
261         }
262
263         DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
264
265 done:
266         TALLOC_FREE(subkeys);
267         TALLOC_FREE(registry_key.name);
268
269         return result;
270 }
271
272 static WERROR backup_registry_key(struct registry_key_handle *krecord,
273                                   const char *fname)
274 {
275         REGF_FILE *regfile;
276         WERROR result;
277
278         /* open the registry file....fail if the file already exists */
279
280         regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
281                               (S_IREAD|S_IWRITE));
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));
286         }
287
288         /* write the registry tree to the file  */
289
290         result = reg_write_tree(regfile, krecord->name, NULL);
291
292         /* cleanup */
293
294         regfio_close(regfile);
295
296         return result;
297 }
298
299 WERROR reg_savekey(struct registry_key *key, const char *fname)
300 {
301         return backup_registry_key(key->key, fname);
302 }