s3-registry: fix bug #8401 - registry/reg_format.c must include includes.h.
[kai/samba.git] / source3 / registry / reg_import.c
1 /*
2  * Samba Unix/Linux SMB client library
3  * Adapter to use reg_parse with the registry api
4  *
5  * Copyright (C) Gregor Beck 2010
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 "reg_parse.h"
23 #include "reg_import.h"
24 #include "registry.h"
25 #include "registry/reg_objects.h"
26 #include <assert.h>
27
28 /* Debuglevel for tracing */
29 static const int TL = 2;
30
31 struct reg_import
32 {
33         struct reg_parse_callback reg_parse_callback;
34         struct reg_import_callback call;
35         void* open_key;
36 };
37
38 static int
39 reg_parse_callback_key(struct reg_import* cb_private,
40                        const char* key[], size_t n,
41                        bool del);
42
43 static int
44 reg_parse_callback_val(struct reg_import* cb_private,
45                        const char* name, uint32_t type,
46                        const uint8_t* data, uint32_t len);
47
48 static int
49 reg_parse_callback_val_registry_value(struct reg_import* cb_private,
50                                       const char* name, uint32_t type,
51                                       const uint8_t* data, uint32_t len);
52
53 static int
54 reg_parse_callback_val_regval_blob(struct reg_import* cb_private,
55                                    const char* name, uint32_t type,
56                                    const uint8_t* data, uint32_t len);
57
58 static int
59 reg_parse_callback_val_del(struct reg_import* cb_private,
60                            const char* name);
61
62 static int
63 reg_parse_callback_comment(struct reg_import* cb_private,
64                            const char* txt);
65
66
67 /*******************************************************************************/
68
69 int reg_parse_callback_key(struct reg_import* p,
70                            const char* key[], size_t n, bool del)
71 {
72         WERROR werr = WERR_OK;
73
74         DEBUG(TL, ("%s: %s\n", __FUNCTION__, key[0]));
75
76         if (p->open_key != NULL ) {
77                 werr = p->call.closekey(p->call.data, p->open_key);
78                 if (!W_ERROR_IS_OK(werr)) {
79                         DEBUG(0, ("closekey failed: %s\n", win_errstr(werr)));
80                 }
81         }
82
83         if (del) {
84                 werr = p->call.deletekey(p->call.data, NULL, key[0]);
85                 if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
86                         /* the key didn't exist, treat as success */
87                         werr = WERR_OK;
88                 }
89                 if (!W_ERROR_IS_OK(werr)) {
90                         DEBUG(0, ("deletekey %s failed: %s\n",
91                                   key[0], win_errstr(werr)));
92                 }
93         }
94         else {
95                 bool existing;
96                 werr = p->call.createkey(p->call.data, NULL, key[0],
97                                          &p->open_key, &existing);
98                 if (W_ERROR_IS_OK(werr)) {
99                         DEBUG(TL, ("createkey %s %s\n",
100                                   existing ? "opened" : "created", key[0]));
101                 } else {
102                         DEBUG(0, ("createkey %s failed: %s\n",
103                                   key[0], win_errstr(werr)));
104                 }
105         }
106
107         return W_ERROR_IS_OK(werr) ? 0 : -1;
108 }
109
110 #define DEBUG_ADD_HEX(LEV, PTR, LEN)                                    \
111         do {                                                            \
112                 int i;                                                  \
113                 const unsigned char* ptr = (const unsigned char*)PTR;   \
114                 for (i=0; i<LEN; i++) {                                 \
115                         DEBUGADD(LEV, ("'%c'(%02x)%s",                  \
116                                        isprint(ptr[i]) ? ptr[i] : '.',  \
117                                        (unsigned)ptr[i],                \
118                                        ((i+1 < LEN) && (i+1)%8)         \
119                                        ? ",  " : "\n"));                \
120                 }                                                       \
121         } while(0)
122
123 /*----------------------------------------------------------------------------*/
124 int reg_parse_callback_val(struct reg_import* p,
125                            const char* name, uint32_t type,
126                            const uint8_t* data, uint32_t len)
127 {
128         WERROR werr = WERR_OK;
129
130         DEBUG(TL, ("%s(%x): >%s< = [%x]\n",  __FUNCTION__, type, name, len));
131         DEBUG_ADD_HEX(TL, data, len);
132
133         werr = p->call.setval.blob(p->call.data, p->open_key, name, type,
134                                    data, len);
135         if (!W_ERROR_IS_OK(werr)) {
136                 DEBUG(0, ("setval %s failed: %s\n",
137                           name, win_errstr(werr)));
138         }
139
140         return W_ERROR_IS_OK(werr) ? 0 : -1;
141 }
142
143 /*----------------------------------------------------------------------------*/
144 int reg_parse_callback_val_registry_value(struct reg_import* p,
145                                           const char* name, uint32_t type,
146                                           const uint8_t* data, uint32_t len)
147 {
148         WERROR werr = WERR_OK;
149         struct registry_value val = {
150                 .type = type,
151                 .data = data_blob_talloc(p, data, len),
152         };
153
154         DEBUG(TL, ("%s(%x): >%s< = [%x]\n", __FUNCTION__, type, name, len));
155         DEBUG_ADD_HEX(TL, data, len);
156
157         werr = p->call.setval.registry_value(p->call.data, p->open_key,
158                                              name, &val);
159         if (!W_ERROR_IS_OK(werr)) {
160                 DEBUG(0, ("setval %s failed: %s\n",
161                           name, win_errstr(werr)));
162         }
163
164         data_blob_free(&val.data);
165         return W_ERROR_IS_OK(werr) ? 0 : -1;
166 }
167
168 /*----------------------------------------------------------------------------*/
169 int reg_parse_callback_val_regval_blob(struct reg_import* p,
170                                        const char* name, uint32_t type,
171                                        const uint8_t* data, uint32_t len)
172 {
173         WERROR werr = WERR_OK;
174         void* mem_ctx = talloc_new(p);
175         struct regval_blob* v = NULL;
176
177         DEBUG(TL, ("%s(%x): >%s< = [%x]\n", __FUNCTION__, type, name, len));
178         DEBUG_ADD_HEX(TL, data, len);
179
180         v = regval_compose(mem_ctx, name, type, data, len);
181         if (v == NULL) {
182                 DEBUG(0, ("regval_compose %s failed\n", name));
183                 werr = WERR_NOMEM;
184                 goto done;
185         }
186
187         werr = p->call.setval.regval_blob(p->call.data, p->open_key, v);
188         if (!W_ERROR_IS_OK(werr)) {
189                 DEBUG(0, ("setval %s failed: %s\n",
190                           name, win_errstr(werr)));
191         }
192
193 done:
194         talloc_free(mem_ctx);
195
196         return W_ERROR_IS_OK(werr) ? 0 : -1;
197 }
198
199
200 /*----------------------------------------------------------------------------*/
201
202 int reg_parse_callback_val_del(struct reg_import* p,
203                                const char* name)
204 {
205         WERROR werr = WERR_OK;
206
207         DEBUG(TL, ("%s: %s\n", __FUNCTION__, name));
208
209         werr = p->call.deleteval(p->call.data, p->open_key, name);
210         if (!W_ERROR_IS_OK(werr)) {
211                 DEBUG(0, ("deleteval %s failed: %s\n",
212                           name, win_errstr(werr)));
213         }
214
215         return W_ERROR_IS_OK(werr) ? 0 : -1;
216 }
217
218
219 int reg_parse_callback_comment(struct reg_import* cb_private,
220                                const char* txt)
221 {
222         DEBUG(TL, ("%s: %s\n", __FUNCTION__, txt));
223         return 0;
224 }
225
226 /******************************************************************************/
227 static int nop(void* data)
228 {
229         return 0;
230 }
231
232
233 struct reg_parse_callback* reg_import_adapter(const void* talloc_ctx,
234                                               struct reg_import_callback cb)
235 {
236         struct reg_parse_callback* ret;
237         struct reg_import* p = talloc_zero(talloc_ctx, struct reg_import);
238         if (p == NULL) {
239                 goto fail;
240         }
241         if (cb.openkey == NULL ) {
242                 cb.openkey = (reg_import_callback_openkey_t)&nop;
243         }
244         if (cb.closekey == NULL ) {
245                 cb.closekey = (reg_import_callback_closekey_t)&nop;
246         }
247         if (cb.createkey == NULL ) {
248                 cb.createkey = (reg_import_callback_createkey_t)&nop;
249         }
250         if (cb.deletekey == NULL ) {
251                 cb.deletekey = (reg_import_callback_deletekey_t)&nop;
252         }
253         if (cb.deleteval == NULL ) {
254                 cb.deleteval = (reg_import_callback_deleteval_t)&nop;
255         }
256
257         p->call = cb;
258
259         ret = &p->reg_parse_callback;
260         ret->key     = (reg_parse_callback_key_t)     &reg_parse_callback_key;
261         ret->val_del = (reg_parse_callback_val_del_t) &reg_parse_callback_val_del;
262         ret->comment = (reg_parse_callback_comment_t) &reg_parse_callback_comment;
263         ret->data = p;
264
265         switch (cb.setval_type) {
266         case BLOB:
267                 assert(cb.setval.blob != NULL);
268                 ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val;
269                 break;
270         case REGISTRY_VALUE:
271                 assert(cb.setval.registry_value != NULL);
272                 ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val_registry_value;
273                 break;
274         case REGVAL_BLOB:
275                 assert(cb.setval.regval_blob != NULL);
276                 ret->val = (reg_parse_callback_val_t) &reg_parse_callback_val_regval_blob;
277                 break;
278         case NONE:
279                 ret->val = NULL;
280                 break;
281         default:
282                 assert(false);
283         }
284
285         assert((struct reg_parse_callback*)p == ret);
286         return ret;
287 fail:
288         talloc_free(p);
289         return NULL;
290 }