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