Fix PReg write support.
[jra/samba/.git] / source4 / lib / registry / tests / diff.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    local testing of registry diff functionality
5
6    Copyright (C) Jelmer Vernooij 2007
7    Copyright (C) Wilco Baan Hofman 2008
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "lib/registry/registry.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/winreg.h"
27 #include "param/param.h"
28
29 struct diff_tcase_data {
30         struct registry_context *r1_ctx;
31         struct registry_context *r2_ctx;
32         struct reg_diff_callbacks *callbacks;
33         void *callback_data;
34         char *tempdir;
35         char *filename;
36 };
37
38 static bool test_generate_diff(struct torture_context *tctx, void *tcase_data)
39 {
40         /* WERROR reg_generate_diff(struct registry_context *ctx1,
41                                   struct registry_context *ctx2,
42                                   const struct reg_diff_callbacks *callbacks,
43                                   void *callback_data)
44                                   */
45         WERROR error;
46         struct diff_tcase_data *td = tcase_data;
47
48         error = reg_generate_diff(td->r1_ctx, td->r2_ctx, 
49                         td->callbacks,
50                         td->callback_data);
51         torture_assert_werr_ok(tctx, error, "reg_generate_diff");
52
53         return true;
54 }
55
56 #if 0
57 static bool test_diff_load(struct torture_context *tctx, void *tcase_data)
58 {
59         struct diff_tcase_data *td = tcase_data;
60         struct smb_iconv_convenience *ic;
61         struct reg_diff_callbacks *callbacks;
62         void *data;
63         WERROR error;
64
65         ic = lp_iconv_convenience(tctx->lp_ctx);
66
67         error = reg_diff_load(td->filename, iconv_convenience, callbacks, data);
68         torture_assert_werr_ok(tctx, error, "reg_diff_load");
69
70         return true;
71 }
72 #endif
73 static bool test_diff_apply(struct torture_context *tctx, void *tcase_data)
74 {
75         struct diff_tcase_data *td = tcase_data;
76         struct registry_key *key;
77         WERROR error;
78
79         error = reg_diff_apply(td->r1_ctx, td->filename);
80         torture_assert_werr_ok(tctx, error, "reg_diff_apply");
81
82         error = td->r1_ctx->ops->get_predefined_key(td->r1_ctx, HKEY_LOCAL_MACHINE, &key);
83         torture_assert_werr_ok(tctx, error, "Opening HKEY_LOCAL_MACHINE failed");
84
85         /* If this generates an error it could be that the apply doesn't work,
86          * but also that the reg_generate_diff didn't work. */
87         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Software", &key);
88         torture_assert_werr_ok(tctx, error, "Opening HKLM\\Software failed");
89         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Microsoft", &key);
90         torture_assert_werr_ok(tctx, error, "Opening HKLM\\Software\\Microsoft failed");
91         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Windows", &key);
92         torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Microsoft\\Windows failed");
93         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "CurrentVersion", &key);
94         torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Windows\\CurrentVersion failed");
95         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Policies", &key);
96         torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\CurrentVersion\\Policies failed");
97         error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Explorer", &key);
98         torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Policies\\Explorer failed");
99
100         
101
102         return true;
103 }
104
105 static const char *added_key = NULL;
106
107 static WERROR test_add_key(void *callback_data, const char *key_name)
108 {
109         added_key = talloc_strdup(callback_data, key_name);
110
111         return WERR_OK;
112 }
113
114 static bool test_generate_diff_key_add(struct torture_context *tctx, void *tcase_data)
115 {
116         struct reg_diff_callbacks cb;
117         struct registry_key rk;
118
119         return true;
120
121         ZERO_STRUCT(cb);
122
123         cb.add_key = test_add_key;
124
125         if (W_ERROR_IS_OK(reg_generate_diff_key(&rk, NULL, "bla", &cb, tctx)))
126                 return false;
127
128         torture_assert_str_equal(tctx, added_key, "bla", "key added");
129
130         return true;
131 }
132
133 static bool test_generate_diff_key_null(struct torture_context *tctx, void *tcase_data)
134 {
135         struct reg_diff_callbacks cb;
136
137         ZERO_STRUCT(cb);
138
139         if (!W_ERROR_IS_OK(reg_generate_diff_key(NULL, NULL, "", &cb, NULL)))
140                 return false;
141
142         return true;
143 }
144 static void tcase_add_tests (struct torture_tcase *tcase) 
145 {
146         torture_tcase_add_simple_test(tcase, "test_generate_diff_key_add",
147                         test_generate_diff_key_add);
148         torture_tcase_add_simple_test(tcase, "test_generate_diff_key_null",
149                         test_generate_diff_key_null);
150         torture_tcase_add_simple_test(tcase, "test_generate_diff",
151                         test_generate_diff);
152         torture_tcase_add_simple_test(tcase, "test_diff_apply",
153                         test_diff_apply);
154 /*      torture_tcase_add_simple_test(tcase, "test_diff_load",
155                         test_diff_load);
156 */
157 }
158
159 static bool diff_setup_tcase(struct torture_context *tctx, void **data)
160 {
161         struct registry_context *r1_ctx, *r2_ctx;
162         WERROR error;
163         NTSTATUS status;
164         struct hive_key *r1_hklm, *r1_hkcu;
165         struct hive_key *r2_hklm, *r2_hkcu;
166         const char *filename;
167         struct diff_tcase_data *td;
168         struct registry_key *key, *newkey;
169         DATA_BLOB blob;
170
171         td = talloc(tctx, struct diff_tcase_data);
172
173         /* Create two registry contexts */
174         error = reg_open_local(tctx, &r1_ctx, NULL, NULL);
175         torture_assert_werr_ok(tctx, error, "Opening registry 1 for patch tests failed");
176         
177         error = reg_open_local(tctx, &r2_ctx, NULL, NULL);
178         torture_assert_werr_ok(tctx, error, "Opening registry 2 for patch tests failed");
179
180         /* Create temp directory */
181         status = torture_temp_dir(tctx, "patchfile", &td->tempdir);
182         torture_assert_ntstatus_ok(tctx, status, "Creating temp dir failed");
183
184         /* Create and mount HKLM and HKCU hives for registry 1 */
185         filename = talloc_asprintf(tctx, "%s/r1_local_machine.ldb", td->tempdir);
186         error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r1_hklm);
187         torture_assert_werr_ok(tctx, error, "Opening local machine file failed");
188
189         error = reg_mount_hive(r1_ctx, r1_hklm, HKEY_LOCAL_MACHINE, NULL);
190         torture_assert_werr_ok(tctx, error, "Mounting hive failed");
191         
192         filename = talloc_asprintf(tctx, "%s/r1_current_user.ldb", td->tempdir);
193         error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r1_hkcu);
194         torture_assert_werr_ok(tctx, error, "Opening current user file failed");
195
196         error = reg_mount_hive(r1_ctx, r1_hkcu, HKEY_CURRENT_USER, NULL);
197         torture_assert_werr_ok(tctx, error, "Mounting hive failed");
198         
199         /* Create and mount HKLM and HKCU hives for registry 2 */
200         filename = talloc_asprintf(tctx, "%s/r2_local_machine.ldb", td->tempdir);
201         error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r2_hklm);
202         torture_assert_werr_ok(tctx, error, "Opening local machine file failed");
203
204         error = reg_mount_hive(r2_ctx, r2_hklm, HKEY_LOCAL_MACHINE, NULL);
205         torture_assert_werr_ok(tctx, error, "Mounting hive failed");
206         
207         filename = talloc_asprintf(tctx, "%s/r2_current_user.ldb", td->tempdir);
208         error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r2_hkcu);
209         torture_assert_werr_ok(tctx, error, "Opening current user file failed");
210         
211         error = reg_mount_hive(r2_ctx, r2_hkcu, HKEY_CURRENT_USER, NULL);
212         torture_assert_werr_ok(tctx, error, "Mounting hive failed");
213
214         error = r1_ctx->ops->get_predefined_key(r2_ctx, HKEY_LOCAL_MACHINE, &key);
215         torture_assert_werr_ok(tctx, error, "Opening HKEY_LOCAL_MACHINE failed");
216         error = r1_ctx->ops->create_key(r2_ctx, key, "Software", NULL, NULL, &newkey);
217         torture_assert_werr_ok(tctx, error, "Creating HKLM\\Sofware failed");
218         error = r1_ctx->ops->create_key(r2_ctx, newkey, "Microsoft", NULL, NULL, &newkey);
219         torture_assert_werr_ok(tctx, error, "Creating HKLM\\Software\\Microsoft failed");
220         error = r1_ctx->ops->create_key(r2_ctx, newkey, "Windows", NULL, NULL, &newkey);
221         torture_assert_werr_ok(tctx, error, "Creating HKLM\\Software\\Microsoft\\Windows failed");
222         error = r1_ctx->ops->create_key(r2_ctx, newkey, "CurrentVersion", NULL, NULL, &newkey);
223         torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Windows\\CurrentVersion failed");
224         error = r1_ctx->ops->create_key(r2_ctx, newkey, "Policies", NULL, NULL, &newkey);
225         torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\CurrentVersion\\Policies failed");
226         error = r1_ctx->ops->create_key(r2_ctx, newkey, "Explorer", NULL, NULL, &newkey);
227         torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Policies\\Explorer failed");
228
229         blob.data = (void *)talloc(r2_ctx, uint32_t);
230         SIVAL(blob.data, 0, 0x03ffffff);
231         blob.length = sizeof(uint32_t);
232
233         r1_ctx->ops->set_value(newkey, "NoDrives", REG_DWORD, blob);
234
235         /* Set test case data */
236         td->r1_ctx = r1_ctx;
237         td->r2_ctx = r2_ctx;
238
239         *data = td;
240
241         return true;
242 }
243
244 static bool diff_setup_preg_tcase (struct torture_context *tctx, void **data)
245 {
246         struct diff_tcase_data *td;
247         struct smb_iconv_convenience *ic;
248         WERROR error;
249
250         diff_setup_tcase(tctx, data);
251         td = *data;
252
253         ic = lp_iconv_convenience(tctx->lp_ctx);
254
255         td->filename = talloc_asprintf(tctx, "%s/test.pol", td->tempdir);
256         error = reg_preg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
257         torture_assert_werr_ok(tctx, error, "reg_preg_diff_save");
258
259         return true;
260 }
261
262 static bool diff_setup_dotreg_tcase (struct torture_context *tctx, void **data)
263 {
264         struct diff_tcase_data *td;
265         struct smb_iconv_convenience *ic;
266         WERROR error;
267
268         diff_setup_tcase(tctx, data);
269         td = *data;
270
271         ic = lp_iconv_convenience(tctx->lp_ctx);
272         
273         td->filename = talloc_asprintf(tctx, "%s/test.reg", td->tempdir);
274         error = reg_dotreg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
275         torture_assert_werr_ok(tctx, error, "reg_dotreg_diff_save");
276
277         return true;
278 }
279 static bool diff_teardown_tcase (struct torture_context *tctx, void *data)
280 {
281         /* Done is called by generate_diff itself! */
282
283         return true;
284 }
285 struct torture_suite *torture_registry_diff(TALLOC_CTX *mem_ctx)
286 {
287         struct torture_tcase *tcase;
288         struct torture_suite *suite = torture_suite_create(mem_ctx, "DIFF");
289
290         tcase = torture_suite_add_tcase(suite, "PReg");
291         torture_tcase_set_fixture(tcase, diff_setup_preg_tcase, diff_teardown_tcase);
292         tcase_add_tests(tcase);
293
294         tcase = torture_suite_add_tcase(suite, "dotreg");
295         torture_tcase_set_fixture(tcase, diff_setup_dotreg_tcase, diff_teardown_tcase);
296         tcase_add_tests(tcase);
297
298         return suite;
299 }