Merge commit 'release-4-0-0alpha1' into v4-0-test
[samba.git] / source / torture / rpc / winreg.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for winreg rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Jelmer Vernooij 2004-2007
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_winreg_c.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "libcli/security/security.h"
27 #include "torture/rpc/rpc.h"
28
29 #define TEST_KEY_BASE "smbtorture test"
30 #define TEST_KEY1 TEST_KEY_BASE "\\spottyfoot"
31 #define TEST_KEY2 TEST_KEY_BASE "\\with a SD (#1)"
32 #define TEST_KEY3 TEST_KEY_BASE "\\with a subkey"
33 #define TEST_SUBKEY TEST_KEY3 "\\subkey"
34
35 static void init_initshutdown_String(TALLOC_CTX *mem_ctx,
36                                      struct initshutdown_String *name,
37                                      const char *s)
38 {
39         name->name = talloc(mem_ctx, struct initshutdown_String_sub);
40         name->name->name = s;
41 }
42
43 static void init_winreg_String(struct winreg_String *name, const char *s)
44 {
45         name->name = s;
46         if (s) {
47                 name->name_len = 2 * (strlen_m(s) + 1);
48                 name->name_size = name->name_len;
49         } else {
50                 name->name_len = 0;
51                 name->name_size = 0;
52         }
53 }
54
55 static bool test_GetVersion(struct dcerpc_pipe *p,
56                             struct torture_context *tctx,
57                             struct policy_handle *handle)
58 {
59         struct winreg_GetVersion r;
60         uint32_t v;
61
62         ZERO_STRUCT(r);
63         r.in.handle = handle;
64         r.out.version = &v;
65
66         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetVersion(p, tctx, &r),
67                                    "GetVersion failed");
68
69         torture_assert_werr_ok(tctx, r.out.result, "GetVersion failed");
70
71         return true;
72 }
73
74 static bool test_NotifyChangeKeyValue(struct dcerpc_pipe *p,
75                                       struct torture_context *tctx,
76                                       struct policy_handle *handle)
77 {
78         struct winreg_NotifyChangeKeyValue r;
79
80         r.in.handle = handle;
81         r.in.watch_subtree = 1;
82         r.in.notify_filter = 0;
83         r.in.unknown = r.in.unknown2 = 0;
84         init_winreg_String(&r.in.string1, NULL);
85         init_winreg_String(&r.in.string2, NULL);
86
87         torture_assert_ntstatus_ok(tctx,
88                                    dcerpc_winreg_NotifyChangeKeyValue(p, tctx, &r),
89                                    "NotifyChangeKeyValue failed");
90
91         if (!W_ERROR_IS_OK(r.out.result)) {
92                 torture_comment(tctx,
93                                 "NotifyChangeKeyValue failed - %s - not considering\n", win_errstr(r.out.result));
94                 return true;
95         }
96
97         return true;
98 }
99
100 static bool test_CreateKey(struct dcerpc_pipe *p, struct torture_context *tctx,
101                            struct policy_handle *handle, const char *name,
102                            const char *class)
103 {
104         struct winreg_CreateKey r;
105         struct policy_handle newhandle;
106         enum winreg_CreateAction action_taken = 0;
107
108         r.in.handle = handle;
109         r.out.new_handle = &newhandle;
110         init_winreg_String(&r.in.name, name);
111         init_winreg_String(&r.in.keyclass, class);
112         r.in.options = 0x0;
113         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
114         r.in.action_taken = r.out.action_taken = &action_taken;
115         r.in.secdesc = NULL;
116
117         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
118                                    "CreateKey failed");
119
120         torture_assert_werr_ok(tctx,  r.out.result, "CreateKey failed");
121
122         return true;
123 }
124
125
126 /*
127   createkey testing with a SD
128 */
129 static bool test_CreateKey_sd(struct dcerpc_pipe *p,
130                               struct torture_context *tctx,
131                               struct policy_handle *handle, const char *name,
132                               const char *class, struct policy_handle *newhandle)
133 {
134         struct winreg_CreateKey r;
135         enum winreg_CreateAction action_taken = 0;
136         struct security_descriptor *sd;
137         DATA_BLOB sdblob;
138         struct winreg_SecBuf secbuf;
139
140         sd = security_descriptor_create(tctx,
141                                         NULL, NULL,
142                                         SID_NT_AUTHENTICATED_USERS,
143                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
144                                         SEC_GENERIC_ALL,
145                                         SEC_ACE_FLAG_OBJECT_INHERIT,
146                                         NULL);
147
148         torture_assert_ntstatus_ok(tctx,
149                 ndr_push_struct_blob(&sdblob, tctx, sd,
150                                      (ndr_push_flags_fn_t)ndr_push_security_descriptor),
151                                      "Failed to push security_descriptor ?!\n");
152
153         secbuf.sd.data = sdblob.data;
154         secbuf.sd.len = sdblob.length;
155         secbuf.sd.size = sdblob.length;
156         secbuf.length = sdblob.length-10;
157         secbuf.inherit = 0;
158
159         r.in.handle = handle;
160         r.out.new_handle = newhandle;
161         init_winreg_String(&r.in.name, name);
162         init_winreg_String(&r.in.keyclass, class);
163         r.in.options = 0x0;
164         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
165         r.in.action_taken = r.out.action_taken = &action_taken;
166         r.in.secdesc = &secbuf;
167
168         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
169                                    "CreateKey with sd failed");
170
171         torture_assert_werr_ok(tctx, r.out.result, "CreateKey with sd failed");
172
173         return true;
174 }
175
176 static bool test_GetKeySecurity(struct dcerpc_pipe *p,
177                                 struct torture_context *tctx,
178                                 struct policy_handle *handle)
179 {
180         struct winreg_GetKeySecurity r;
181         struct security_descriptor sd;
182         DATA_BLOB sdblob;
183
184         ZERO_STRUCT(r);
185
186         r.in.handle = handle;
187         r.in.sd = r.out.sd = talloc_zero(tctx, struct KeySecurityData);
188         r.in.sd->size = 0x1000;
189         r.in.sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
190
191         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetKeySecurity(p, tctx, &r),
192                                    "GetKeySecurity failed");
193
194         torture_assert_werr_ok(tctx, r.out.result, "GetKeySecurity failed");
195
196         sdblob.data = r.out.sd->data;
197         sdblob.length = r.out.sd->len;
198
199         torture_assert_ntstatus_ok(tctx,
200                 ndr_pull_struct_blob(&sdblob, tctx, &sd,
201                                      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor),
202                                      "pull_security_descriptor failed");
203
204         if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
205                 NDR_PRINT_DEBUG(security_descriptor, &sd);
206         }
207
208         return true;
209 }
210
211 static bool test_CloseKey(struct dcerpc_pipe *p, struct torture_context *tctx,
212                           struct policy_handle *handle)
213 {
214         struct winreg_CloseKey r;
215
216         r.in.handle = r.out.handle = handle;
217
218         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r),
219                                    "CloseKey failed");
220
221         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
222
223         return true;
224 }
225
226 static bool test_FlushKey(struct dcerpc_pipe *p, struct torture_context *tctx,
227                           struct policy_handle *handle)
228 {
229         struct winreg_FlushKey r;
230
231         r.in.handle = handle;
232
233         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_FlushKey(p, tctx, &r),
234                                    "FlushKey failed");
235
236         torture_assert_werr_ok(tctx, r.out.result, "FlushKey failed");
237
238         return true;
239 }
240
241 static bool test_OpenKey(struct dcerpc_pipe *p, struct torture_context *tctx,
242                          struct policy_handle *hive_handle,
243                          const char *keyname, struct policy_handle *key_handle)
244 {
245         struct winreg_OpenKey r;
246
247         r.in.parent_handle = hive_handle;
248         init_winreg_String(&r.in.keyname, keyname);
249         r.in.unknown = 0x00000000;
250         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
251         r.out.handle = key_handle;
252
253         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r),
254                                    "OpenKey failed");
255
256         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
257
258         return true;
259 }
260
261 static bool test_Cleanup(struct dcerpc_pipe *p, struct torture_context *tctx,
262                          struct policy_handle *handle, const char *key)
263 {
264         struct winreg_DeleteKey r;
265
266         r.in.handle = handle;
267
268         init_winreg_String(&r.in.key, key);
269         dcerpc_winreg_DeleteKey(p, tctx, &r);
270
271         return true;
272 }
273
274
275 static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
276                            struct policy_handle *handle, const char *key)
277 {
278         NTSTATUS status;
279         struct winreg_DeleteKey r;
280
281         r.in.handle = handle;
282         init_winreg_String(&r.in.key, key);
283
284         status = dcerpc_winreg_DeleteKey(p, tctx, &r);
285
286         torture_assert_ntstatus_ok(tctx, status, "DeleteKey failed");
287         torture_assert_werr_ok(tctx, r.out.result, "DeleteKey failed");
288
289         return true;
290 }
291
292 /* DeleteKey on a key with subkey(s) should
293  * return WERR_ACCESS_DENIED. */
294 static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
295                                      struct torture_context *tctx,
296                                      struct policy_handle *handle, const char *key)
297 {
298         struct winreg_DeleteKey r;
299
300         r.in.handle = handle;
301         init_winreg_String(&r.in.key, key);
302
303         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
304                                    "DeleteKeyWithSubkey failed");
305
306         torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
307                                   "DeleteKeyWithSubkey failed");
308
309         return true;
310 }
311
312 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
313                               struct torture_context *tctx,
314                               struct policy_handle *handle, char *class)
315 {
316         struct winreg_QueryInfoKey r;
317         uint32_t num_subkeys, max_subkeylen, max_subkeysize,
318                 num_values, max_valnamelen, max_valbufsize,
319                 secdescsize;
320         NTTIME last_changed_time;
321
322         ZERO_STRUCT(r);
323         r.in.handle = handle;
324         r.out.num_subkeys = &num_subkeys;
325         r.out.max_subkeylen = &max_subkeylen;
326         r.out.max_subkeysize = &max_subkeysize;
327         r.out.num_values = &num_values;
328         r.out.max_valnamelen = &max_valnamelen;
329         r.out.max_valbufsize = &max_valbufsize;
330         r.out.secdescsize = &secdescsize;
331         r.out.last_changed_time = &last_changed_time;
332
333         r.out.classname = talloc(tctx, struct winreg_String);
334
335         r.in.classname = talloc(tctx, struct winreg_String);
336         init_winreg_String(r.in.classname, class);
337
338         torture_assert_ntstatus_ok(tctx,
339                                    dcerpc_winreg_QueryInfoKey(p, tctx, &r),
340                                    "QueryInfoKey failed");
341
342         torture_assert_werr_ok(tctx, r.out.result, "QueryInfoKey failed");
343
344         return true;
345 }
346
347 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
348                      struct policy_handle *handle, int depth);
349
350 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
351                          struct policy_handle *handle, int depth)
352 {
353         struct winreg_EnumKey r;
354         struct winreg_StringBuf class, name;
355         NTSTATUS status;
356         NTTIME t = 0;
357
358         class.name   = "";
359         class.size   = 1024;
360
361         r.in.handle = handle;
362         r.in.enum_index = 0;
363         r.in.name = &name;
364         r.in.keyclass = &class;
365         r.out.name = &name;
366         r.in.last_changed_time = &t;
367
368         do {
369                 name.name   = NULL;
370                 name.size   = 1024;
371
372                 status = dcerpc_winreg_EnumKey(p, tctx, &r);
373
374                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
375                         struct policy_handle key_handle;
376
377                         torture_comment(tctx, "EnumKey: %d: %s\n", r.in.enum_index, 
378                                         r.out.name->name);
379
380                         if (!test_OpenKey(p, tctx, handle, r.out.name->name,
381                                           &key_handle)) {
382                         } else {
383                                 test_key(p, tctx, &key_handle, depth + 1);
384                         }
385                 }
386
387                 r.in.enum_index++;
388
389         } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
390
391         torture_assert_ntstatus_ok(tctx, status, "EnumKey failed");
392
393         if (!W_ERROR_IS_OK(r.out.result) &&
394                 !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
395                 torture_fail(tctx, "EnumKey failed");
396         }
397
398         return true;
399 }
400
401 static bool test_QueryMultipleValues(struct dcerpc_pipe *p,
402                                      struct torture_context *tctx,
403                                      struct policy_handle *handle,
404                                      const char *valuename)
405 {
406         struct winreg_QueryMultipleValues r;
407         NTSTATUS status;
408         uint32_t bufsize=0;
409
410         r.in.key_handle = handle;
411         r.in.values = r.out.values = talloc_array(tctx, struct QueryMultipleValue, 1);
412         r.in.values[0].name = talloc(tctx, struct winreg_String);
413         r.in.values[0].name->name = valuename;
414         r.in.values[0].offset = 0;
415         r.in.values[0].length = 0;
416         r.in.values[0].type = 0;
417
418         r.in.num_values = 1;
419         r.in.buffer_size = r.out.buffer_size = talloc(tctx, uint32_t);
420         *r.in.buffer_size = bufsize;
421         do {
422                 *r.in.buffer_size = bufsize;
423                 r.in.buffer = r.out.buffer = talloc_zero_array(tctx, uint8_t,
424                                                                *r.in.buffer_size);
425
426                 status = dcerpc_winreg_QueryMultipleValues(p, tctx, &r);
427
428                 if(NT_STATUS_IS_ERR(status))
429                         torture_fail(tctx, "QueryMultipleValues failed");
430
431                 talloc_free(r.in.buffer);
432                 bufsize += 0x20;
433         } while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
434
435         torture_assert_werr_ok(tctx, r.out.result, "QueryMultipleValues failed");
436
437         return true;
438 }
439
440 static bool test_QueryValue(struct dcerpc_pipe *p,
441                             struct torture_context *tctx,
442                             struct policy_handle *handle,
443                             const char *valuename)
444 {
445         struct winreg_QueryValue r;
446         NTSTATUS status;
447         enum winreg_Type zero_type = 0;
448         uint32_t offered = 0xfff;
449         uint32_t zero = 0;
450
451         r.in.handle = handle;
452         r.in.data = NULL;
453         r.in.value_name.name = valuename;
454         r.in.type = &zero_type;
455         r.in.size = &offered;
456         r.in.length = &zero;
457
458         status = dcerpc_winreg_QueryValue(p, tctx, &r);
459         if (NT_STATUS_IS_ERR(status)) {
460                 torture_fail(tctx, "QueryValue failed");
461         }
462
463         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
464
465         return true;
466 }
467
468 static bool test_EnumValue(struct dcerpc_pipe *p, struct torture_context *tctx,
469                            struct policy_handle *handle, int max_valnamelen,
470                            int max_valbufsize)
471 {
472         struct winreg_EnumValue r;
473         enum winreg_Type type = 0;
474         uint32_t size = max_valbufsize, zero = 0;
475         bool ret = true;
476         uint8_t buf8;
477         struct winreg_StringBuf name;
478
479         name.name   = "";
480         name.size   = 1024;
481
482         r.in.handle = handle;
483         r.in.enum_index = 0;
484         r.in.name = &name;
485         r.out.name = &name;
486         r.in.type = &type;
487         r.in.value = &buf8;
488         r.in.length = &zero;
489         r.in.size = &size;
490
491         do {
492                 torture_assert_ntstatus_ok(tctx, 
493                                            dcerpc_winreg_EnumValue(p, tctx, &r),
494                                            "EnumValue failed");
495
496                 if (W_ERROR_IS_OK(r.out.result)) {
497                         ret &= test_QueryValue(p, tctx, handle, r.out.name->name);
498                         ret &= test_QueryMultipleValues(p, tctx, handle, r.out.name->name);
499                 }
500
501                 r.in.enum_index++;
502         } while (W_ERROR_IS_OK(r.out.result));
503
504         torture_assert_werr_equal(tctx, r.out.result, WERR_NO_MORE_ITEMS,
505                                   "EnumValue failed");
506
507         return ret;
508 }
509
510 static bool test_AbortSystemShutdown(struct dcerpc_pipe *p,
511                                      struct torture_context *tctx)
512 {
513         struct winreg_AbortSystemShutdown r;
514         uint16_t server = 0x0;
515
516         r.in.server = &server;
517
518         torture_assert_ntstatus_ok(tctx,
519                                    dcerpc_winreg_AbortSystemShutdown(p, tctx, &r),
520                                    "AbortSystemShutdown failed");
521
522         torture_assert_werr_ok(tctx, r.out.result, "AbortSystemShutdown failed");
523
524         return true;
525 }
526
527 static bool test_InitiateSystemShutdown(struct torture_context *tctx,
528                                         struct dcerpc_pipe *p)
529 {
530         struct winreg_InitiateSystemShutdown r;
531         uint16_t hostname = 0x0;
532
533         r.in.hostname = &hostname;
534         r.in.message = talloc(tctx, struct initshutdown_String);
535         init_initshutdown_String(tctx, r.in.message, "spottyfood");
536         r.in.force_apps = 1;
537         r.in.timeout = 30;
538         r.in.reboot = 1;
539
540         torture_assert_ntstatus_ok(tctx,
541                                    dcerpc_winreg_InitiateSystemShutdown(p, tctx, &r),
542                                    "InitiateSystemShutdown failed");
543
544         torture_assert_werr_ok(tctx, r.out.result, "InitiateSystemShutdown failed");
545
546         return test_AbortSystemShutdown(p, tctx);
547 }
548
549
550 static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
551                                           struct dcerpc_pipe *p)
552 {
553         struct winreg_InitiateSystemShutdownEx r;
554         uint16_t hostname = 0x0;
555
556         r.in.hostname = &hostname;
557         r.in.message = talloc(tctx, struct initshutdown_String);
558         init_initshutdown_String(tctx, r.in.message, "spottyfood");
559         r.in.force_apps = 1;
560         r.in.timeout = 30;
561         r.in.reboot = 1;
562         r.in.reason = 0;
563
564         torture_assert_ntstatus_ok(tctx,
565                 dcerpc_winreg_InitiateSystemShutdownEx(p, tctx, &r),
566                 "InitiateSystemShutdownEx failed");
567
568         torture_assert_werr_ok(tctx, r.out.result,
569                                "InitiateSystemShutdownEx failed");
570
571         return test_AbortSystemShutdown(p, tctx);
572 }
573 #define MAX_DEPTH 2             /* Only go this far down the tree */
574
575 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
576                      struct policy_handle *handle, int depth)
577 {
578         if (depth == MAX_DEPTH)
579                 return true;
580
581         if (!test_QueryInfoKey(p, tctx, handle, NULL)) {
582         }
583
584         if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
585         }
586
587         if (!test_GetKeySecurity(p, tctx, handle)) {
588         }
589
590         if (!test_EnumKey(p, tctx, handle, depth)) {
591         }
592
593         if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
594         }
595
596         test_CloseKey(p, tctx, handle);
597
598         return true;
599 }
600
601 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
602
603 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
604                       void *userdata)
605 {
606         struct policy_handle handle, newhandle;
607         bool ret = true, created = false, created2 = false, deleted = false;
608         bool created3 = false, created_subkey = false;
609         struct winreg_OpenHKLM r;
610
611         winreg_open_fn open_fn = userdata;
612
613         r.in.system_name = 0;
614         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
615         r.out.handle = &handle;
616
617         torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
618                                    "open");
619
620         test_Cleanup(p, tctx, &handle, TEST_KEY1);
621         test_Cleanup(p, tctx, &handle, TEST_KEY2);
622         test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
623         test_Cleanup(p, tctx, &handle, TEST_KEY3);
624         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
625
626         if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
627                 torture_comment(tctx, "CreateKey failed - not considering a failure\n");
628         } else {
629                 created = true;
630         }
631
632         if (created && !test_FlushKey(p, tctx, &handle)) {
633                 torture_comment(tctx, "FlushKey failed\n");
634                 ret = false;
635         }
636
637         if (created && !test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle))
638                 torture_fail(tctx,
639                              "CreateKey failed (OpenKey after Create didn't work)\n");
640
641         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY1)) {
642                 torture_comment(tctx, "DeleteKey failed\n");
643                 ret = false;
644         } else {
645                 deleted = true;
646         }
647
648         if (created && !test_FlushKey(p, tctx, &handle)) {
649                 torture_comment(tctx, "FlushKey failed\n");
650                 ret = false;
651         }
652
653         if (created && deleted &&
654             test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
655                 torture_comment(tctx,
656                                 "DeleteKey failed (OpenKey after Delete worked)\n");
657                 ret = false;
658         }
659
660         if (!test_GetVersion(p, tctx, &handle)) {
661                 torture_comment(tctx, "GetVersion failed\n");
662                 ret = false;
663         }
664
665         if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
666                                          NULL, &newhandle)) {
667                 created2 = true;
668         }
669
670         if (created2 && !test_GetKeySecurity(p, tctx, &newhandle)) {
671                 printf("GetKeySecurity failed\n");
672                 ret = false;
673         }
674
675         if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
676                 printf("CloseKey failed\n");
677                 ret = false;
678         }
679
680         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
681                 printf("DeleteKey failed\n");
682                 ret = false;
683         }
684
685         if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
686                 created3 = true;
687         }
688
689         if (created3 &&
690             test_CreateKey(p, tctx, &handle, TEST_SUBKEY, NULL))
691         {
692                 created_subkey = true;
693         }
694
695         if (created_subkey &&
696             !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3))
697         {
698                 printf("DeleteKeyWithSubkey failed "
699                        "(DeleteKey didn't return ACCESS_DENIED)\n");
700                 ret = false;
701         }
702
703         if (created_subkey &&
704             !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY))
705         {
706                 printf("DeleteKey failed\n");
707                 ret = false;
708         }
709
710         if (created3 &&
711             !test_DeleteKey(p, tctx, &handle, TEST_KEY3))
712         {
713                 printf("DeleteKey failed\n");
714                 ret = false;
715         }
716
717         /* The HKCR hive has a very large fanout */
718         if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
719                 if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
720                         ret = false;
721                 }
722         }
723
724         if(!test_key(p, tctx, &handle, 0)) {
725                 ret = false;
726         }
727
728         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
729
730         return ret;
731 }
732
733 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
734 {
735         struct {
736                 const char *name;
737                 winreg_open_fn fn;
738         } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
739                         {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
740                         {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
741                         {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
742         int i;
743         struct torture_rpc_tcase *tcase;
744         struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
745         struct torture_test *test;
746
747         tcase = torture_suite_add_rpc_iface_tcase(suite, "winreg",
748                                                   &ndr_table_winreg);
749
750         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdown",
751                                           test_InitiateSystemShutdown);
752         test->dangerous = true;
753
754         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdownEx",
755                                           test_InitiateSystemShutdownEx);
756         test->dangerous = true;
757
758         for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
759                 torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name,
760                                               test_Open, open_fns[i].fn);
761         }
762
763         return suite;
764 }