subunit: Support formatting compatible with upstream subunit, for consistency.
[sfrench/samba-autobuild/.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35
36 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
37 #define TORTURE_PRINTER                 "torture_printer"
38 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
39 #define TORTURE_PRINTER_EX              "torture_printer_ex"
40
41 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
42 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
43 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
44 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
45 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
46
47 struct test_spoolss_context {
48         /* print server handle */
49         struct policy_handle server_handle;
50
51         /* for EnumPorts */
52         uint32_t port_count[3];
53         union spoolss_PortInfo *ports[3];
54
55         /* for EnumPrinterDrivers */
56         uint32_t driver_count[8];
57         union spoolss_DriverInfo *drivers[8];
58
59         /* for EnumMonitors */
60         uint32_t monitor_count[3];
61         union spoolss_MonitorInfo *monitors[3];
62
63         /* for EnumPrintProcessors */
64         uint32_t print_processor_count[2];
65         union spoolss_PrintProcessorInfo *print_processors[2];
66
67         /* for EnumPrinters */
68         uint32_t printer_count[6];
69         union spoolss_PrinterInfo *printers[6];
70 };
71
72 #define COMPARE_STRING(tctx, c,r,e) \
73         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
74
75 /* not every compiler supports __typeof__() */
76 #if (__GNUC__ >= 3)
77 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
78         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
79                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
80         }\
81         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
82                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
83         }\
84 } while(0)
85 #else
86 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
87 #endif
88
89 #define COMPARE_UINT32(tctx, c, r, e) do {\
90         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
91         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
92 } while(0)
93
94 #define COMPARE_UINT64(tctx, c, r, e) do {\
95         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
96         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
97 } while(0)
98
99
100 #define COMPARE_NTTIME(tctx, c, r, e) do {\
101         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
102         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
103 } while(0)
104
105 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
106         int __i; \
107         if (!c.e && !r.e) { \
108                 break; \
109         } \
110         if (c.e && !r.e) { \
111                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
112         } \
113         if (!c.e && r.e) { \
114                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
115         } \
116         for (__i=0;c.e[__i] != NULL; __i++) { \
117                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
118         } \
119 } while(0)
120
121 #define CHECK_ALIGN(size, n) do {\
122         if (size % n) {\
123                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
124                         size, n, size + n - (size % n));\
125         }\
126 } while(0)
127
128 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
129
130 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
131         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
132         uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
133         uint32_t round_size = DO_ROUND(size, align);\
134         if (round_size != needed) {\
135                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
136                 CHECK_ALIGN(size, align);\
137         }\
138         }\
139 } while(0)
140
141 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
142         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
143         uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
144         uint32_t round_size = DO_ROUND(size, align);\
145         if (round_size != needed) {\
146                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
147                 CHECK_ALIGN(size, align);\
148         }\
149         }\
150 } while(0)
151
152 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
153         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
154         uint32_t size = ndr_size_##fn(info, level, ic, 0);\
155         uint32_t round_size = DO_ROUND(size, align);\
156         if (round_size != needed) {\
157                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
158                 CHECK_ALIGN(size, align);\
159         }\
160         }\
161 } while(0)
162
163 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
164                                           const union spoolss_PrinterInfo *i,
165                                           uint32_t level,
166                                           union spoolss_SetPrinterInfo *s)
167 {
168         switch (level) {
169         case 0:
170                 s->info0                        = talloc(tctx, struct spoolss_SetPrinterInfo0);
171                 break;
172         case 2:
173                 s->info2                        = talloc(tctx, struct spoolss_SetPrinterInfo2);
174                 s->info2->servername            = i->info2.servername;
175                 s->info2->printername           = i->info2.printername;
176                 s->info2->sharename             = i->info2.sharename;
177                 s->info2->portname              = i->info2.portname;
178                 s->info2->drivername            = i->info2.drivername;
179                 s->info2->comment               = i->info2.comment;
180                 s->info2->location              = i->info2.location;
181                 s->info2->devmode_ptr           = 0;
182                 s->info2->sepfile               = i->info2.sepfile;
183                 s->info2->printprocessor        = i->info2.printprocessor;
184                 s->info2->datatype              = i->info2.datatype;
185                 s->info2->parameters            = i->info2.parameters;
186                 s->info2->secdesc_ptr           = 0;
187                 s->info2->attributes            = i->info2.attributes;
188                 s->info2->priority              = i->info2.priority;
189                 s->info2->defaultpriority       = i->info2.defaultpriority;
190                 s->info2->starttime             = i->info2.starttime;
191                 s->info2->untiltime             = i->info2.untiltime;
192                 s->info2->status                = i->info2.status;
193                 s->info2->cjobs                 = i->info2.cjobs;
194                 s->info2->averageppm            = i->info2.averageppm;
195                 break;
196         case 3:
197         case 4:
198         case 5:
199         case 6:
200         case 7:
201         case 8:
202         case 9:
203         default:
204                 return false;
205         }
206
207         return true;
208 }
209
210 static bool test_OpenPrinter_server(struct torture_context *tctx,
211                                     struct dcerpc_pipe *p,
212                                     struct policy_handle *server_handle)
213 {
214         NTSTATUS status;
215         struct spoolss_OpenPrinter op;
216         struct dcerpc_binding_handle *b = p->binding_handle;
217
218         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
219         op.in.datatype          = NULL;
220         op.in.devmode_ctr.devmode= NULL;
221         op.in.access_mask       = 0;
222         op.out.handle           = server_handle;
223
224         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
225
226         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
227         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
228         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
229
230         return true;
231 }
232
233 static bool test_EnumPorts(struct torture_context *tctx,
234                            struct dcerpc_binding_handle *b,
235                            struct test_spoolss_context *ctx)
236 {
237         NTSTATUS status;
238         struct spoolss_EnumPorts r;
239         uint16_t levels[] = { 1, 2 };
240         int i, j;
241
242         for (i=0;i<ARRAY_SIZE(levels);i++) {
243                 int level = levels[i];
244                 DATA_BLOB blob;
245                 uint32_t needed;
246                 uint32_t count;
247                 union spoolss_PortInfo *info;
248
249                 r.in.servername = "";
250                 r.in.level = level;
251                 r.in.buffer = NULL;
252                 r.in.offered = 0;
253                 r.out.needed = &needed;
254                 r.out.count = &count;
255                 r.out.info = &info;
256
257                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
258
259                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
260                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
261                 if (W_ERROR_IS_OK(r.out.result)) {
262                         /* TODO: do some more checks here */
263                         continue;
264                 }
265                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
266                         "EnumPorts unexpected return code");
267
268                 blob = data_blob_talloc_zero(ctx, needed);
269                 r.in.buffer = &blob;
270                 r.in.offered = needed;
271
272                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
273                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
274
275                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
276
277                 torture_assert(tctx, info, "EnumPorts returned no info");
278
279                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
280
281                 ctx->port_count[level]  = count;
282                 ctx->ports[level]       = info;
283         }
284
285         for (i=1;i<ARRAY_SIZE(levels);i++) {
286                 int level = levels[i];
287                 int old_level = levels[i-1];
288                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
289                         "EnumPorts invalid value");
290         }
291         /* if the array sizes are not the same we would maybe segfault in the following code */
292
293         for (i=0;i<ARRAY_SIZE(levels);i++) {
294                 int level = levels[i];
295                 for (j=0;j<ctx->port_count[level];j++) {
296                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
297                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
298                         switch (level) {
299                         case 1:
300                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
301                                 break;
302                         case 2:
303                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
304                                 break;
305                         }
306                 }
307         }
308
309         return true;
310 }
311
312 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
313                                             struct dcerpc_pipe *p,
314                                             const char *environment)
315 {
316         NTSTATUS status;
317         struct dcerpc_binding_handle *b = p->binding_handle;
318         struct spoolss_GetPrintProcessorDirectory r;
319         struct {
320                 uint16_t level;
321                 const char *server;
322         } levels[] = {{
323                         .level  = 1,
324                         .server = NULL
325                 },{
326                         .level  = 1,
327                         .server = ""
328                 },{
329                         .level  = 78,
330                         .server = ""
331                 },{
332                         .level  = 1,
333                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
334                 },{
335                         .level  = 1024,
336                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
337                 }
338         };
339         int i;
340         uint32_t needed;
341
342         for (i=0;i<ARRAY_SIZE(levels);i++) {
343                 int level = levels[i].level;
344                 DATA_BLOB blob;
345
346                 r.in.server             = levels[i].server;
347                 r.in.environment        = environment;
348                 r.in.level              = level;
349                 r.in.buffer             = NULL;
350                 r.in.offered            = 0;
351                 r.out.needed            = &needed;
352
353                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
354
355                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
356                 torture_assert_ntstatus_ok(tctx, status,
357                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
358                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
359                         "GetPrintProcessorDirectory unexpected return code");
360
361                 blob = data_blob_talloc_zero(tctx, needed);
362                 r.in.buffer = &blob;
363                 r.in.offered = needed;
364
365                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
366                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
367
368                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
369
370                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
371         }
372
373         return true;
374 }
375
376
377 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
378                                            struct dcerpc_pipe *p,
379                                            const char *environment)
380 {
381         NTSTATUS status;
382         struct dcerpc_binding_handle *b = p->binding_handle;
383         struct spoolss_GetPrinterDriverDirectory r;
384         struct {
385                 uint16_t level;
386                 const char *server;
387         } levels[] = {{
388                         .level  = 1,
389                         .server = NULL
390                 },{
391                         .level  = 1,
392                         .server = ""
393                 },{
394                         .level  = 78,
395                         .server = ""
396                 },{
397                         .level  = 1,
398                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
399                 },{
400                         .level  = 1024,
401                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
402                 }
403         };
404         int i;
405         uint32_t needed;
406
407         for (i=0;i<ARRAY_SIZE(levels);i++) {
408                 int level = levels[i].level;
409                 DATA_BLOB blob;
410
411                 r.in.server             = levels[i].server;
412                 r.in.environment        = environment;
413                 r.in.level              = level;
414                 r.in.buffer             = NULL;
415                 r.in.offered            = 0;
416                 r.out.needed            = &needed;
417
418                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
419
420                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
421                 torture_assert_ntstatus_ok(tctx, status,
422                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
423                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
424                         "GetPrinterDriverDirectory unexpected return code");
425
426                 blob = data_blob_talloc_zero(tctx, needed);
427                 r.in.buffer = &blob;
428                 r.in.offered = needed;
429
430                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
431                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
432
433                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
434
435                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
436         }
437
438         return true;
439 }
440
441 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
442                                     struct dcerpc_pipe *p,
443                                     struct test_spoolss_context *ctx,
444                                     const char *architecture)
445 {
446         NTSTATUS status;
447         struct dcerpc_binding_handle *b = p->binding_handle;
448         struct spoolss_EnumPrinterDrivers r;
449         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
450         int i, j;
451
452         for (i=0;i<ARRAY_SIZE(levels);i++) {
453                 int level = levels[i];
454                 DATA_BLOB blob;
455                 uint32_t needed;
456                 uint32_t count;
457                 union spoolss_DriverInfo *info;
458
459                 /* FIXME: gd, come back and fix "" as server, and handle
460                  * priority of returned error codes in torture test and samba 3
461                  * server */
462
463                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
464                 r.in.environment        = architecture;
465                 r.in.level              = level;
466                 r.in.buffer             = NULL;
467                 r.in.offered            = 0;
468                 r.out.needed            = &needed;
469                 r.out.count             = &count;
470                 r.out.info              = &info;
471
472                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
473
474                 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
475                 torture_assert_ntstatus_ok(tctx, status,
476                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
477                 if (W_ERROR_IS_OK(r.out.result)) {
478                         /* TODO: do some more checks here */
479                         continue;
480                 }
481                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
482                         blob = data_blob_talloc_zero(ctx, needed);
483                         r.in.buffer = &blob;
484                         r.in.offered = needed;
485
486                         status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
487                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
488                 }
489
490                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
491
492                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
493
494                 ctx->driver_count[level]        = count;
495                 ctx->drivers[level]             = info;
496         }
497
498         for (i=1;i<ARRAY_SIZE(levels);i++) {
499                 int level = levels[i];
500                 int old_level = levels[i-1];
501
502                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
503                         "EnumPrinterDrivers invalid value");
504         }
505
506         for (i=0;i<ARRAY_SIZE(levels);i++) {
507                 int level = levels[i];
508
509                 for (j=0;j<ctx->driver_count[level];j++) {
510                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
511                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
512
513                         switch (level) {
514                         case 1:
515                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
516                                 break;
517                         case 2:
518                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
519                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
520                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
521                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
522                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
523                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
524                                 break;
525                         case 3:
526                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
527                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
528                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
529                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
530                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
531                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
532                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
533                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
534                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
535                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
536                                 break;
537                         case 4:
538                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
539                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
540                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
541                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
542                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
543                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
544                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
545                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
546                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
547                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
548                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
549                                 break;
550                         case 5:
551                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
552                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
553                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
554                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
555                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
556                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
557                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
558                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
559                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
560                                 break;
561                         case 6:
562                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
563                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
564                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
565                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
566                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
567                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
568                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
569                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
570                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
571                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
572                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
573                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
574                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
575                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
576                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
577                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
578                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
579                                 break;
580                         case 8:
581                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
582                                 break;
583                         }
584                 }
585         }
586
587         return true;
588 }
589
590 static bool test_EnumMonitors(struct torture_context *tctx,
591                               struct dcerpc_binding_handle *b,
592                               struct test_spoolss_context *ctx)
593 {
594         NTSTATUS status;
595         struct spoolss_EnumMonitors r;
596         uint16_t levels[] = { 1, 2 };
597         int i, j;
598
599         for (i=0;i<ARRAY_SIZE(levels);i++) {
600                 int level = levels[i];
601                 DATA_BLOB blob;
602                 uint32_t needed;
603                 uint32_t count;
604                 union spoolss_MonitorInfo *info;
605
606                 r.in.servername = "";
607                 r.in.level = level;
608                 r.in.buffer = NULL;
609                 r.in.offered = 0;
610                 r.out.needed = &needed;
611                 r.out.count = &count;
612                 r.out.info = &info;
613
614                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
615
616                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
617                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
618                 if (W_ERROR_IS_OK(r.out.result)) {
619                         /* TODO: do some more checks here */
620                         continue;
621                 }
622                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
623                         "EnumMonitors failed");
624
625                 blob = data_blob_talloc_zero(ctx, needed);
626                 r.in.buffer = &blob;
627                 r.in.offered = needed;
628
629                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
630                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
631
632                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
633
634                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
635
636                 ctx->monitor_count[level]       = count;
637                 ctx->monitors[level]            = info;
638         }
639
640         for (i=1;i<ARRAY_SIZE(levels);i++) {
641                 int level = levels[i];
642                 int old_level = levels[i-1];
643                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
644                                          "EnumMonitors invalid value");
645         }
646
647         for (i=0;i<ARRAY_SIZE(levels);i++) {
648                 int level = levels[i];
649                 for (j=0;j<ctx->monitor_count[level];j++) {
650                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
651                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
652                         switch (level) {
653                         case 1:
654                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
655                                 break;
656                         case 2:
657                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
658                                 break;
659                         }
660                 }
661         }
662
663         return true;
664 }
665
666 static bool test_EnumPrintProcessors(struct torture_context *tctx,
667                                      struct dcerpc_binding_handle *b,
668                                      struct test_spoolss_context *ctx,
669                                      const char *environment)
670 {
671         NTSTATUS status;
672         struct spoolss_EnumPrintProcessors r;
673         uint16_t levels[] = { 1 };
674         int i, j;
675
676         for (i=0;i<ARRAY_SIZE(levels);i++) {
677                 int level = levels[i];
678                 DATA_BLOB blob;
679                 uint32_t needed;
680                 uint32_t count;
681                 union spoolss_PrintProcessorInfo *info;
682
683                 r.in.servername = "";
684                 r.in.environment = environment;
685                 r.in.level = level;
686                 r.in.buffer = NULL;
687                 r.in.offered = 0;
688                 r.out.needed = &needed;
689                 r.out.count = &count;
690                 r.out.info = &info;
691
692                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
693
694                 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
695                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
696                 if (W_ERROR_IS_OK(r.out.result)) {
697                         /* TODO: do some more checks here */
698                         continue;
699                 }
700                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
701                         "EnumPrintProcessors unexpected return code");
702
703                 blob = data_blob_talloc_zero(ctx, needed);
704                 r.in.buffer = &blob;
705                 r.in.offered = needed;
706
707                 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
708                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
709
710                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
711
712                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
713
714                 ctx->print_processor_count[level]       = count;
715                 ctx->print_processors[level]            = info;
716         }
717
718         for (i=1;i<ARRAY_SIZE(levels);i++) {
719                 int level = levels[i];
720                 int old_level = levels[i-1];
721                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
722                         "EnumPrintProcessors failed");
723         }
724
725         for (i=0;i<ARRAY_SIZE(levels);i++) {
726                 int level = levels[i];
727                 for (j=0;j<ctx->print_processor_count[level];j++) {
728 #if 0
729                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
730                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
731 #endif
732                         switch (level) {
733                         case 1:
734                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
735                                 break;
736                         }
737                 }
738         }
739
740         return true;
741 }
742
743 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
744                                         struct dcerpc_binding_handle *b)
745 {
746         NTSTATUS status;
747         struct spoolss_EnumPrintProcDataTypes r;
748         uint16_t levels[] = { 1 };
749         int i;
750
751         for (i=0;i<ARRAY_SIZE(levels);i++) {
752                 int level = levels[i];
753                 DATA_BLOB blob;
754                 uint32_t needed;
755                 uint32_t count;
756                 union spoolss_PrintProcDataTypesInfo *info;
757
758                 r.in.servername = "";
759                 r.in.print_processor_name = "winprint";
760                 r.in.level = level;
761                 r.in.buffer = NULL;
762                 r.in.offered = 0;
763                 r.out.needed = &needed;
764                 r.out.count = &count;
765                 r.out.info = &info;
766
767                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
768
769                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
770                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
771                 if (W_ERROR_IS_OK(r.out.result)) {
772                         /* TODO: do some more checks here */
773                         continue;
774                 }
775                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
776                         "EnumPrintProcDataTypes unexpected return code");
777
778                 blob = data_blob_talloc_zero(tctx, needed);
779                 r.in.buffer = &blob;
780                 r.in.offered = needed;
781
782                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
783                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
784
785                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
786
787                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
788
789         }
790
791         return true;
792 }
793
794
795 static bool test_EnumPrinters(struct torture_context *tctx,
796                               struct dcerpc_binding_handle *b,
797                               struct test_spoolss_context *ctx)
798 {
799         struct spoolss_EnumPrinters r;
800         NTSTATUS status;
801         uint16_t levels[] = { 0, 1, 2, 4, 5 };
802         int i, j;
803
804         for (i=0;i<ARRAY_SIZE(levels);i++) {
805                 int level = levels[i];
806                 DATA_BLOB blob;
807                 uint32_t needed;
808                 uint32_t count;
809                 union spoolss_PrinterInfo *info;
810
811                 r.in.flags      = PRINTER_ENUM_LOCAL;
812                 r.in.server     = "";
813                 r.in.level      = level;
814                 r.in.buffer     = NULL;
815                 r.in.offered    = 0;
816                 r.out.needed    = &needed;
817                 r.out.count     = &count;
818                 r.out.info      = &info;
819
820                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
821
822                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
823                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
824                 if (W_ERROR_IS_OK(r.out.result)) {
825                         /* TODO: do some more checks here */
826                         continue;
827                 }
828                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
829                         "EnumPrinters unexpected return code");
830
831                 blob = data_blob_talloc_zero(ctx, needed);
832                 r.in.buffer = &blob;
833                 r.in.offered = needed;
834
835                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
836                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
837
838                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
839
840                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
841
842                 ctx->printer_count[level]       = count;
843                 ctx->printers[level]            = info;
844         }
845
846         for (i=1;i<ARRAY_SIZE(levels);i++) {
847                 int level = levels[i];
848                 int old_level = levels[i-1];
849                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
850                                          "EnumPrinters invalid value");
851         }
852
853         for (i=0;i<ARRAY_SIZE(levels);i++) {
854                 int level = levels[i];
855                 for (j=0;j<ctx->printer_count[level];j++) {
856                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
857                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
858                         switch (level) {
859                         case 0:
860                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
861                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
862                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
863                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
864                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
865                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
866                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
867                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
868                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
869                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
870                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
871                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
872                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
873                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
874                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
875                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
876                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
877                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
878                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
879                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
880                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
881                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
882                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
883                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
884                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
885                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
886                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
887                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
888                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
889                                 break;
890                         case 1:
891                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
892                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
893                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
894                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
895                                 break;
896                         case 2:
897                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
898                                 break;
899                         case 4:
900                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
901                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
902                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
903                                 break;
904                         case 5:
905                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
906                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
907                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
908                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
909                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
910                                 break;
911                         }
912                 }
913         }
914
915         /* TODO:
916          *      - verify that the port of a printer was in the list returned by EnumPorts
917          */
918
919         return true;
920 }
921
922 static bool test_GetPrinterDriver2(struct torture_context *tctx,
923                                    struct dcerpc_binding_handle *b,
924                                    struct policy_handle *handle,
925                                    const char *driver_name,
926                                    const char *environment);
927
928 bool test_GetPrinter_level(struct torture_context *tctx,
929                            struct dcerpc_binding_handle *b,
930                            struct policy_handle *handle,
931                            uint32_t level,
932                            union spoolss_PrinterInfo *info)
933 {
934         struct spoolss_GetPrinter r;
935         uint32_t needed;
936
937         r.in.handle = handle;
938         r.in.level = level;
939         r.in.buffer = NULL;
940         r.in.offered = 0;
941         r.out.needed = &needed;
942
943         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
944
945         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
946                 "GetPrinter failed");
947
948         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
949                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
950                 r.in.buffer = &blob;
951                 r.in.offered = needed;
952
953                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
954                         "GetPrinter failed");
955         }
956
957         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
958
959         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
960
961         if (info && r.out.info) {
962                 *info = *r.out.info;
963         }
964
965         return true;
966 }
967
968
969 static bool test_GetPrinter(struct torture_context *tctx,
970                             struct dcerpc_binding_handle *b,
971                             struct policy_handle *handle,
972                             const char *environment)
973 {
974         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
975         int i;
976
977         for (i=0;i<ARRAY_SIZE(levels);i++) {
978
979                 union spoolss_PrinterInfo info;
980
981                 ZERO_STRUCT(info);
982
983                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
984                         "failed to call GetPrinter");
985
986                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
987                         torture_assert(tctx,
988                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
989                                 "failed to call test_GetPrinterDriver2");
990                 }
991         }
992
993         return true;
994 }
995
996 static bool test_SetPrinter(struct torture_context *tctx,
997                             struct dcerpc_binding_handle *b,
998                             struct policy_handle *handle,
999                             struct spoolss_SetPrinterInfoCtr *info_ctr,
1000                             struct spoolss_DevmodeContainer *devmode_ctr,
1001                             struct sec_desc_buf *secdesc_ctr,
1002                             enum spoolss_PrinterControl command)
1003 {
1004         struct spoolss_SetPrinter r;
1005
1006         r.in.handle = handle;
1007         r.in.info_ctr = info_ctr;
1008         r.in.devmode_ctr = devmode_ctr;
1009         r.in.secdesc_ctr = secdesc_ctr;
1010         r.in.command = command;
1011
1012         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1013
1014         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1015                 "failed to call SetPrinter");
1016         torture_assert_werr_ok(tctx, r.out.result,
1017                 "failed to call SetPrinter");
1018
1019         return true;
1020 }
1021
1022 static bool test_SetPrinter_errors(struct torture_context *tctx,
1023                                    struct dcerpc_binding_handle *b,
1024                                    struct policy_handle *handle)
1025 {
1026         struct spoolss_SetPrinter r;
1027         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1028         int i;
1029
1030         struct spoolss_SetPrinterInfoCtr info_ctr;
1031         struct spoolss_DevmodeContainer devmode_ctr;
1032         struct sec_desc_buf secdesc_ctr;
1033
1034         info_ctr.level = 0;
1035         info_ctr.info.info0 = NULL;
1036
1037         ZERO_STRUCT(devmode_ctr);
1038         ZERO_STRUCT(secdesc_ctr);
1039
1040         r.in.handle = handle;
1041         r.in.info_ctr = &info_ctr;
1042         r.in.devmode_ctr = &devmode_ctr;
1043         r.in.secdesc_ctr = &secdesc_ctr;
1044         r.in.command = 0;
1045
1046         torture_comment(tctx, "Testing SetPrinter all zero\n");
1047
1048         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1049                 "failed to call SetPrinter");
1050         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1051                 "failed to call SetPrinter");
1052
1053  again:
1054         for (i=0; i < ARRAY_SIZE(levels); i++) {
1055
1056                 struct spoolss_SetPrinterInfo0 info0;
1057                 struct spoolss_SetPrinterInfo1 info1;
1058                 struct spoolss_SetPrinterInfo2 info2;
1059                 struct spoolss_SetPrinterInfo3 info3;
1060                 struct spoolss_SetPrinterInfo4 info4;
1061                 struct spoolss_SetPrinterInfo5 info5;
1062                 struct spoolss_SetPrinterInfo6 info6;
1063                 struct spoolss_SetPrinterInfo7 info7;
1064                 struct spoolss_SetPrinterInfo8 info8;
1065                 struct spoolss_SetPrinterInfo9 info9;
1066
1067
1068                 info_ctr.level = levels[i];
1069                 switch (levels[i]) {
1070                 case 0:
1071                         ZERO_STRUCT(info0);
1072                         info_ctr.info.info0 = &info0;
1073                         break;
1074                 case 1:
1075                         ZERO_STRUCT(info1);
1076                         info_ctr.info.info1 = &info1;
1077                         break;
1078                 case 2:
1079                         ZERO_STRUCT(info2);
1080                         info_ctr.info.info2 = &info2;
1081                         break;
1082                 case 3:
1083                         ZERO_STRUCT(info3);
1084                         info_ctr.info.info3 = &info3;
1085                         break;
1086                 case 4:
1087                         ZERO_STRUCT(info4);
1088                         info_ctr.info.info4 = &info4;
1089                         break;
1090                 case 5:
1091                         ZERO_STRUCT(info5);
1092                         info_ctr.info.info5 = &info5;
1093                         break;
1094                 case 6:
1095                         ZERO_STRUCT(info6);
1096                         info_ctr.info.info6 = &info6;
1097                         break;
1098                 case 7:
1099                         ZERO_STRUCT(info7);
1100                         info_ctr.info.info7 = &info7;
1101                         break;
1102                 case 8:
1103                         ZERO_STRUCT(info8);
1104                         info_ctr.info.info8 = &info8;
1105                         break;
1106                 case 9:
1107                         ZERO_STRUCT(info9);
1108                         info_ctr.info.info9 = &info9;
1109                         break;
1110                 }
1111
1112                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1113                         info_ctr.level, r.in.command);
1114
1115                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1116                         "failed to call SetPrinter");
1117
1118                 switch (r.in.command) {
1119                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1120                         /* is ignored for all levels other then 0 */
1121                         if (info_ctr.level > 0) {
1122                                 /* ignored then */
1123                                 break;
1124                         }
1125                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1126                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1127                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1128                         if (info_ctr.level > 0) {
1129                                 /* is invalid for all levels other then 0 */
1130                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1131                                         "unexpected error code returned");
1132                                 continue;
1133                         } else {
1134                                 torture_assert_werr_ok(tctx, r.out.result,
1135                                         "failed to call SetPrinter with non 0 command");
1136                                 continue;
1137                         }
1138                         break;
1139
1140                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1141                         /* FIXME: gd needs further investigation */
1142                 default:
1143                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1144                                 "unexpected error code returned");
1145                         continue;
1146                 }
1147
1148                 switch (info_ctr.level) {
1149                 case 1:
1150                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1151                                 "unexpected error code returned");
1152                         break;
1153                 case 2:
1154                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1155                                 "unexpected error code returned");
1156                         break;
1157                 case 3:
1158                 case 4:
1159                 case 5:
1160                 case 7:
1161                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1162                                 "unexpected error code returned");
1163                         break;
1164                 case 9:
1165                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1166                                 "unexpected error code returned");
1167                         break;
1168                 default:
1169                         torture_assert_werr_ok(tctx, r.out.result,
1170                                 "failed to call SetPrinter");
1171                         break;
1172                 }
1173         }
1174
1175         if (r.in.command < 5) {
1176                 r.in.command++;
1177                 goto again;
1178         }
1179
1180         return true;
1181 }
1182
1183 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1184 {
1185         if ((r->level == 2) && (r->info.info2)) {
1186                 r->info.info2->secdesc_ptr = 0;
1187                 r->info.info2->devmode_ptr = 0;
1188         }
1189 }
1190
1191 static bool test_PrinterInfo(struct torture_context *tctx,
1192                              struct dcerpc_binding_handle *b,
1193                              struct policy_handle *handle)
1194 {
1195         NTSTATUS status;
1196         struct spoolss_SetPrinter s;
1197         struct spoolss_GetPrinter q;
1198         struct spoolss_GetPrinter q0;
1199         struct spoolss_SetPrinterInfoCtr info_ctr;
1200         union spoolss_PrinterInfo info;
1201         struct spoolss_DevmodeContainer devmode_ctr;
1202         struct sec_desc_buf secdesc_ctr;
1203         uint32_t needed;
1204         bool ret = true;
1205         int i;
1206
1207         uint32_t status_list[] = {
1208                 /* these do not stick
1209                 PRINTER_STATUS_PAUSED,
1210                 PRINTER_STATUS_ERROR,
1211                 PRINTER_STATUS_PENDING_DELETION, */
1212                 PRINTER_STATUS_PAPER_JAM,
1213                 PRINTER_STATUS_PAPER_OUT,
1214                 PRINTER_STATUS_MANUAL_FEED,
1215                 PRINTER_STATUS_PAPER_PROBLEM,
1216                 PRINTER_STATUS_OFFLINE,
1217                 PRINTER_STATUS_IO_ACTIVE,
1218                 PRINTER_STATUS_BUSY,
1219                 PRINTER_STATUS_PRINTING,
1220                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1221                 PRINTER_STATUS_NOT_AVAILABLE,
1222                 PRINTER_STATUS_WAITING,
1223                 PRINTER_STATUS_PROCESSING,
1224                 PRINTER_STATUS_INITIALIZING,
1225                 PRINTER_STATUS_WARMING_UP,
1226                 PRINTER_STATUS_TONER_LOW,
1227                 PRINTER_STATUS_NO_TONER,
1228                 PRINTER_STATUS_PAGE_PUNT,
1229                 PRINTER_STATUS_USER_INTERVENTION,
1230                 PRINTER_STATUS_OUT_OF_MEMORY,
1231                 PRINTER_STATUS_DOOR_OPEN,
1232                 PRINTER_STATUS_SERVER_UNKNOWN,
1233                 PRINTER_STATUS_POWER_SAVE,
1234                 /* these do not stick
1235                 0x02000000,
1236                 0x04000000,
1237                 0x08000000,
1238                 0x10000000,
1239                 0x20000000,
1240                 0x40000000,
1241                 0x80000000 */
1242         };
1243         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1244         uint32_t attribute_list[] = {
1245                 PRINTER_ATTRIBUTE_QUEUED,
1246                 /* fails with WERR_INVALID_DATATYPE:
1247                 PRINTER_ATTRIBUTE_DIRECT, */
1248                 /* does not stick
1249                 PRINTER_ATTRIBUTE_DEFAULT, */
1250                 PRINTER_ATTRIBUTE_SHARED,
1251                 /* does not stick
1252                 PRINTER_ATTRIBUTE_NETWORK, */
1253                 PRINTER_ATTRIBUTE_HIDDEN,
1254                 PRINTER_ATTRIBUTE_LOCAL,
1255                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1256                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1257                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1258                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1259                 /* does not stick
1260                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1261                 /* fails with WERR_INVALID_DATATYPE:
1262                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1263                 /* these do not stick
1264                 PRINTER_ATTRIBUTE_PUBLISHED,
1265                 PRINTER_ATTRIBUTE_FAX,
1266                 PRINTER_ATTRIBUTE_TS,
1267                 0x00010000,
1268                 0x00020000,
1269                 0x00040000,
1270                 0x00080000,
1271                 0x00100000,
1272                 0x00200000,
1273                 0x00400000,
1274                 0x00800000,
1275                 0x01000000,
1276                 0x02000000,
1277                 0x04000000,
1278                 0x08000000,
1279                 0x10000000,
1280                 0x20000000,
1281                 0x40000000,
1282                 0x80000000 */
1283         };
1284
1285         ZERO_STRUCT(devmode_ctr);
1286         ZERO_STRUCT(secdesc_ctr);
1287
1288         s.in.handle = handle;
1289         s.in.command = 0;
1290         s.in.info_ctr = &info_ctr;
1291         s.in.devmode_ctr = &devmode_ctr;
1292         s.in.secdesc_ctr = &secdesc_ctr;
1293
1294         q.in.handle = handle;
1295         q.out.info = &info;
1296         q0 = q;
1297
1298 #define TESTGETCALL(call, r) \
1299                 r.in.buffer = NULL; \
1300                 r.in.offered = 0;\
1301                 r.out.needed = &needed; \
1302                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1303                 if (!NT_STATUS_IS_OK(status)) { \
1304                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1305                                r.in.level, nt_errstr(status), __location__); \
1306                         ret = false; \
1307                         break; \
1308                 }\
1309                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1310                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1311                         r.in.buffer = &blob; \
1312                         r.in.offered = needed; \
1313                 }\
1314                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1315                 if (!NT_STATUS_IS_OK(status)) { \
1316                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1317                                r.in.level, nt_errstr(status), __location__); \
1318                         ret = false; \
1319                         break; \
1320                 } \
1321                 if (!W_ERROR_IS_OK(r.out.result)) { \
1322                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1323                                r.in.level, win_errstr(r.out.result), __location__); \
1324                         ret = false; \
1325                         break; \
1326                 }
1327
1328
1329 #define TESTSETCALL_EXP(call, r, err) \
1330                 clear_info2(&info_ctr);\
1331                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1332                 if (!NT_STATUS_IS_OK(status)) { \
1333                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1334                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1335                         ret = false; \
1336                         break; \
1337                 } \
1338                 if (!W_ERROR_IS_OK(err)) { \
1339                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1340                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1341                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1342                                 ret = false; \
1343                         } \
1344                         break; \
1345                 } \
1346                 if (!W_ERROR_IS_OK(r.out.result)) { \
1347                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1348                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1349                         ret = false; \
1350                         break; \
1351                 }
1352
1353 #define TESTSETCALL(call, r) \
1354         TESTSETCALL_EXP(call, r, WERR_OK)
1355
1356 #define STRING_EQUAL(s1, s2, field) \
1357                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1358                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1359                                #field, s2, __location__); \
1360                         ret = false; \
1361                         break; \
1362                 }
1363
1364 #define MEM_EQUAL(s1, s2, length, field) \
1365                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1366                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1367                                #field, (const char *)s2, __location__); \
1368                         ret = false; \
1369                         break; \
1370                 }
1371
1372 #define INT_EQUAL(i1, i2, field) \
1373                 if (i1 != i2) { \
1374                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1375                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1376                         ret = false; \
1377                         break; \
1378                 }
1379
1380 #define SD_EQUAL(sd1, sd2, field) \
1381                 if (!security_descriptor_equal(sd1, sd2)) { \
1382                         torture_comment(tctx, "Failed to set %s (%s)\n", \
1383                                #field, __location__); \
1384                         ret = false; \
1385                         break; \
1386                 }
1387
1388 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1389                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1390                 q.in.level = lvl1; \
1391                 TESTGETCALL(GetPrinter, q) \
1392                 info_ctr.level = lvl1; \
1393                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1394                 info_ctr.info.info ## lvl1->field1 = value;\
1395                 TESTSETCALL_EXP(SetPrinter, s, err) \
1396                 info_ctr.info.info ## lvl1->field1 = ""; \
1397                 TESTGETCALL(GetPrinter, q) \
1398                 info_ctr.info.info ## lvl1->field1 = value; \
1399                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1400                 q.in.level = lvl2; \
1401                 TESTGETCALL(GetPrinter, q) \
1402                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1403                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1404         } while (0)
1405
1406 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1407         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1408         } while (0);
1409
1410 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1411                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1412                 q.in.level = lvl1; \
1413                 TESTGETCALL(GetPrinter, q) \
1414                 info_ctr.level = lvl1; \
1415                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1416                 info_ctr.info.info ## lvl1->field1 = value; \
1417                 TESTSETCALL(SetPrinter, s) \
1418                 info_ctr.info.info ## lvl1->field1 = 0; \
1419                 TESTGETCALL(GetPrinter, q) \
1420                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1421                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1422                 q.in.level = lvl2; \
1423                 TESTGETCALL(GetPrinter, q) \
1424                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1425                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1426         } while (0)
1427
1428 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1429         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1430         } while (0)
1431
1432         q0.in.level = 0;
1433         do { TESTGETCALL(GetPrinter, q0) } while (0);
1434
1435         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1436         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1437
1438         /* level 0 printername does not stick */
1439 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1440         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1441         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1442         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1443         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1444 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1445         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1446         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1447         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1448         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1449 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1450         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1451         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1452         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1453         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1454
1455         /* servername can be set but does not stick
1456         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1457         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1458         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1459         */
1460
1461         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1462         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1463         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1464         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1465         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1466
1467         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1468         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1469         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1470         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1471         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1472         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1473         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1474         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1475         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1476         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1477
1478         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1479 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1480                         attribute_list[i],
1481                         (attribute_list[i] | default_attribute)
1482                         ); */
1483                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1484                         attribute_list[i],
1485                         (attribute_list[i] | default_attribute)
1486                         );
1487                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1488                         attribute_list[i],
1489                         (attribute_list[i] | default_attribute)
1490                         );
1491                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1492                         attribute_list[i],
1493                         (attribute_list[i] | default_attribute)
1494                         );
1495 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1496                         attribute_list[i],
1497                         (attribute_list[i] | default_attribute)
1498                         ); */
1499                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1500                         attribute_list[i],
1501                         (attribute_list[i] | default_attribute)
1502                         );
1503                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1504                         attribute_list[i],
1505                         (attribute_list[i] | default_attribute)
1506                         );
1507                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1508                         attribute_list[i],
1509                         (attribute_list[i] | default_attribute)
1510                         );
1511 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1512                         attribute_list[i],
1513                         (attribute_list[i] | default_attribute)
1514                         ); */
1515                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1516                         attribute_list[i],
1517                         (attribute_list[i] | default_attribute)
1518                         );
1519                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1520                         attribute_list[i],
1521                         (attribute_list[i] | default_attribute)
1522                         );
1523                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1524                         attribute_list[i],
1525                         (attribute_list[i] | default_attribute)
1526                         );
1527         }
1528
1529         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1530                 /* level 2 sets do not stick
1531                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1532                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1533                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1534                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1535                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1536                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1537         }
1538
1539         /* priorities need to be between 0 and 99
1540            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1541         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1542         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1543         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1544         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1545         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1546         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1547         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1548         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1549
1550         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1551         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1552
1553         /* does not stick
1554         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1555         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1556
1557         /* does not stick
1558         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1559         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1560
1561         /* FIXME: gd also test devmode and secdesc behavior */
1562
1563         {
1564                 /* verify composition of level 1 description field */
1565                 const char *description;
1566                 const char *tmp;
1567
1568                 q0.in.level = 1;
1569                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1570
1571                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1572
1573                 q0.in.level = 2;
1574                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1575
1576                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1577                         q0.out.info->info2.printername,
1578                         q0.out.info->info2.drivername,
1579                         q0.out.info->info2.location);
1580
1581                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1582         }
1583
1584         return ret;
1585 }
1586
1587 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1588         do { struct dom_sid *__got = (got), *__expected = (expected); \
1589         if (!dom_sid_equal(__got, __expected)) { \
1590                 torture_result(torture_ctx, TORTURE_FAIL, \
1591                                            __location__": "#got" was %s, expected %s: %s", \
1592                                            dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1593                 return false; \
1594         } \
1595         } while(0)
1596
1597 static bool test_security_descriptor_equal(struct torture_context *tctx,
1598                                            const struct security_descriptor *sd1,
1599                                            const struct security_descriptor *sd2)
1600 {
1601         if (sd1 == sd2) {
1602                 return true;
1603         }
1604
1605         if (!sd1 || !sd2) {
1606                 torture_comment(tctx, "%s\n", __location__);
1607                 return false;
1608         }
1609
1610         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1611         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1612
1613         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1614         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1615
1616         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1617                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1618                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1619                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1620                 return false;
1621         }
1622         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1623                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1624                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1625                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1626                 return false;
1627         }
1628
1629         return true;
1630 }
1631
1632 static bool test_sd_set_level(struct torture_context *tctx,
1633                               struct dcerpc_binding_handle *b,
1634                               struct policy_handle *handle,
1635                               uint32_t level,
1636                               struct security_descriptor *sd)
1637 {
1638         struct spoolss_SetPrinterInfoCtr info_ctr;
1639         struct spoolss_DevmodeContainer devmode_ctr;
1640         struct sec_desc_buf secdesc_ctr;
1641         union spoolss_SetPrinterInfo sinfo;
1642
1643         ZERO_STRUCT(devmode_ctr);
1644         ZERO_STRUCT(secdesc_ctr);
1645
1646         switch (level) {
1647         case 2: {
1648                 union spoolss_PrinterInfo info;
1649                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1650                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1651
1652                 info_ctr.level = 2;
1653                 info_ctr.info = sinfo;
1654
1655                 break;
1656         }
1657         case 3: {
1658                 struct spoolss_SetPrinterInfo3 info3;
1659
1660                 info3.sec_desc_ptr = 0;
1661
1662                 info_ctr.level = 3;
1663                 info_ctr.info.info3 = &info3;
1664
1665                 break;
1666         }
1667         default:
1668                 return false;
1669         }
1670
1671         secdesc_ctr.sd = sd;
1672
1673         torture_assert(tctx,
1674                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1675
1676         return true;
1677 }
1678
1679 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1680                                  struct dcerpc_binding_handle *b,
1681                                  struct policy_handle *handle)
1682 {
1683         union spoolss_PrinterInfo info;
1684         struct security_descriptor *sd1, *sd2;
1685         int i;
1686
1687         /* just compare level 2 and level 3 */
1688
1689         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1690
1691         sd1 = info.info2.secdesc;
1692
1693         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1694
1695         sd2 = info.info3.secdesc;
1696
1697         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1698                 "SD level 2 != SD level 3");
1699
1700
1701         /* query level 2, set level 2, query level 2 */
1702
1703         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1704
1705         sd1 = info.info2.secdesc;
1706
1707         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1708
1709         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1710
1711         sd2 = info.info2.secdesc;
1712         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1713                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1714                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1715         }
1716
1717         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1718                 "SD level 2 != SD level 2 after SD has been set via level 2");
1719
1720
1721         /* query level 2, set level 3, query level 2 */
1722
1723         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1724
1725         sd1 = info.info2.secdesc;
1726
1727         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1728
1729         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1730
1731         sd2 = info.info2.secdesc;
1732
1733         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1734                 "SD level 2 != SD level 2 after SD has been set via level 3");
1735
1736         /* set modified sd level 3, query level 2 */
1737
1738         for (i=0; i < 93; i++) {
1739                 struct security_ace a;
1740                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1741                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1742                 a.flags = 0;
1743                 a.size = 0; /* autogenerated */
1744                 a.access_mask = 0;
1745                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1746                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1747         }
1748
1749         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1750
1751         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1752         sd2 = info.info2.secdesc;
1753
1754         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1755                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1756                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1757         }
1758
1759         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1760                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1761
1762
1763         return true;
1764 }
1765
1766 /*
1767  * wrapper call that saves original sd, runs tests, and restores sd
1768  */
1769
1770 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1771                                 struct dcerpc_binding_handle *b,
1772                                 struct policy_handle *handle)
1773 {
1774         union spoolss_PrinterInfo info;
1775         struct security_descriptor *sd;
1776         bool ret = true;
1777
1778         torture_comment(tctx, "Testing Printer Security Descriptors\n");
1779
1780         /* save original sd */
1781
1782         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1783                 "failed to get initial security descriptor");
1784
1785         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1786
1787         /* run tests */
1788
1789         ret = test_PrinterInfo_SDs(tctx, b, handle);
1790
1791         /* restore original sd */
1792
1793         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1794                 "failed to restore initial security descriptor");
1795
1796         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1797                 ret ? "succeeded" : "failed");
1798
1799
1800         return ret;
1801 }
1802
1803 static bool test_devmode_set_level(struct torture_context *tctx,
1804                                    struct dcerpc_binding_handle *b,
1805                                    struct policy_handle *handle,
1806                                    uint32_t level,
1807                                    struct spoolss_DeviceMode *devmode)
1808 {
1809         struct spoolss_SetPrinterInfoCtr info_ctr;
1810         struct spoolss_DevmodeContainer devmode_ctr;
1811         struct sec_desc_buf secdesc_ctr;
1812         union spoolss_SetPrinterInfo sinfo;
1813
1814         ZERO_STRUCT(devmode_ctr);
1815         ZERO_STRUCT(secdesc_ctr);
1816
1817         switch (level) {
1818         case 2: {
1819                 union spoolss_PrinterInfo info;
1820                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1821                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1822
1823                 info_ctr.level = 2;
1824                 info_ctr.info = sinfo;
1825
1826                 break;
1827         }
1828         case 8: {
1829                 struct spoolss_SetPrinterInfo8 info8;
1830
1831                 info8.devmode_ptr = 0;
1832
1833                 info_ctr.level = 8;
1834                 info_ctr.info.info8 = &info8;
1835
1836                 break;
1837         }
1838         default:
1839                 return false;
1840         }
1841
1842         devmode_ctr.devmode = devmode;
1843
1844         torture_assert(tctx,
1845                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1846
1847         return true;
1848 }
1849
1850
1851 static bool test_devicemode_equal(struct torture_context *tctx,
1852                                   const struct spoolss_DeviceMode *d1,
1853                                   const struct spoolss_DeviceMode *d2)
1854 {
1855         if (d1 == d2) {
1856                 return true;
1857         }
1858
1859         if (!d1 || !d2) {
1860                 torture_comment(tctx, "%s\n", __location__);
1861                 return false;
1862         }
1863         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1864         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1865         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1866         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1867         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1868         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1869         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1870         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1871         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1872         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1873         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1874         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1875         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1876         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1877         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1878         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1879         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1880         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1881         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1882         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1883         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1884         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1885         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1886         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1887         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1888         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1889         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1890         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1891         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1892         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1893         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1894         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1895         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1896         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1897         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1898
1899         return true;
1900 }
1901
1902 static bool test_devicemode_full(struct torture_context *tctx,
1903                                  struct dcerpc_binding_handle *b,
1904                                  struct policy_handle *handle)
1905 {
1906         struct spoolss_SetPrinter s;
1907         struct spoolss_GetPrinter q;
1908         struct spoolss_GetPrinter q0;
1909         struct spoolss_SetPrinterInfoCtr info_ctr;
1910         struct spoolss_SetPrinterInfo8 info8;
1911         union spoolss_PrinterInfo info;
1912         struct spoolss_DevmodeContainer devmode_ctr;
1913         struct sec_desc_buf secdesc_ctr;
1914         uint32_t needed;
1915         bool ret = true;
1916         NTSTATUS status;
1917
1918 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1919                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1920                 q.in.level = lvl1; \
1921                 TESTGETCALL(GetPrinter, q) \
1922                 info_ctr.level = lvl1; \
1923                 if (lvl1 == 2) {\
1924                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1925                 } else if (lvl1 == 8) {\
1926                         info_ctr.info.info ## lvl1 = &info8; \
1927                 }\
1928                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1929                 devmode_ctr.devmode->field1 = value; \
1930                 TESTSETCALL(SetPrinter, s) \
1931                 TESTGETCALL(GetPrinter, q) \
1932                 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1933                 q.in.level = lvl2; \
1934                 TESTGETCALL(GetPrinter, q) \
1935                 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1936         } while (0)
1937
1938 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1939         TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1940         } while (0)
1941
1942         ZERO_STRUCT(devmode_ctr);
1943         ZERO_STRUCT(secdesc_ctr);
1944         ZERO_STRUCT(info8);
1945
1946         s.in.handle = handle;
1947         s.in.command = 0;
1948         s.in.info_ctr = &info_ctr;
1949         s.in.devmode_ctr = &devmode_ctr;
1950         s.in.secdesc_ctr = &secdesc_ctr;
1951
1952         q.in.handle = handle;
1953         q.out.info = &info;
1954         q0 = q;
1955
1956 #if 0
1957         const char *devicename;/* [charset(UTF16)] */
1958         enum spoolss_DeviceModeSpecVersion specversion;
1959         uint16_t driverversion;
1960         uint16_t size;
1961         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1962         uint32_t fields;
1963 #endif
1964
1965         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
1966         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
1967         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
1968         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
1969         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
1970         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
1971         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
1972         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
1973         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
1974         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
1975         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
1976         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
1977         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
1978 #if 0
1979         const char *formname;/* [charset(UTF16)] */
1980 #endif
1981         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
1982         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
1983         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
1984         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
1985         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
1986         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
1987         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
1988         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
1989         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
1990         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
1991         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
1992         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
1993         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
1994         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
1995
1996         return ret;
1997 }
1998
1999 static bool call_OpenPrinterEx(struct torture_context *tctx,
2000                                struct dcerpc_pipe *p,
2001                                const char *name,
2002                                struct spoolss_DeviceMode *devmode,
2003                                struct policy_handle *handle);
2004
2005 static bool test_ClosePrinter(struct torture_context *tctx,
2006                               struct dcerpc_binding_handle *b,
2007                               struct policy_handle *handle);
2008
2009 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2010                                       struct dcerpc_pipe *p,
2011                                       struct policy_handle *handle,
2012                                       const char *name)
2013 {
2014         union spoolss_PrinterInfo info;
2015         struct spoolss_DeviceMode *devmode;
2016         struct spoolss_DeviceMode *devmode2;
2017         struct policy_handle handle_devmode;
2018         struct dcerpc_binding_handle *b = p->binding_handle;
2019
2020         /* simply compare level8 and level2 devmode */
2021
2022         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2023
2024         devmode = info.info8.devmode;
2025
2026         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2027
2028         devmode2 = info.info2.devmode;
2029
2030         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2031                 "DM level 8 != DM level 2");
2032
2033
2034         /* set devicemode level 8 and see if it persists */
2035
2036         devmode->copies = 93;
2037         devmode->formname = talloc_strdup(tctx, "Legal");
2038
2039         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2040
2041         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2042
2043         devmode2 = info.info8.devmode;
2044
2045         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2046                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2047
2048         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2049
2050         devmode2 = info.info2.devmode;
2051
2052         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2053                 "modified DM level 8 != DM level 2");
2054
2055
2056         /* set devicemode level 2 and see if it persists */
2057
2058         devmode->copies = 39;
2059         devmode->formname = talloc_strdup(tctx, "Executive");
2060
2061         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2062
2063         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2064
2065         devmode2 = info.info8.devmode;
2066
2067         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2068                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2069
2070         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2071
2072         devmode2 = info.info2.devmode;
2073
2074         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2075                 "modified DM level 8 != DM level 2");
2076
2077
2078         /* check every single bit in public part of devicemode */
2079
2080         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2081                 "failed to set every single devicemode component");
2082
2083
2084         /* change formname upon open and see if it persists in getprinter calls */
2085
2086         devmode->formname = talloc_strdup(tctx, "A4");
2087         devmode->copies = 42;
2088
2089         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2090                 "failed to open printer handle");
2091
2092         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2093
2094         devmode2 = info.info8.devmode;
2095
2096         if (strequal(devmode->devicename, devmode2->devicename)) {
2097                 torture_warning(tctx, "devicenames are the same\n");
2098         } else {
2099                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2100                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2101         }
2102
2103         if (strequal(devmode->formname, devmode2->formname)) {
2104                 torture_warning(tctx, "formname are the same\n");
2105         } else {
2106                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2107                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2108         }
2109
2110         if (devmode->copies == devmode2->copies) {
2111                 torture_warning(tctx, "copies are the same\n");
2112         } else {
2113                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2114                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2115         }
2116
2117         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2118
2119         devmode2 = info.info2.devmode;
2120
2121         if (strequal(devmode->devicename, devmode2->devicename)) {
2122                 torture_warning(tctx, "devicenames are the same\n");
2123         } else {
2124                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2125                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2126         }
2127
2128         if (strequal(devmode->formname, devmode2->formname)) {
2129                 torture_warning(tctx, "formname is the same\n");
2130         } else {
2131                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2132                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2133         }
2134
2135         if (devmode->copies == devmode2->copies) {
2136                 torture_warning(tctx, "copies are the same\n");
2137         } else {
2138                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2139                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2140         }
2141
2142         test_ClosePrinter(tctx, b, &handle_devmode);
2143
2144         return true;
2145 }
2146
2147 /*
2148  * wrapper call that saves original devmode, runs tests, and restores devmode
2149  */
2150
2151 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2152                                      struct dcerpc_pipe *p,
2153                                      struct policy_handle *handle,
2154                                      const char *name)
2155 {
2156         union spoolss_PrinterInfo info;
2157         struct spoolss_DeviceMode *devmode;
2158         bool ret = true;
2159         struct dcerpc_binding_handle *b = p->binding_handle;
2160
2161         torture_comment(tctx, "Testing Printer Devicemodes\n");
2162
2163         /* save original devmode */
2164
2165         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2166                 "failed to get initial global devicemode");
2167
2168         devmode = info.info8.devmode;
2169
2170         /* run tests */
2171
2172         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2173
2174         /* restore original devmode */
2175
2176         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2177                 "failed to restore initial global device mode");
2178
2179         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2180                 ret ? "succeeded" : "failed");
2181
2182
2183         return ret;
2184 }
2185
2186 static bool test_ClosePrinter(struct torture_context *tctx,
2187                               struct dcerpc_binding_handle *b,
2188                               struct policy_handle *handle)
2189 {
2190         NTSTATUS status;
2191         struct spoolss_ClosePrinter r;
2192
2193         r.in.handle = handle;
2194         r.out.handle = handle;
2195
2196         torture_comment(tctx, "Testing ClosePrinter\n");
2197
2198         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2199         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2200         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2201
2202         return true;
2203 }
2204
2205 static bool test_GetForm_args(struct torture_context *tctx,
2206                               struct dcerpc_binding_handle *b,
2207                               struct policy_handle *handle,
2208                               const char *form_name,
2209                               uint32_t level,
2210                               union spoolss_FormInfo *info_p)
2211 {
2212         NTSTATUS status;
2213         struct spoolss_GetForm r;
2214         uint32_t needed;
2215
2216         r.in.handle = handle;
2217         r.in.form_name = form_name;
2218         r.in.level = level;
2219         r.in.buffer = NULL;
2220         r.in.offered = 0;
2221         r.out.needed = &needed;
2222
2223         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2224
2225         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2226         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2227
2228         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2229                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2230                 r.in.buffer = &blob;
2231                 r.in.offered = needed;
2232                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2233                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2234
2235                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2236
2237                 torture_assert(tctx, r.out.info, "No form info returned");
2238         }
2239
2240         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2241
2242         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2243
2244         if (info_p) {
2245                 *info_p = *r.out.info;
2246         }
2247
2248         return true;
2249 }
2250
2251 static bool test_GetForm(struct torture_context *tctx,
2252                          struct dcerpc_binding_handle *b,
2253                          struct policy_handle *handle,
2254                          const char *form_name,
2255                          uint32_t level)
2256 {
2257         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2258 }
2259
2260 static bool test_EnumForms(struct torture_context *tctx,
2261                            struct dcerpc_binding_handle *b,
2262                            struct policy_handle *handle,
2263                            bool print_server,
2264                            uint32_t level,
2265                            uint32_t *count_p,
2266                            union spoolss_FormInfo **info_p)
2267 {
2268         struct spoolss_EnumForms r;
2269         uint32_t needed;
2270         uint32_t count;
2271         union spoolss_FormInfo *info;
2272
2273         r.in.handle = handle;
2274         r.in.level = level;
2275         r.in.buffer = NULL;
2276         r.in.offered = 0;
2277         r.out.needed = &needed;
2278         r.out.count = &count;
2279         r.out.info = &info;
2280
2281         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2282
2283         torture_assert_ntstatus_ok(tctx,
2284                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2285                 "EnumForms failed");
2286
2287         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2288                 torture_skip(tctx, "EnumForms level 2 not supported");
2289         }
2290
2291         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2292                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2293         }
2294
2295         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2296                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2297                 r.in.buffer = &blob;
2298                 r.in.offered = needed;
2299
2300                 torture_assert_ntstatus_ok(tctx,
2301                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2302                         "EnumForms failed");
2303
2304                 torture_assert(tctx, info, "No forms returned");
2305         }
2306
2307         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2308
2309         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2310
2311         if (info_p) {
2312                 *info_p = info;
2313         }
2314         if (count_p) {
2315                 *count_p = count;
2316         }
2317
2318         return true;
2319 }
2320
2321 static bool test_EnumForms_all(struct torture_context *tctx,
2322                                struct dcerpc_binding_handle *b,
2323                                struct policy_handle *handle,
2324                                bool print_server)
2325 {
2326         uint32_t levels[] = { 1, 2 };
2327         int i, j;
2328
2329         for (i=0; i<ARRAY_SIZE(levels); i++) {
2330
2331                 uint32_t count = 0;
2332                 union spoolss_FormInfo *info = NULL;
2333
2334                 torture_assert(tctx,
2335                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2336                         "failed to enum forms");
2337
2338                 for (j = 0; j < count; j++) {
2339                         if (!print_server) {
2340                                 torture_assert(tctx,
2341                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2342                                         "failed to get form");
2343                         }
2344                 }
2345         }
2346
2347         return true;
2348 }
2349
2350 static bool test_EnumForms_find_one(struct torture_context *tctx,
2351                                     struct dcerpc_binding_handle *b,
2352                                     struct policy_handle *handle,
2353                                     bool print_server,
2354                                     const char *form_name)
2355 {
2356         union spoolss_FormInfo *info;
2357         uint32_t count;
2358         bool found = false;
2359         int i;
2360
2361         torture_assert(tctx,
2362                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2363                 "failed to enumerate forms");
2364
2365         for (i=0; i<count; i++) {
2366                 if (strequal(form_name, info[i].info1.form_name)) {
2367                         found = true;
2368                         break;
2369                 }
2370         }
2371
2372         return found;
2373 }
2374
2375 static bool test_DeleteForm(struct torture_context *tctx,
2376                             struct dcerpc_binding_handle *b,
2377                             struct policy_handle *handle,
2378                             const char *form_name,
2379                             WERROR expected_result)
2380 {
2381         struct spoolss_DeleteForm r;
2382
2383         r.in.handle = handle;
2384         r.in.form_name = form_name;
2385
2386         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2387
2388         torture_assert_ntstatus_ok(tctx,
2389                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2390                 "DeleteForm failed");
2391         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2392                 "DeleteForm gave unexpected result");
2393         if (W_ERROR_IS_OK(r.out.result)) {
2394                 torture_assert_ntstatus_ok(tctx,
2395                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2396                         "2nd DeleteForm failed");
2397                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2398                         "2nd DeleteForm failed");
2399         }
2400
2401         return true;
2402 }
2403
2404 static bool test_AddForm(struct torture_context *tctx,
2405                          struct dcerpc_binding_handle *b,
2406                          struct policy_handle *handle,
2407                          uint32_t level,
2408                          union spoolss_AddFormInfo *info,
2409                          WERROR expected_result)
2410 {
2411         struct spoolss_AddForm r;
2412
2413         if (level != 1) {
2414                 torture_skip(tctx, "only level 1 supported");
2415         }
2416
2417         r.in.handle     = handle;
2418         r.in.level      = level;
2419         r.in.info       = *info;
2420
2421         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2422                 r.in.info.info1->form_name, r.in.level,
2423                 r.in.info.info1->flags);
2424
2425         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2426                 "AddForm failed");
2427         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2428                 "AddForm gave unexpected result");
2429
2430         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2431                 "2nd AddForm failed");
2432         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2433                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2434                         "2nd AddForm gave unexpected result");
2435         } else {
2436                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2437                         "2nd AddForm gave unexpected result");
2438         }
2439
2440         return true;
2441 }
2442
2443 static bool test_SetForm(struct torture_context *tctx,
2444                          struct dcerpc_binding_handle *b,
2445                          struct policy_handle *handle,
2446                          const char *form_name,
2447                          uint32_t level,
2448                          union spoolss_AddFormInfo *info)
2449 {
2450         struct spoolss_SetForm r;
2451
2452         r.in.handle     = handle;
2453         r.in.form_name  = form_name;
2454         r.in.level      = level;
2455         r.in.info       = *info;
2456
2457         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2458                 form_name, r.in.level);
2459
2460         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2461                 "SetForm failed");
2462
2463         torture_assert_werr_ok(tctx, r.out.result,
2464                 "SetForm failed");
2465
2466         return true;
2467 }
2468
2469 static bool test_GetForm_winreg(struct torture_context *tctx,
2470                                 struct dcerpc_binding_handle *b,
2471                                 struct policy_handle *handle,
2472                                 const char *key_name,
2473                                 const char *form_name,
2474                                 enum winreg_Type *w_type,
2475                                 uint32_t *w_size,
2476                                 uint32_t *w_length,
2477                                 uint8_t **w_data);
2478
2479 static bool test_Forms_args(struct torture_context *tctx,
2480                             struct dcerpc_binding_handle *b,
2481                             struct policy_handle *handle,
2482                             bool print_server,
2483                             const char *printer_name,
2484                             struct dcerpc_binding_handle *winreg_handle,
2485                             struct policy_handle *hive_handle,
2486                             const char *form_name,
2487                             struct spoolss_AddFormInfo1 *info1,
2488                             WERROR expected_add_result,
2489                             WERROR expected_delete_result)
2490 {
2491         union spoolss_FormInfo info;
2492         union spoolss_AddFormInfo add_info;
2493
2494         enum winreg_Type w_type;
2495         uint32_t w_size;
2496         uint32_t w_length;
2497         uint8_t *w_data;
2498
2499         add_info.info1 = info1;
2500
2501         torture_assert(tctx,
2502                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2503                 "failed to add form");
2504
2505         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2506
2507                 torture_assert(tctx,
2508                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2509                         "failed to get form via winreg");
2510
2511                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2512                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2513                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2514                 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2515                 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2516                 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2517                 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2518                 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2519                 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2520                 /* skip index here */
2521                 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2522         }
2523
2524         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2525                 torture_assert(tctx,
2526                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2527                         "failed to get added form");
2528
2529                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2530                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2531                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2532                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2533                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2534                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2535                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2536
2537                 if (winreg_handle && hive_handle) {
2538                         torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2539                         torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2540                         torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2541                         torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2542                         torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2543                         torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2544                         /* skip index here */
2545                         torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2546                 }
2547
2548                 add_info.info1->size.width = 1234;
2549
2550                 torture_assert(tctx,
2551                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2552                         "failed to set form");
2553                 torture_assert(tctx,
2554                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2555                         "failed to get setted form");
2556
2557                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2558         }
2559
2560         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2561                 torture_assert(tctx,
2562                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2563                         "Newly added form not found in enum call");
2564         }
2565
2566         torture_assert(tctx,
2567                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2568                 "failed to delete form");
2569
2570         return true;
2571 }
2572
2573 static bool test_Forms(struct torture_context *tctx,
2574                        struct dcerpc_binding_handle *b,
2575                        struct policy_handle *handle,
2576                        bool print_server,
2577                        const char *printer_name,
2578                        struct dcerpc_binding_handle *winreg_handle,
2579                        struct policy_handle *hive_handle)
2580 {
2581
2582         struct spoolss_FormSize size;
2583         struct spoolss_FormArea area;
2584         int i;
2585
2586         size.width      = 50;
2587         size.height     = 25;
2588         area.left       = 5;
2589         area.top        = 10;
2590         area.right      = 45;
2591         area.bottom     = 15;
2592
2593         struct {
2594                 struct spoolss_AddFormInfo1 info1;
2595                 WERROR expected_add_result;
2596                 WERROR expected_delete_result;
2597         } forms[] = {
2598                 {
2599                         .info1.flags            = SPOOLSS_FORM_USER,
2600                         .info1.form_name        = "testform_user",
2601                         .info1.size             = size,
2602                         .info1.area             = area,
2603                         .expected_add_result    = WERR_OK,
2604                         .expected_delete_result = WERR_OK
2605                 },
2606 /*
2607                 weird, we can add a builtin form but we can never remove it
2608                 again - gd
2609
2610                 {
2611                         .info1.flags            = SPOOLSS_FORM_BUILTIN,
2612                         .info1.form_name        = "testform_builtin",
2613                         .info1.size             = size,
2614                         .info1.area             = area,
2615                         .expected_add_result    = WERR_OK,
2616                         .expected_delete_result = WERR_INVALID_PARAM,
2617                 },
2618 */
2619                 {
2620                         .info1.flags            = SPOOLSS_FORM_PRINTER,
2621                         .info1.form_name        = "testform_printer",
2622                         .info1.size             = size,
2623                         .info1.area             = area,
2624                         .expected_add_result    = WERR_OK,
2625                         .expected_delete_result = WERR_OK
2626                 },
2627                 {
2628                         .info1.flags            = SPOOLSS_FORM_USER,
2629                         .info1.form_name        = "Letter",
2630                         .info1.size             = size,
2631                         .info1.area             = area,
2632                         .expected_add_result    = WERR_FILE_EXISTS,
2633                         .expected_delete_result = WERR_INVALID_PARAM
2634                 },
2635                 {
2636                         .info1.flags            = SPOOLSS_FORM_BUILTIN,
2637                         .info1.form_name        = "Letter",
2638                         .info1.size             = size,
2639                         .info1.area             = area,
2640                         .expected_add_result    = WERR_FILE_EXISTS,
2641                         .expected_delete_result = WERR_INVALID_PARAM
2642                 },
2643                 {
2644                         .info1.flags            = SPOOLSS_FORM_PRINTER,
2645                         .info1.form_name        = "Letter",
2646                         .info1.size             = size,
2647                         .info1.area             = area,
2648                         .expected_add_result    = WERR_FILE_EXISTS,
2649                         .expected_delete_result = WERR_INVALID_PARAM
2650                 },
2651                 {
2652                         .info1.flags            = 12345,
2653                         .info1.form_name        = "invalid_flags",
2654                         .info1.size             = size,
2655                         .info1.area             = area,
2656                         .expected_add_result    = WERR_INVALID_PARAM,
2657                         .expected_delete_result = WERR_INVALID_FORM_NAME
2658                 }
2659
2660         };
2661
2662         for (i=0; i < ARRAY_SIZE(forms); i++) {
2663                 torture_assert(tctx,
2664                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2665                                         winreg_handle, hive_handle,
2666                                         forms[i].info1.form_name,
2667                                         &forms[i].info1,
2668                                         forms[i].expected_add_result,
2669                                         forms[i].expected_delete_result),
2670                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2671         }
2672
2673         return true;
2674 }
2675
2676 static bool test_EnumPorts_old(struct torture_context *tctx,
2677                                struct dcerpc_pipe *p)
2678 {
2679         NTSTATUS status;
2680         struct spoolss_EnumPorts r;
2681         uint32_t needed;
2682         uint32_t count;
2683         union spoolss_PortInfo *info;
2684         struct dcerpc_binding_handle *b = p->binding_handle;
2685
2686         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2687                                           dcerpc_server_name(p));
2688         r.in.level = 2;
2689         r.in.buffer = NULL;
2690         r.in.offered = 0;
2691         r.out.needed = &needed;
2692         r.out.count = &count;
2693         r.out.info = &info;
2694
2695         torture_comment(tctx, "Testing EnumPorts\n");
2696
2697         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2698
2699         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2700
2701         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2702                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2703                 r.in.buffer = &blob;
2704                 r.in.offered = needed;
2705
2706                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2707                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2708                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2709
2710                 torture_assert(tctx, info, "No ports returned");
2711         }
2712
2713         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2714
2715         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2716
2717         return true;
2718 }
2719
2720 static bool test_AddPort(struct torture_context *tctx,
2721                          struct dcerpc_pipe *p)
2722 {
2723         NTSTATUS status;
2724         struct spoolss_AddPort r;
2725         struct dcerpc_binding_handle *b = p->binding_handle;
2726
2727         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2728                                            dcerpc_server_name(p));
2729         r.in.unknown = 0;
2730         r.in.monitor_name = "foo";
2731
2732         torture_comment(tctx, "Testing AddPort\n");
2733
2734         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2735
2736         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2737
2738         /* win2k3 returns WERR_NOT_SUPPORTED */
2739
2740 #if 0
2741
2742         if (!W_ERROR_IS_OK(r.out.result)) {
2743                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2744                 return false;
2745         }
2746
2747 #endif
2748
2749         return true;
2750 }
2751
2752 static bool test_GetJob_args(struct torture_context *tctx,
2753                              struct dcerpc_binding_handle *b,
2754                              struct policy_handle *handle,
2755                              uint32_t job_id,
2756                              uint32_t level,
2757                              union spoolss_JobInfo *info_p)
2758 {
2759         NTSTATUS status;
2760         struct spoolss_GetJob r;
2761         union spoolss_JobInfo info;
2762         uint32_t needed;
2763
2764         r.in.handle = handle;
2765         r.in.job_id = job_id;
2766         r.in.level = level;
2767         r.in.buffer = NULL;
2768         r.in.offered = 0;
2769         r.out.needed = &needed;
2770         r.out.info = &info;
2771
2772         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2773
2774         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2775         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2776         if (level == 0) {
2777                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2778         }
2779
2780         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2781                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2782                 r.in.buffer = &blob;
2783                 r.in.offered = needed;
2784
2785                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2786                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2787         }
2788
2789         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2790         torture_assert(tctx, r.out.info, "No job info returned");
2791
2792         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2793
2794         if (info_p) {
2795                 *info_p = *r.out.info;
2796         }
2797
2798         return true;
2799 }
2800
2801 static bool test_GetJob(struct torture_context *tctx,
2802                         struct dcerpc_binding_handle *b,
2803                         struct policy_handle *handle,
2804                         uint32_t job_id)
2805 {
2806         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
2807         uint32_t i;
2808
2809         for (i=0; i < ARRAY_SIZE(levels); i++) {
2810                 torture_assert(tctx,
2811                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
2812                         "GetJob failed");
2813         }
2814
2815         return true;
2816 }
2817
2818 static bool test_SetJob(struct torture_context *tctx,
2819                         struct dcerpc_binding_handle *b,
2820                         struct policy_handle *handle, uint32_t job_id,
2821                         enum spoolss_JobControl command)
2822 {
2823         NTSTATUS status;
2824         struct spoolss_SetJob r;
2825
2826         r.in.handle     = handle;
2827         r.in.job_id     = job_id;
2828         r.in.ctr        = NULL;
2829         r.in.command    = command;
2830
2831         switch (command) {
2832         case SPOOLSS_JOB_CONTROL_PAUSE:
2833                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2834                 break;
2835         case SPOOLSS_JOB_CONTROL_RESUME:
2836                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2837                 break;
2838         case SPOOLSS_JOB_CONTROL_CANCEL:
2839                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2840                 break;
2841         case SPOOLSS_JOB_CONTROL_RESTART:
2842                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2843                 break;
2844         case SPOOLSS_JOB_CONTROL_DELETE:
2845                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2846                 break;
2847         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2848                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2849                 break;
2850         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2851                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2852                 break;
2853         case SPOOLSS_JOB_CONTROL_RETAIN:
2854                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2855                 break;
2856         case SPOOLSS_JOB_CONTROL_RELEASE:
2857                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2858                 break;
2859         default:
2860                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
2861                 break;
2862         }
2863
2864         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
2865         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2866         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2867
2868         return true;
2869 }
2870
2871 static bool test_AddJob(struct torture_context *tctx,
2872                         struct dcerpc_binding_handle *b,
2873                         struct policy_handle *handle)
2874 {
2875         NTSTATUS status;
2876         struct spoolss_AddJob r;
2877         uint32_t needed;
2878
2879         r.in.level = 0;
2880         r.in.handle = handle;
2881         r.in.offered = 0;
2882         r.out.needed = &needed;
2883         r.in.buffer = r.out.buffer = NULL;
2884
2885         torture_comment(tctx, "Testing AddJob\n");
2886
2887         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2888         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2889
2890         r.in.level = 1;
2891
2892         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2893         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2894
2895         return true;
2896 }
2897
2898
2899 static bool test_EnumJobs_args(struct torture_context *tctx,
2900                                struct dcerpc_binding_handle *b,
2901                                struct policy_handle *handle,
2902                                uint32_t level,
2903                                uint32_t *count_p,
2904                                union spoolss_JobInfo **info_p)
2905 {
2906         NTSTATUS status;
2907         struct spoolss_EnumJobs r;
2908         uint32_t needed;
2909         uint32_t count;
2910         union spoolss_JobInfo *info;
2911
2912         r.in.handle = handle;
2913         r.in.firstjob = 0;
2914         r.in.numjobs = 0xffffffff;
2915         r.in.level = level;
2916         r.in.buffer = NULL;
2917         r.in.offered = 0;
2918         r.out.needed = &needed;
2919         r.out.count = &count;
2920         r.out.info = &info;
2921
2922         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
2923
2924         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2925
2926         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2927
2928         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2929                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2930                 r.in.buffer = &blob;
2931                 r.in.offered = needed;
2932
2933                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2934
2935                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2936                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2937                 torture_assert(tctx, info, "No jobs returned");
2938
2939                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2940
2941         } else {
2942                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2943         }
2944
2945         if (count_p) {
2946                 *count_p = count;
2947         }
2948         if (info_p) {
2949                 *info_p = info;
2950         }
2951
2952         return true;
2953 }
2954
2955 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
2956                                          struct dcerpc_binding_handle *b,
2957                                          struct policy_handle *handle,
2958                                          uint32_t *job_id)
2959 {
2960         NTSTATUS status;
2961         struct spoolss_StartDocPrinter s;
2962         struct spoolss_DocumentInfo1 info1;
2963         struct spoolss_StartPagePrinter sp;
2964         struct spoolss_WritePrinter w;
2965         struct spoolss_EndPagePrinter ep;
2966         struct spoolss_EndDocPrinter e;
2967         int i;
2968         uint32_t num_written;
2969
2970         torture_comment(tctx, "Testing StartDocPrinter\n");
2971
2972         s.in.handle             = handle;
2973         s.in.level              = 1;
2974         s.in.info.info1         = &info1;
2975         s.out.job_id            = job_id;
2976         info1.document_name     = "TorturePrintJob";
2977         info1.output_file       = NULL;
2978         info1.datatype          = "RAW";
2979
2980         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
2981         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2982         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2983
2984         for (i=1; i < 4; i++) {
2985                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2986
2987                 sp.in.handle            = handle;
2988
2989                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
2990                 torture_assert_ntstatus_ok(tctx, status,
2991                                            "dcerpc_spoolss_StartPagePrinter failed");
2992                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2993
2994                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2995
2996                 w.in.handle             = handle;
2997                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2998                 w.out.num_written       = &num_written;
2999
3000                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3001                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3002                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3003
3004                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3005
3006                 ep.in.handle            = handle;
3007
3008                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3009                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3010                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3011         }
3012
3013         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3014
3015         e.in.handle = handle;
3016
3017         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3018         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3019         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3020
3021         return true;
3022 }
3023
3024 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3025                                         struct dcerpc_binding_handle *b,
3026                                         struct policy_handle *handle,
3027                                         uint32_t num_jobs,
3028                                         uint32_t *job_ids)
3029 {
3030         uint32_t count;
3031         union spoolss_JobInfo *info = NULL;
3032         int i;
3033
3034         torture_assert(tctx,
3035                 test_AddJob(tctx, b, handle),
3036                 "AddJob failed");
3037
3038         torture_assert(tctx,
3039                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3040                 "EnumJobs level 1 failed");
3041
3042         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3043
3044         for (i=0; i < num_jobs; i++) {
3045                 union spoolss_JobInfo ginfo;
3046
3047                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3048
3049                 torture_assert(tctx,
3050                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3051                         "failed to call test_GetJob");
3052
3053                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3054         }
3055
3056         for (i=0; i < num_jobs; i++) {
3057                 torture_assert(tctx,
3058                         test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE),
3059                         "failed to pause printjob");
3060                 torture_assert(tctx,
3061                         test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME),
3062                         "failed to resume printjob");
3063         }
3064
3065         return true;
3066 }
3067
3068 static bool test_DoPrintTest(struct torture_context *tctx,
3069                              struct dcerpc_binding_handle *b,
3070                              struct policy_handle *handle)
3071 {
3072         bool ret = true;
3073         uint32_t num_jobs = 8;
3074         uint32_t *job_ids;
3075         int i;
3076
3077         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3078
3079         for (i=0; i < num_jobs; i++) {
3080                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3081         }
3082
3083         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3084
3085         for (i=0; i < num_jobs; i++) {
3086                 ret &= test_SetJob(tctx, b, handle, job_ids[i], SPOOLSS_JOB_CONTROL_DELETE);
3087         }
3088
3089         return ret;
3090 }
3091
3092 static bool test_PausePrinter(struct torture_context *tctx,
3093                               struct dcerpc_binding_handle *b,
3094                               struct policy_handle *handle)
3095 {
3096         NTSTATUS status;
3097         struct spoolss_SetPrinter r;
3098         struct spoolss_SetPrinterInfoCtr info_ctr;
3099         struct spoolss_DevmodeContainer devmode_ctr;
3100         struct sec_desc_buf secdesc_ctr;
3101
3102         info_ctr.level = 0;
3103         info_ctr.info.info0 = NULL;
3104
3105         ZERO_STRUCT(devmode_ctr);
3106         ZERO_STRUCT(secdesc_ctr);
3107
3108         r.in.handle             = handle;
3109         r.in.info_ctr           = &info_ctr;
3110         r.in.devmode_ctr        = &devmode_ctr;
3111         r.in.secdesc_ctr        = &secdesc_ctr;
3112         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3113
3114         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3115
3116         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3117
3118         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3119
3120         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3121
3122         return true;
3123 }
3124
3125 static bool test_ResumePrinter(struct torture_context *tctx,
3126                                struct dcerpc_binding_handle *b,
3127                                struct policy_handle *handle)
3128 {
3129         NTSTATUS status;
3130         struct spoolss_SetPrinter r;
3131         struct spoolss_SetPrinterInfoCtr info_ctr;
3132         struct spoolss_DevmodeContainer devmode_ctr;
3133         struct sec_desc_buf secdesc_ctr;
3134
3135         info_ctr.level = 0;
3136         info_ctr.info.info0 = NULL;
3137
3138         ZERO_STRUCT(devmode_ctr);
3139         ZERO_STRUCT(secdesc_ctr);
3140
3141         r.in.handle             = handle;
3142         r.in.info_ctr           = &info_ctr;
3143         r.in.devmode_ctr        = &devmode_ctr;
3144         r.in.secdesc_ctr        = &secdesc_ctr;
3145         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3146
3147         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3148
3149         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3150
3151         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3152
3153         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3154
3155         return true;
3156 }
3157
3158 static bool test_GetPrinterData(struct torture_context *tctx,
3159                                 struct dcerpc_binding_handle *b,
3160                                 struct policy_handle *handle,
3161                                 const char *value_name,
3162                                 enum winreg_Type *type_p,
3163                                 uint8_t **data_p,
3164                                 uint32_t *needed_p)
3165 {
3166         NTSTATUS status;
3167         struct spoolss_GetPrinterData r;
3168         uint32_t needed;
3169         enum winreg_Type type;
3170         union spoolss_PrinterData data;
3171
3172         r.in.handle = handle;
3173         r.in.value_name = value_name;
3174         r.in.offered = 0;
3175         r.out.needed = &needed;
3176         r.out.type = &type;
3177         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3178
3179         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3180
3181         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3182         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3183
3184         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3185                 r.in.offered = needed;
3186                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3187                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3188                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3189         }
3190
3191         torture_assert_werr_ok(tctx, r.out.result,
3192                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3193
3194         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3195
3196         if (type_p) {
3197                 *type_p = type;
3198         }
3199
3200         if (data_p) {
3201                 *data_p = r.out.data;
3202         }
3203
3204         if (needed_p) {
3205                 *needed_p = needed;
3206         }
3207
3208         return true;
3209 }
3210
3211 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3212                                   struct dcerpc_pipe *p,
3213                                   struct policy_handle *handle,
3214                                   const char *key_name,
3215                                   const char *value_name,
3216                                   enum winreg_Type *type_p,
3217                                   uint8_t **data_p,
3218                                   uint32_t *needed_p)
3219 {
3220         NTSTATUS status;
3221         struct spoolss_GetPrinterDataEx r;
3222         enum winreg_Type type;
3223         uint32_t needed;
3224         union spoolss_PrinterData data;
3225         struct dcerpc_binding_handle *b = p->binding_handle;
3226
3227         r.in.handle = handle;
3228         r.in.key_name = key_name;
3229         r.in.value_name = value_name;
3230         r.in.offered = 0;
3231         r.out.type = &type;
3232         r.out.needed = &needed;
3233         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3234
3235         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3236                 r.in.key_name, r.in.value_name);
3237
3238         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3239         if (!NT_STATUS_IS_OK(status)) {
3240                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
3241                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
3242                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3243                 }
3244                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3245         }
3246
3247         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3248                 r.in.offered = needed;
3249                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3250                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3251                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3252         }
3253
3254         torture_assert_werr_ok(tctx, r.out.result,
3255                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3256
3257         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3258
3259         if (type_p) {
3260                 *type_p = type;
3261         }
3262
3263         if (data_p) {
3264                 *data_p = r.out.data;
3265         }
3266
3267         if (needed_p) {
3268                 *needed_p = needed;
3269         }
3270
3271         return true;
3272 }
3273
3274 static bool test_GetPrinterData_list(struct torture_context *tctx,
3275                                      struct dcerpc_pipe *p,
3276                                      struct policy_handle *handle,
3277                                      const char **architecture)
3278 {
3279         struct dcerpc_binding_handle *b = p->binding_handle;
3280         const char *list[] = {
3281                 "W3SvcInstalled",
3282                 "BeepEnabled",
3283                 "EventLog",
3284                 /* "NetPopup", not on w2k8 */
3285                 /* "NetPopupToComputer", not on w2k8 */
3286                 "MajorVersion",
3287                 "MinorVersion",
3288                 "DefaultSpoolDirectory",
3289                 "Architecture",
3290                 "DsPresent",
3291                 "OSVersion",
3292                 /* "OSVersionEx", not on s3 */
3293                 "DNSMachineName"
3294         };
3295         int i;
3296
3297         for (i=0; i < ARRAY_SIZE(list); i++) {
3298                 enum winreg_Type type, type_ex;
3299                 uint8_t *data, *data_ex;
3300                 uint32_t needed, needed_ex;
3301
3302                 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3303                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3304                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3305                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3306                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3307                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3308                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3309
3310                 if (strequal(list[i], "Architecture")) {
3311                         if (architecture) {
3312                                 DATA_BLOB blob = data_blob_const(data, needed);
3313                                 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3314                         }
3315                 }
3316         }
3317
3318         return true;
3319 }
3320
3321 static bool test_EnumPrinterData(struct torture_context *tctx,
3322                                  struct dcerpc_pipe *p,
3323                                  struct policy_handle *handle,
3324                                  uint32_t enum_index,
3325                                  uint32_t value_offered,
3326                                  uint32_t data_offered,
3327                                  enum winreg_Type *type_p,
3328                                  uint32_t *value_needed_p,
3329                                  uint32_t *data_needed_p,
3330                                  const char **value_name_p,
3331                                  uint8_t **data_p,
3332                                  WERROR *result_p)
3333 {
3334         struct spoolss_EnumPrinterData r;
3335         uint32_t data_needed;
3336         uint32_t value_needed;
3337         enum winreg_Type type;
3338         struct dcerpc_binding_handle *b = p->binding_handle;
3339
3340         r.in.handle = handle;
3341         r.in.enum_index = enum_index;
3342         r.in.value_offered = value_offered;
3343         r.in.data_offered = data_offered;
3344         r.out.data_needed = &data_needed;
3345         r.out.value_needed = &value_needed;
3346         r.out.type = &type;
3347         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3348         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3349
3350         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3351
3352         torture_assert_ntstatus_ok(tctx,
3353                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3354                 "EnumPrinterData failed");
3355
3356         if (type_p) {
3357                 *type_p = type;
3358         }
3359         if (value_needed_p) {
3360                 *value_needed_p = value_needed;
3361         }
3362         if (data_needed_p) {
3363                 *data_needed_p = data_needed;
3364         }
3365         if (value_name_p) {
3366                 *value_name_p = r.out.value_name;
3367         }
3368         if (data_p) {
3369                 *data_p = r.out.data;
3370         }
3371         if (result_p) {
3372                 *result_p = r.out.result;
3373         }
3374
3375         return true;
3376 }
3377
3378
3379 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3380                                      struct dcerpc_pipe *p,
3381                                      struct policy_handle *handle)
3382 {
3383         uint32_t enum_index = 0;
3384         enum winreg_Type type;
3385         uint32_t value_needed;
3386         uint32_t data_needed;
3387         uint8_t *data;
3388         const char *value_name;
3389         WERROR result;
3390
3391         torture_comment(tctx, "Testing EnumPrinterData\n");
3392
3393         do {
3394                 torture_assert(tctx,
3395                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3396                                              &type, &value_needed, &data_needed,
3397                                              &value_name, &data, &result),
3398                         "EnumPrinterData failed");
3399
3400                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3401                         break;
3402                 }
3403
3404                 torture_assert(tctx,
3405                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3406                                              &type, &value_needed, &data_needed,
3407                                              &value_name, &data, &result),
3408                         "EnumPrinterData failed");
3409
3410                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3411                         break;
3412                 }
3413
3414                 enum_index++;
3415
3416         } while (W_ERROR_IS_OK(result));
3417
3418         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3419
3420         return true;
3421 }
3422
3423 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3424                                    struct dcerpc_binding_handle *b,
3425                                    struct policy_handle *handle,
3426                                    const char *key_name,
3427                                    uint32_t *count_p,
3428                                    struct spoolss_PrinterEnumValues **info_p)
3429 {
3430         struct spoolss_EnumPrinterDataEx r;
3431         struct spoolss_PrinterEnumValues *info;
3432         uint32_t needed;
3433         uint32_t count;
3434
3435         r.in.handle = handle;
3436         r.in.key_name = key_name;
3437         r.in.offered = 0;
3438         r.out.needed = &needed;
3439         r.out.count = &count;
3440         r.out.info = &info;
3441
3442         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3443
3444         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3445                 "EnumPrinterDataEx failed");
3446         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3447                 r.in.offered = needed;
3448                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3449                         "EnumPrinterDataEx failed");
3450         }
3451
3452         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3453
3454         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3455
3456         if (count_p) {
3457                 *count_p = count;
3458         }
3459         if (info_p) {
3460                 *info_p = info;
3461         }
3462
3463         return true;
3464 }
3465
3466 static bool test_SetPrinterData(struct torture_context *tctx,
3467                                 struct dcerpc_binding_handle *b,
3468                                 struct policy_handle *handle,
3469                                 const char *value_name,
3470                                 enum winreg_Type type,
3471                                 uint8_t *data,
3472                                 uint32_t offered);
3473 static bool test_DeletePrinterData(struct torture_context *tctx,
3474                                    struct dcerpc_binding_handle *b,
3475                                    struct policy_handle *handle,
3476                                    const char *value_name);
3477
3478 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3479                                              struct dcerpc_pipe *p,
3480                                              struct policy_handle *handle)
3481 {
3482         uint32_t count;
3483         struct spoolss_PrinterEnumValues *info;
3484         int i;
3485         uint32_t value_needed, data_needed;
3486         uint32_t value_offered, data_offered;
3487         WERROR result;
3488         struct dcerpc_binding_handle *b = p->binding_handle;
3489
3490         enum winreg_Type type;
3491         DATA_BLOB blob;
3492
3493         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3494
3495         torture_assert(tctx,
3496                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3497                                   "REG_SZ", "torture_data1", &type, &blob), "");
3498
3499         torture_assert(tctx,
3500                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3501                 "SetPrinterData failed");
3502
3503         blob = data_blob_string_const("torture_data2");
3504
3505         torture_assert(tctx,
3506                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3507                 "SetPrinterData failed");
3508
3509         blob = data_blob_talloc(tctx, NULL, 4);
3510         SIVAL(blob.data, 0, 0x11223344);
3511
3512         torture_assert(tctx,
3513                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3514                 "SetPrinterData failed");
3515
3516         torture_assert(tctx,
3517                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3518                 "failed to call EnumPrinterDataEx");
3519
3520         /* get the max sizes for value and data */
3521
3522         torture_assert(tctx,
3523                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3524                                      NULL, &value_needed, &data_needed,
3525                                      NULL, NULL, &result),
3526                 "EnumPrinterData failed");
3527         torture_assert_werr_ok(tctx, result, "unexpected result");
3528
3529         /* check if the reply from the EnumPrinterData really matches max values */
3530
3531         for (i=0; i < count; i++) {
3532                 if (info[i].value_name_len > value_needed) {
3533                         torture_fail(tctx,
3534                                 talloc_asprintf(tctx,
3535                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3536                                 info[i].value_name_len, value_needed));
3537                 }
3538                 if (info[i].data_length > data_needed) {
3539                         torture_fail(tctx,
3540                                 talloc_asprintf(tctx,
3541                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3542                                 info[i].data_length, data_needed));
3543                 }
3544         }
3545
3546         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3547          * sort or not sort the replies by value name, we should be able to do
3548          * the following entry comparison */
3549
3550         data_offered = data_needed;
3551         value_offered = value_needed;
3552
3553         for (i=0; i < count; i++) {
3554
3555                 const char *value_name;
3556                 uint8_t *data;
3557
3558                 torture_assert(tctx,
3559                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3560                                              &type, &value_needed, &data_needed,
3561                                              &value_name, &data, &result),
3562                         "EnumPrinterData failed");
3563
3564                 if (i -1 == count) {
3565                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3566                                 "unexpected result");
3567                         break;
3568                 } else {
3569                         torture_assert_werr_ok(tctx, result, "unexpected result");
3570                 }
3571
3572                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3573                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3574                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3575                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3576                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3577         }
3578
3579         torture_assert(tctx,
3580                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3581                 "DeletePrinterData failed");
3582         torture_assert(tctx,
3583                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3584                 "DeletePrinterData failed");
3585         torture_assert(tctx,
3586                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3587                 "DeletePrinterData failed");
3588
3589         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3590
3591         return true;
3592 }
3593
3594 static bool test_DeletePrinterData(struct torture_context *tctx,
3595                                    struct dcerpc_binding_handle *b,
3596                                    struct policy_handle *handle,
3597                                    const char *value_name)
3598 {
3599         NTSTATUS status;
3600         struct spoolss_DeletePrinterData r;
3601
3602         r.in.handle = handle;
3603         r.in.value_name = value_name;
3604
3605         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3606                 r.in.value_name);
3607
3608         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3609
3610         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3611         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3612
3613         return true;
3614 }
3615
3616 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3617                                      struct dcerpc_binding_handle *b,
3618                                      struct policy_handle *handle,
3619                                      const char *key_name,
3620                                      const char *value_name)
3621 {
3622         struct spoolss_DeletePrinterDataEx r;
3623
3624         r.in.handle = handle;
3625         r.in.key_name = key_name;
3626         r.in.value_name = value_name;
3627
3628         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3629                 r.in.key_name, r.in.value_name);
3630
3631         torture_assert_ntstatus_ok(tctx,
3632                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3633                 "DeletePrinterDataEx failed");
3634         torture_assert_werr_ok(tctx, r.out.result,
3635                 "DeletePrinterDataEx failed");
3636
3637         return true;
3638 }
3639
3640 static bool test_DeletePrinterKey(struct torture_context *tctx,
3641                                   struct dcerpc_binding_handle *b,
3642                                   struct policy_handle *handle,
3643                                   const char *key_name)
3644 {
3645         struct spoolss_DeletePrinterKey r;
3646
3647         r.in.handle = handle;
3648         r.in.key_name = key_name;
3649
3650         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3651
3652         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3653                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3654                 return true;
3655         }
3656
3657         torture_assert_ntstatus_ok(tctx,
3658                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3659                 "DeletePrinterKey failed");
3660         torture_assert_werr_ok(tctx, r.out.result,
3661                 "DeletePrinterKey failed");
3662
3663         return true;
3664 }
3665
3666 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3667                                  struct dcerpc_binding_handle *b,
3668                                  struct policy_handle *handle)
3669 {
3670         struct winreg_OpenHKLM r;
3671
3672         r.in.system_name = NULL;
3673         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3674         r.out.handle = handle;
3675
3676         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3677
3678         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3679         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3680
3681         return true;
3682 }
3683
3684 static void init_winreg_String(struct winreg_String *name, const char *s)
3685 {
3686         name->name = s;
3687         if (s) {
3688                 name->name_len = 2 * (strlen_m(s) + 1);
3689                 name->name_size = name->name_len;
3690         } else {
3691                 name->name_len = 0;
3692                 name->name_size = 0;
3693         }
3694 }
3695
3696 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3697                                      struct dcerpc_binding_handle *b,
3698                                      struct policy_handle *hive_handle,
3699                                      const char *keyname,
3700                                      uint32_t options,
3701                                      struct policy_handle *key_handle)
3702 {
3703         struct winreg_OpenKey r;
3704
3705         r.in.parent_handle = hive_handle;
3706         init_winreg_String(&r.in.keyname, keyname);
3707         r.in.options = options;
3708         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3709         r.out.handle = key_handle;
3710
3711         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3712
3713         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3714         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3715
3716         return true;
3717 }
3718
3719 static bool test_winreg_OpenKey(struct torture_context *tctx,
3720                                 struct dcerpc_binding_handle *b,
3721                                 struct policy_handle *hive_handle,
3722                                 const char *keyname,
3723                                 struct policy_handle *key_handle)
3724 {
3725         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
3726                                         REG_OPTION_NON_VOLATILE, key_handle);
3727 }
3728
3729 static bool test_winreg_CloseKey(struct torture_context *tctx,
3730                                  struct dcerpc_binding_handle *b,
3731                                  struct policy_handle *handle)
3732 {
3733         struct winreg_CloseKey r;
3734
3735         r.in.handle = handle;
3736         r.out.handle = handle;
3737
3738         torture_comment(tctx, "Testing winreg_CloseKey\n");
3739
3740         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3741         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3742
3743         return true;
3744 }
3745
3746 bool test_winreg_QueryValue(struct torture_context *tctx,
3747                             struct dcerpc_binding_handle *b,
3748                             struct policy_handle *handle,
3749                             const char *value_name,
3750                             enum winreg_Type *type_p,
3751                             uint32_t *data_size_p,
3752                             uint32_t *data_length_p,
3753                             uint8_t **data_p)
3754 {
3755         struct winreg_QueryValue r;
3756         enum winreg_Type type = REG_NONE;
3757         uint32_t data_size = 0;
3758         uint32_t data_length = 0;
3759         struct winreg_String valuename;
3760         uint8_t *data = NULL;
3761
3762         init_winreg_String(&valuename, value_name);
3763
3764         data = talloc_zero_array(tctx, uint8_t, 0);
3765
3766         r.in.handle = handle;
3767         r.in.value_name = &valuename;
3768         r.in.type = &type;
3769         r.in.data_size = &data_size;
3770         r.in.data_length = &data_length;
3771         r.in.data = data;
3772         r.out.type = &type;
3773         r.out.data = data;
3774         r.out.data_size = &data_size;
3775         r.out.data_length = &data_length;
3776
3777         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3778
3779         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3780         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3781                 *r.in.data_size = *r.out.data_size;
3782                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3783                 r.in.data = data;
3784                 r.out.data = data;
3785                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3786         }
3787         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3788
3789         if (type_p) {
3790                 *type_p = *r.out.type;
3791         }
3792         if (data_size_p) {
3793                 *data_size_p = *r.out.data_size;
3794         }
3795         if (data_length_p) {
3796                 *data_length_p = *r.out.data_length;
3797         }
3798         if (data_p) {
3799                 *data_p = r.out.data;
3800         }
3801
3802         return true;
3803 }
3804
3805 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3806                                           struct dcerpc_binding_handle *b,
3807                                           struct policy_handle *handle,
3808                                           const char *printer_name,
3809                                           const char *key_name,
3810                                           const char *value_name,
3811                                           enum winreg_Type *w_type,
3812                                           uint32_t *w_size,
3813                                           uint32_t *w_length,
3814                                           uint8_t **w_data)
3815 {
3816         const char *printer_key;
3817         struct policy_handle key_handle;
3818
3819         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3820                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
3821
3822         torture_assert(tctx,
3823                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
3824
3825         torture_assert(tctx,
3826                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3827
3828         torture_assert(tctx,
3829                 test_winreg_CloseKey(tctx, b, &key_handle), "");
3830
3831         return true;
3832 }
3833
3834 static bool test_GetForm_winreg(struct torture_context *tctx,
3835                                 struct dcerpc_binding_handle *b,
3836                                 struct policy_handle *handle,
3837                                 const char *key_name,
3838                                 const char *form_name,
3839                                 enum winreg_Type *w_type,
3840                                 uint32_t *w_size,
3841                                 uint32_t *w_length,
3842                                 uint8_t **w_data)
3843 {
3844         struct policy_handle key_handle;
3845
3846         torture_assert(tctx,
3847                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
3848
3849         torture_assert(tctx,
3850                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
3851
3852         torture_assert(tctx,
3853                 test_winreg_CloseKey(tctx, b, &key_handle), "");
3854
3855         return true;
3856 }
3857
3858 static bool test_winreg_symbolic_link(struct torture_context *tctx,
3859                                       struct dcerpc_binding_handle *b,
3860                                       struct policy_handle *handle,
3861                                       const char *symlink_keyname,
3862                                       const char *symlink_destination)
3863 {
3864         /* check if the first key is a symlink to the second key */
3865
3866         enum winreg_Type w_type;
3867         uint32_t w_size;
3868         uint32_t w_length;
3869         uint8_t *w_data;
3870         struct policy_handle key_handle;
3871         DATA_BLOB blob;
3872         const char *str;
3873
3874         if (torture_setting_bool(tctx, "samba3", false)) {
3875                 torture_skip(tctx, "skip winreg symlink test against samba");
3876         }
3877
3878         torture_assert(tctx,
3879                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
3880                         "failed to open key link");
3881
3882         torture_assert(tctx,
3883                 test_winreg_QueryValue(tctx, b, &key_handle,
3884                                        "SymbolicLinkValue",
3885                                        &w_type, &w_size, &w_length, &w_data),
3886                 "failed to query for 'SymbolicLinkValue' attribute");
3887
3888         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
3889
3890         blob = data_blob(w_data, w_size);
3891         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3892
3893         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
3894
3895         torture_assert(tctx,
3896                 test_winreg_CloseKey(tctx, b, &key_handle),
3897                 "failed to close key link");
3898
3899         return true;
3900 }
3901
3902 static const char *strip_unc(const char *unc)
3903 {
3904         char *name;
3905
3906         if (!unc) {
3907                 return NULL;
3908         }
3909
3910         if (unc[0] == '\\' && unc[1] == '\\') {
3911                 unc +=2;
3912         }
3913
3914         name = strchr(unc, '\\');
3915         if (name) {
3916                 return name+1;
3917         }
3918
3919         return unc;
3920 }
3921
3922 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
3923                                        struct dcerpc_binding_handle *b,
3924                                        struct policy_handle *handle,
3925                                        const char *printer_name,
3926                                        struct dcerpc_binding_handle *winreg_handle,
3927                                        struct policy_handle *hive_handle)
3928 {
3929         union spoolss_PrinterInfo info;
3930         const char *keys[] = {
3931                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
3932                 TOP_LEVEL_PRINT_PRINTERS_KEY
3933         };
3934         int i;
3935         const char *printername, *sharename;
3936
3937         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
3938
3939         torture_assert(tctx,
3940                 test_GetPrinter_level(tctx, b, handle, 2, &info),
3941                 "failed to get printer info level 2");
3942
3943         printername = strip_unc(info.info2.printername);
3944         sharename = strip_unc(info.info2.sharename);
3945
3946 #define test_sz(key, wname, iname) \
3947 do {\
3948         DATA_BLOB blob;\
3949         const char *str;\
3950         enum winreg_Type w_type;\
3951         uint32_t w_size;\
3952         uint32_t w_length;\
3953         uint8_t *w_data;\
3954         torture_assert(tctx,\
3955                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
3956                                        &w_type, &w_size, &w_length, &w_data),\
3957                 "failed to query winreg");\
3958         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
3959         blob = data_blob(w_data, w_size);\
3960         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);\
3961         if (w_size == 2 && iname == NULL) {\
3962                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
3963         } else {\
3964                 torture_assert_str_equal(tctx, str, iname,\
3965                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
3966         }\
3967 } while(0);
3968
3969 #define test_dword(key, wname, iname) \
3970 do {\
3971         uint32_t value;\
3972         enum winreg_Type w_type;\
3973         uint32_t w_size;\
3974         uint32_t w_length;\
3975         uint8_t *w_data;\
3976         torture_assert(tctx,\
3977                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
3978                                        &w_type, &w_size, &w_length, &w_data),\
3979                 "failed to query winreg");\
3980         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
3981         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
3982         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
3983         value = IVAL(w_data, 0);\
3984         torture_assert_int_equal(tctx, value, iname,\
3985                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
3986 } while(0);
3987
3988 #define test_dm(key, wname, iname) \
3989 do {\
3990         DATA_BLOB blob;\
3991         struct spoolss_DeviceMode dm;\
3992         enum ndr_err_code ndr_err;\
3993         enum winreg_Type w_type;\
3994         uint32_t w_size;\
3995         uint32_t w_length;\
3996         uint8_t *w_data;\
3997         torture_assert(tctx,\
3998                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
3999                                        &w_type, &w_size, &w_length, &w_data),\
4000                 "failed to query winreg");\
4001         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4002         blob = data_blob(w_data, w_size);\
4003         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &dm,\
4004                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4005         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4006         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4007                 "dm unequal");\
4008 } while(0);
4009
4010 #define test_sd(key, wname, iname) \
4011 do {\
4012         DATA_BLOB blob;\
4013         struct security_descriptor sd;\
4014         enum ndr_err_code ndr_err;\
4015         enum winreg_Type w_type;\
4016         uint32_t w_size;\
4017         uint32_t w_length;\
4018         uint8_t *w_data;\
4019         torture_assert(tctx,\
4020                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4021                                        &w_type, &w_size, &w_length, &w_data),\
4022                 "failed to query winreg");\
4023         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4024         blob = data_blob(w_data, w_size);\
4025         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &sd,\
4026                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4027         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4028         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4029                 "sd unequal");\
4030 } while(0);
4031
4032
4033         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4034                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4035                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4036         {
4037                 torture_warning(tctx, "failed to check for winreg symlink");
4038         }
4039
4040
4041         for (i=0; i < ARRAY_SIZE(keys); i++) {
4042
4043                 const char *printer_key;
4044                 struct policy_handle key_handle;
4045
4046                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4047                         keys[i], printer_name);
4048
4049                 torture_assert(tctx,
4050                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4051
4052                 test_sz(keys[i], "Name", printername);
4053                 test_sz(keys[i], "Share Name", sharename);
4054                 test_sz(keys[i], "Port", info.info2.portname);
4055                 test_sz(keys[i], "Printer Driver", info.info2.drivername);
4056                 test_sz(keys[i], "Description", info.info2.comment);
4057                 test_sz(keys[i], "Location", info.info2.location);
4058                 test_sz(keys[i], "Separator File", info.info2.sepfile);
4059                 test_sz(keys[i], "Print Processor", info.info2.printprocessor);
4060                 test_sz(keys[i], "Datatype", info.info2.datatype);
4061                 test_sz(keys[i], "Parameters", info.info2.parameters);
4062                 /* winreg: 0, spoolss not */
4063 /*              test_dword(keys[i], "Attributes", info.info2.attributes); */
4064                 test_dword(keys[i], "Priority", info.info2.priority);
4065                 test_dword(keys[i], "Default Priority", info.info2.defaultpriority);
4066                 /* winreg: 60, spoolss: 0 */
4067 /*              test_dword(keys[i], "StartTime", info.info2.starttime); */
4068 /*              test_dword(keys[i], "UntilTime", info.info2.untiltime); */
4069                 /* winreg != spoolss */
4070 /*              test_dword(keys[i], "Status", info.info2.status); */
4071                 test_dm(keys[i], "Default DevMode", info.info2.devmode);
4072                 test_sd(keys[i], "Security", info.info2.secdesc);
4073
4074                 torture_assert(tctx,
4075                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4076         }
4077
4078 #undef test_sz
4079 #undef test_dword
4080 #undef test_dm
4081 #undef test_sd
4082
4083         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4084
4085         return true;
4086 }
4087
4088 static bool test_SetPrinterData(struct torture_context *tctx,
4089                                 struct dcerpc_binding_handle *b,
4090                                 struct policy_handle *handle,
4091                                 const char *value_name,
4092                                 enum winreg_Type type,
4093                                 uint8_t *data,
4094                                 uint32_t offered)
4095 {
4096         struct spoolss_SetPrinterData r;
4097
4098         r.in.handle = handle;
4099         r.in.value_name = value_name;
4100         r.in.type = type;
4101         r.in.data = data;
4102         r.in.offered = offered;
4103
4104         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4105                 r.in.value_name);
4106
4107         torture_assert_ntstatus_ok(tctx,
4108                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4109                 "SetPrinterData failed");
4110         torture_assert_werr_ok(tctx, r.out.result,
4111                 "SetPrinterData failed");
4112
4113         return true;
4114 }
4115
4116 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4117                                        struct dcerpc_binding_handle *b,
4118                                        struct policy_handle *handle,
4119                                        const char *printer_name,
4120                                        struct dcerpc_binding_handle *winreg_handle,
4121                                        struct policy_handle *hive_handle)
4122 {
4123         const char *values[] = {
4124                 "spootyfoot",
4125                 "spooty\\foot",
4126 #if 0
4127         /* FIXME: not working with s3 atm. */
4128                 "spooty,foot",
4129                 "spooty,fo,ot",
4130 #endif
4131                 "spooty foot",
4132 #if 0
4133         /* FIXME: not working with s3 atm. */
4134                 "spooty\\fo,ot",
4135                 "spooty,fo\\ot"
4136 #endif
4137         };
4138         int i;
4139
4140         for (i=0; i < ARRAY_SIZE(values); i++) {
4141
4142                 enum winreg_Type type;
4143                 DATA_BLOB blob;
4144                 uint8_t *data;
4145                 uint32_t needed;
4146
4147                 torture_assert(tctx,
4148                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4149                                           "REG_SZ", "dog", &type, &blob), "");
4150
4151                 torture_assert(tctx,
4152                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4153                         "SetPrinterData failed");
4154
4155                 torture_assert(tctx,
4156                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4157                         "GetPrinterData failed");
4158
4159                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4160                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4161                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4162
4163                 if (winreg_handle && hive_handle) {
4164
4165                         enum winreg_Type w_type;
4166                         uint32_t w_size;
4167                         uint32_t w_length;
4168                         uint8_t *w_data;
4169
4170                         torture_assert(tctx,
4171                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4172                                         printer_name, "PrinterDriverData", values[i],
4173                                         &w_type, &w_size, &w_length, &w_data), "");
4174
4175                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4176                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4177                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4178                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4179                 }
4180
4181                 torture_assert(tctx,
4182                         test_DeletePrinterData(tctx, b, handle, values[i]),
4183                         "DeletePrinterData failed");
4184         }
4185
4186         return true;
4187 }
4188
4189
4190 static bool test_EnumPrinterKey(struct torture_context *tctx,
4191                                 struct dcerpc_binding_handle *b,
4192                                 struct policy_handle *handle,
4193                                 const char *key_name,
4194                                 const char ***array);
4195
4196 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4197                                   struct dcerpc_binding_handle *b,
4198                                   struct policy_handle *handle,
4199                                   const char *key_name,
4200                                   const char *value_name,
4201                                   enum winreg_Type type,
4202                                   uint8_t *data,
4203                                   uint32_t offered)
4204 {
4205         NTSTATUS status;
4206         struct spoolss_SetPrinterDataEx r;
4207
4208         r.in.handle = handle;
4209         r.in.key_name = key_name;
4210         r.in.value_name = value_name;
4211         r.in.type = type;
4212         r.in.data = data;
4213         r.in.offered = offered;
4214
4215         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4216                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4217
4218         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4219
4220         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4221         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4222
4223         return true;
4224 }
4225
4226 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4227                                          struct dcerpc_pipe *p,
4228                                          struct policy_handle *handle,
4229                                          const char *printername,
4230                                          struct dcerpc_binding_handle *winreg_handle,
4231                                          struct policy_handle *hive_handle)
4232 {
4233         struct dcerpc_binding_handle *b = p->binding_handle;
4234         const char *value_name = "dog";
4235         const char *keys[] = {
4236                 "torturedataex",
4237                 "torture data ex",
4238 #if 0
4239         /* FIXME: not working with s3 atm. */
4240                 "torturedataex_with_subkey\\subkey",
4241                 "torturedataex_with_subkey\\subkey:0",
4242                 "torturedataex_with_subkey\\subkey:1",
4243                 "torturedataex_with_subkey\\subkey\\subsubkey",
4244                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4245                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4246 #endif
4247                 "torture,data",
4248 #if 0
4249         /* FIXME: not working with s3 atm. */
4250
4251                 "torture,data,ex",
4252                 "torture,data\\ex",
4253                 "torture\\data,ex"
4254 #endif
4255         };
4256         enum winreg_Type types[] = {
4257                 REG_SZ,
4258                 REG_MULTI_SZ,
4259                 REG_DWORD,
4260                 REG_BINARY
4261         };
4262         const char *str = "abcdefghijklmnopqrstuvwxzy";
4263         int i, t, s;
4264
4265
4266         for (i=0; i < ARRAY_SIZE(keys); i++) {
4267         for (t=0; t < ARRAY_SIZE(types); t++) {
4268         for (s=0; s < strlen(str); s++) {
4269
4270                 char *c;
4271                 const char *key;
4272                 enum winreg_Type type;
4273                 const char *string = talloc_strndup(tctx, str, s);
4274                 DATA_BLOB blob = data_blob_string_const(string);
4275                 const char **subkeys;
4276                 DATA_BLOB data;
4277                 uint8_t *data_out;
4278                 uint32_t needed, offered = 0;
4279                 uint32_t ecount;
4280                 struct spoolss_PrinterEnumValues *einfo;
4281
4282                 if (types[t] == REG_DWORD) {
4283                         s = 0xffff;
4284                 }
4285
4286                 if (torture_setting_bool(tctx, "samba3", false)) {
4287                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
4288                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4289                                 continue;
4290                         }
4291                 }
4292
4293                 switch (types[t]) {
4294                 case REG_BINARY:
4295                         data = blob;
4296                         offered = blob.length;
4297                         break;
4298                 case REG_DWORD:
4299                         data = data_blob_talloc(tctx, NULL, 4);
4300                         SIVAL(data.data, 0, 0x12345678);
4301                         offered = 4;
4302                         break;
4303                 case REG_SZ:
4304                         torture_assert(tctx,
4305                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4306                                                   "REG_SZ", string, &type, &data), "");
4307                         offered = data.length;
4308                         /*strlen_m_term(data.string)*2;*/
4309                         break;
4310                 case REG_MULTI_SZ:
4311                         torture_assert(tctx,
4312                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4313                                                   "REG_SZ", string, &type, &data), "");
4314                         torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
4315                         memset(&data.data[data.length - 2], '\0', 2);
4316                         offered = data.length;
4317                         break;
4318                 default:
4319                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4320                 }
4321
4322                 torture_assert(tctx,
4323                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4324                         "failed to call SetPrinterDataEx");
4325
4326                 torture_assert(tctx,
4327                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4328                         "failed to call GetPrinterDataEx");
4329
4330                 torture_assert(tctx,
4331                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4332                         "failed to call EnumPrinterDataEx");
4333
4334                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4335                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4336                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4337
4338                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4339                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4340                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4341                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4342                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4343                 if (einfo[0].data_length > 0) {
4344                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4345                 }
4346
4347                 if (winreg_handle && hive_handle) {
4348                         enum winreg_Type w_type;
4349                         uint32_t w_size;
4350                         uint32_t w_length;
4351                         uint8_t *w_data;
4352
4353                         torture_assert(tctx,
4354                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4355                                         printername, keys[i], value_name,
4356                                         &w_type, &w_size, &w_length, &w_data), "");
4357
4358                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4359                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4360                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4361                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4362                 }
4363
4364                 key = talloc_strdup(tctx, keys[i]);
4365
4366                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4367                         return false;
4368                 }
4369
4370                 c = strchr(key, '\\');
4371                 if (c) {
4372                         int k;
4373
4374                         /* we have subkeys */
4375
4376                         *c = 0;
4377
4378                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4379                                 return false;
4380                         }
4381
4382                         for (k=0; subkeys && subkeys[k]; k++) {
4383
4384                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4385
4386                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4387                                         return false;
4388                                 }
4389                         }
4390
4391                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4392                                 return false;
4393                         }
4394
4395                 } else {
4396                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4397                                 return false;
4398                         }
4399                 }
4400         }
4401         }
4402         }
4403
4404         return true;
4405 }
4406
4407 static bool test_PrinterData_winreg(struct torture_context *tctx,
4408                                     struct dcerpc_pipe *p,
4409                                     struct policy_handle *handle,
4410                                     const char *printer_name)
4411 {
4412         struct dcerpc_binding_handle *b = p->binding_handle;
4413         struct dcerpc_pipe *p2;
4414         bool ret = true;
4415         struct policy_handle hive_handle;
4416         struct dcerpc_binding_handle *b2;
4417
4418         torture_assert_ntstatus_ok(tctx,
4419                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4420                 "could not open winreg pipe");
4421         b2 = p2->binding_handle;
4422
4423         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4424
4425         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4426         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4427
4428         test_winreg_CloseKey(tctx, b2, &hive_handle);
4429
4430         talloc_free(p2);
4431
4432         return ret;
4433 }
4434
4435 static bool test_Forms_winreg(struct torture_context *tctx,
4436                               struct dcerpc_binding_handle *b,
4437                               struct policy_handle *handle,
4438                               bool print_server,
4439                               const char *printer_name)
4440 {
4441         struct dcerpc_pipe *p2;
4442         bool ret = true;
4443         struct policy_handle hive_handle;
4444         struct dcerpc_binding_handle *b2;
4445
4446         torture_assert_ntstatus_ok(tctx,
4447                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4448                 "could not open winreg pipe");
4449         b2 = p2->binding_handle;
4450
4451         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4452
4453         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4454
4455         test_winreg_CloseKey(tctx, b2, &hive_handle);
4456
4457         talloc_free(p2);
4458
4459         return ret;
4460 }
4461
4462 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
4463                                     struct dcerpc_pipe *p,
4464                                     struct policy_handle *handle,
4465                                     const char *printer_name)
4466 {
4467         struct dcerpc_binding_handle *b = p->binding_handle;
4468         struct dcerpc_pipe *p2;
4469         bool ret = true;
4470         struct policy_handle hive_handle;
4471         struct dcerpc_binding_handle *b2;
4472
4473         torture_assert_ntstatus_ok(tctx,
4474                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4475                 "could not open winreg pipe");
4476         b2 = p2->binding_handle;
4477
4478         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4479
4480         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
4481
4482         test_winreg_CloseKey(tctx, b2, &hive_handle);
4483
4484         talloc_free(p2);
4485
4486         return ret;
4487 }
4488
4489 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
4490                                          struct dcerpc_binding_handle *b,
4491                                          struct policy_handle *handle,
4492                                          uint32_t *change_id)
4493 {
4494         enum winreg_Type type;
4495         uint8_t *data;
4496         uint32_t needed;
4497
4498         torture_assert(tctx,
4499                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
4500                 "failed to call GetPrinterData");
4501
4502         torture_assert(tctx, type == REG_DWORD, "unexpected type");
4503         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4504
4505         *change_id = IVAL(data, 0);
4506
4507         return true;
4508 }
4509
4510 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
4511                                            struct dcerpc_pipe *p,
4512                                            struct policy_handle *handle,
4513                                            uint32_t *change_id)
4514 {
4515         enum winreg_Type type;
4516         uint8_t *data;
4517         uint32_t needed;
4518
4519         torture_assert(tctx,
4520                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
4521                 "failed to call GetPrinterData");
4522
4523         torture_assert(tctx, type == REG_DWORD, "unexpected type");
4524         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4525
4526         *change_id = IVAL(data, 0);
4527
4528         return true;
4529 }
4530
4531 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
4532                                          struct dcerpc_binding_handle *b,
4533                                          struct policy_handle *handle,
4534                                          uint32_t *change_id)
4535 {
4536         union spoolss_PrinterInfo info;
4537
4538         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
4539                 "failed to query Printer level 0");
4540
4541         *change_id = info.info0.change_id;
4542
4543         return true;
4544 }
4545
4546 static bool test_ChangeID(struct torture_context *tctx,
4547                           struct dcerpc_pipe *p,
4548                           struct policy_handle *handle)
4549 {
4550         uint32_t change_id, change_id_ex, change_id_info;
4551         uint32_t change_id2, change_id_ex2, change_id_info2;
4552         union spoolss_PrinterInfo info;
4553         const char *comment;
4554         struct dcerpc_binding_handle *b = p->binding_handle;
4555
4556         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
4557
4558         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4559                 "failed to query for ChangeID");
4560         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4561                 "failed to query for ChangeID");
4562         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4563                 "failed to query for ChangeID");
4564
4565         torture_assert_int_equal(tctx, change_id, change_id_ex,
4566                 "change_ids should all be equal");
4567         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4568                 "change_ids should all be equal");
4569
4570
4571         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
4572
4573         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4574                 "failed to query for ChangeID");
4575         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4576                 "failed to query Printer level 2");
4577         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4578                 "failed to query for ChangeID");
4579         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4580                 "failed to query for ChangeID");
4581         torture_assert_int_equal(tctx, change_id, change_id_ex,
4582                 "change_id should not have changed");
4583         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4584                 "change_id should not have changed");
4585
4586
4587         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
4588
4589         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4590                 "failed to query for ChangeID");
4591         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4592                 "failed to query for ChangeID");
4593         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4594                 "failed to query for ChangeID");
4595         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4596                 "failed to query Printer level 2");
4597         comment = talloc_strdup(tctx, info.info2.comment);
4598
4599         {
4600                 struct spoolss_SetPrinterInfoCtr info_ctr;
4601                 struct spoolss_DevmodeContainer devmode_ctr;
4602                 struct sec_desc_buf secdesc_ctr;
4603                 union spoolss_SetPrinterInfo sinfo;
4604
4605                 ZERO_STRUCT(info_ctr);
4606                 ZERO_STRUCT(devmode_ctr);
4607                 ZERO_STRUCT(secdesc_ctr);
4608
4609
4610                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4611                 sinfo.info2->comment    = "torture_comment";
4612
4613                 info_ctr.level = 2;
4614                 info_ctr.info = sinfo;
4615
4616                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4617                         "failed to call SetPrinter");
4618
4619                 sinfo.info2->comment    = comment;
4620
4621                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4622                         "failed to call SetPrinter");
4623
4624         }
4625
4626         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
4627                 "failed to query for ChangeID");
4628         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
4629                 "failed to query for ChangeID");
4630         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
4631                 "failed to query for ChangeID");
4632
4633         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
4634                 "change_ids should all be equal");
4635         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
4636                 "change_ids should all be equal");
4637
4638         torture_assert(tctx, (change_id < change_id2),
4639                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4640                 change_id2, change_id));
4641         torture_assert(tctx, (change_id_ex < change_id_ex2),
4642                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4643                 change_id_ex2, change_id_ex));
4644         torture_assert(tctx, (change_id_info < change_id_info2),
4645                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4646                 change_id_info2, change_id_info));
4647
4648         torture_comment(tctx, "ChangeID tests succeeded\n\n");
4649
4650         return true;
4651 }
4652
4653 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
4654                                        struct dcerpc_pipe *p,
4655                                        struct policy_handle *handle)
4656 {
4657         NTSTATUS status;
4658         struct dcerpc_binding *b;
4659         struct dcerpc_pipe *p2;
4660         struct spoolss_ClosePrinter cp;
4661
4662         /* only makes sense on SMB */
4663         if (p->conn->transport.transport != NCACN_NP) {
4664                 return true;
4665         }
4666
4667         torture_comment(tctx, "Testing close on secondary pipe\n");
4668
4669         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
4670         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
4671
4672         status = dcerpc_secondary_connection(p, &p2, b);
4673         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
4674
4675         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
4676         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
4677
4678         cp.in.handle = handle;
4679         cp.out.handle = handle;
4680
4681         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
4682         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
4683                         "ERROR: Allowed close on secondary connection");
4684
4685         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
4686                                  "Unexpected fault code");
4687
4688         talloc_free(p2);
4689
4690         return true;
4691 }
4692
4693 static bool test_OpenPrinter_badname(struct torture_context *tctx,
4694                                      struct dcerpc_binding_handle *b, const char *name)
4695 {
4696         NTSTATUS status;
4697         struct spoolss_OpenPrinter op;
4698         struct spoolss_OpenPrinterEx opEx;
4699         struct policy_handle handle;
4700         bool ret = true;
4701
4702         op.in.printername       = name;
4703         op.in.datatype          = NULL;
4704         op.in.devmode_ctr.devmode= NULL;
4705         op.in.access_mask       = 0;
4706         op.out.handle           = &handle;
4707
4708         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
4709
4710         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
4711         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4712         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4713                 "unexpected result");
4714
4715         if (W_ERROR_IS_OK(op.out.result)) {
4716                 ret &=test_ClosePrinter(tctx, b, &handle);
4717         }
4718
4719         opEx.in.printername             = name;
4720         opEx.in.datatype                = NULL;
4721         opEx.in.devmode_ctr.devmode     = NULL;
4722         opEx.in.access_mask             = 0;
4723         opEx.in.level                   = 1;
4724         opEx.in.userlevel.level1        = NULL;
4725         opEx.out.handle                 = &handle;
4726
4727         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4728
4729         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
4730         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4731         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4732                 "unexpected result");
4733
4734         if (W_ERROR_IS_OK(opEx.out.result)) {
4735                 ret &=test_ClosePrinter(tctx, b, &handle);
4736         }
4737
4738         return ret;
4739 }
4740
4741 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
4742                                           struct dcerpc_binding_handle *b,
4743                                           const char *server_name)
4744 {
4745         const char *badnames[] = {
4746                 "__INVALID_PRINTER__",
4747                 "\\\\__INVALID_HOST__",
4748                 "",
4749                 "\\\\\\",
4750                 "\\\\\\__INVALID_PRINTER__"
4751         };
4752         const char *badname;
4753         int i;
4754
4755         for (i=0; i < ARRAY_SIZE(badnames); i++) {
4756                 torture_assert(tctx,
4757                         test_OpenPrinter_badname(tctx, b, badnames[i]),
4758                         "");
4759         }
4760
4761         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
4762         torture_assert(tctx,
4763                 test_OpenPrinter_badname(tctx, b, badname),
4764                 "");
4765
4766         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
4767         torture_assert(tctx,
4768                 test_OpenPrinter_badname(tctx, b, badname),
4769                 "");
4770
4771         return true;
4772 }
4773
4774 static bool test_OpenPrinter(struct torture_context *tctx,
4775                              struct dcerpc_pipe *p,
4776                              const char *name,
4777                              const char *environment)
4778 {
4779         NTSTATUS status;
4780         struct spoolss_OpenPrinter r;
4781         struct policy_handle handle;
4782         bool ret = true;
4783         struct dcerpc_binding_handle *b = p->binding_handle;
4784
4785         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4786         r.in.datatype           = NULL;
4787         r.in.devmode_ctr.devmode= NULL;
4788         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4789         r.out.handle            = &handle;
4790
4791         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4792
4793         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
4794
4795         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4796
4797         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4798
4799         if (!test_GetPrinter(tctx, b, &handle, environment)) {
4800                 ret = false;
4801         }
4802
4803         if (!torture_setting_bool(tctx, "samba3", false)) {
4804                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4805                         ret = false;
4806                 }
4807         }
4808
4809         if (!test_ClosePrinter(tctx, b, &handle)) {
4810                 ret = false;
4811         }
4812
4813         return ret;
4814 }
4815
4816 static bool call_OpenPrinterEx(struct torture_context *tctx,
4817                                struct dcerpc_pipe *p,
4818                                const char *name,
4819                                struct spoolss_DeviceMode *devmode,
4820                                struct policy_handle *handle)
4821 {
4822         struct spoolss_OpenPrinterEx r;
4823         struct spoolss_UserLevel1 userlevel1;
4824         NTSTATUS status;
4825         struct dcerpc_binding_handle *b = p->binding_handle;
4826
4827         if (name && name[0]) {
4828                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4829                                                    dcerpc_server_name(p), name);
4830         } else {
4831                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4832                                                    dcerpc_server_name(p));
4833         }
4834
4835         r.in.datatype           = NULL;
4836         r.in.devmode_ctr.devmode= devmode;
4837         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4838         r.in.level              = 1;
4839         r.in.userlevel.level1   = &userlevel1;
4840         r.out.handle = handle;
4841
4842         userlevel1.size = 1234;
4843         userlevel1.client = "hello";
4844         userlevel1.user = "spottyfoot!";
4845         userlevel1.build = 1;
4846         userlevel1.major = 2;
4847         userlevel1.minor = 3;
4848         userlevel1.processor = 4;
4849
4850         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4851
4852         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
4853
4854         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4855
4856         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4857
4858         return true;
4859 }
4860
4861 static bool test_printer_rename(struct torture_context *tctx,
4862                                 struct dcerpc_pipe *p,
4863                                 struct policy_handle *handle,
4864                                 const char *name)
4865 {
4866         bool ret = true;
4867         union spoolss_PrinterInfo info;
4868         union spoolss_SetPrinterInfo sinfo;
4869         struct spoolss_SetPrinterInfoCtr info_ctr;
4870         struct spoolss_DevmodeContainer devmode_ctr;
4871         struct sec_desc_buf secdesc_ctr;
4872         const char *printer_name;
4873         const char *printer_name_orig;
4874         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4875         struct policy_handle new_handle;
4876         const char *q;
4877         struct dcerpc_binding_handle *b = p->binding_handle;
4878
4879         ZERO_STRUCT(devmode_ctr);
4880         ZERO_STRUCT(secdesc_ctr);
4881
4882         torture_comment(tctx, "Testing Printer rename operations\n");
4883
4884         torture_assert(tctx,
4885                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4886                 "failed to call GetPrinter level 2");
4887
4888         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4889
4890         q = strrchr(info.info2.printername, '\\');
4891         if (q) {
4892                 torture_warning(tctx,
4893                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4894         }
4895
4896         torture_assert(tctx,
4897                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4898
4899         sinfo.info2->printername = printer_name_new;
4900
4901         info_ctr.level = 2;
4902         info_ctr.info = sinfo;
4903
4904         torture_assert(tctx,
4905                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4906                 "failed to call SetPrinter level 2");
4907
4908         torture_assert(tctx,
4909                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4910                 "failed to call GetPrinter level 2");
4911
4912         printer_name = talloc_strdup(tctx, info.info2.printername);
4913
4914         q = strrchr(info.info2.printername, '\\');
4915         if (q) {
4916                 torture_warning(tctx,
4917                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4918                 q++;
4919                 printer_name = q;
4920         }
4921
4922         torture_assert_str_equal(tctx, printer_name, printer_name_new,
4923                 "new printer name was not set");
4924
4925         /* samba currently cannot fully rename printers */
4926         if (!torture_setting_bool(tctx, "samba3", false)) {
4927                 torture_assert(tctx,
4928                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
4929                         "still can open printer with oldname after rename");
4930         } else {
4931                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
4932         }
4933
4934         torture_assert(tctx,
4935                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4936                 "failed to open printer with new name");
4937
4938         torture_assert(tctx,
4939                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
4940                 "failed to call GetPrinter level 2");
4941
4942         /* FIXME: we openend with servername! */
4943         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4944                 dcerpc_server_name(p), printer_name_new);
4945
4946         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4947                 "new printer name was not set");
4948
4949         torture_assert(tctx,
4950                 test_ClosePrinter(tctx, b, &new_handle),
4951                 "failed to close printer");
4952
4953         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4954
4955         return ret;
4956 }
4957
4958
4959 static bool test_OpenPrinterEx(struct torture_context *tctx,
4960                                struct dcerpc_pipe *p,
4961                                const char *name,
4962                                const char *environment)
4963 {
4964         struct policy_handle handle;
4965         bool ret = true;
4966         struct dcerpc_binding_handle *b = p->binding_handle;
4967
4968         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4969                 return false;
4970         }
4971
4972         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
4973                 ret = false;
4974         }
4975
4976         if (!test_GetPrinter(tctx, b, &handle, environment)) {
4977                 ret = false;
4978         }
4979
4980         if (!test_EnumForms_all(tctx, b, &handle, false)) {
4981                 ret = false;
4982         }
4983
4984         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
4985                 ret = false;
4986         }
4987
4988         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
4989                 ret = false;
4990         }
4991
4992         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4993                 ret = false;
4994         }
4995
4996         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
4997                 ret = false;
4998         }
4999
5000         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5001                 ret = false;
5002         }
5003
5004         if (!test_printer_keys(tctx, b, &handle)) {
5005                 ret = false;
5006         }
5007
5008         if (!test_PausePrinter(tctx, b, &handle)) {
5009                 ret = false;
5010         }
5011
5012         if (!test_DoPrintTest(tctx, b, &handle)) {
5013                 ret = false;
5014         }
5015
5016         if (!test_ResumePrinter(tctx, b, &handle)) {
5017                 ret = false;
5018         }
5019
5020         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5021                 ret = false;
5022         }
5023
5024         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5025                 ret = false;
5026         }
5027
5028         if (!torture_setting_bool(tctx, "samba3", false)) {
5029                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5030                         ret = false;
5031                 }
5032         }
5033
5034         if (!test_ClosePrinter(tctx, b, &handle)) {
5035                 ret = false;
5036         }
5037
5038         return ret;
5039 }
5040
5041 static bool test_EnumPrinters_old(struct torture_context *tctx,
5042                                   struct dcerpc_pipe *p,
5043                                   const char *environment)
5044 {
5045         struct spoolss_EnumPrinters r;
5046         NTSTATUS status;
5047         uint16_t levels[] = {1, 2, 4, 5};
5048         int i;
5049         bool ret = true;
5050         struct dcerpc_binding_handle *b = p->binding_handle;
5051
5052         for (i=0;i<ARRAY_SIZE(levels);i++) {
5053                 union spoolss_PrinterInfo *info;
5054                 int j;
5055                 uint32_t needed;
5056                 uint32_t count;
5057
5058                 r.in.flags      = PRINTER_ENUM_LOCAL;
5059                 r.in.server     = "";
5060                 r.in.level      = levels[i];
5061                 r.in.buffer     = NULL;
5062                 r.in.offered    = 0;
5063                 r.out.needed    = &needed;
5064                 r.out.count     = &count;
5065                 r.out.info      = &info;
5066
5067                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5068
5069                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5070                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5071
5072                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5073                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5074                         r.in.buffer = &blob;
5075                         r.in.offered = needed;
5076                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5077                 }
5078
5079                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5080
5081                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5082
5083                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5084
5085                 if (!info) {
5086                         torture_comment(tctx, "No printers returned\n");
5087                         return true;
5088                 }
5089
5090                 for (j=0;j<count;j++) {
5091                         if (r.in.level == 1) {
5092                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5093                                 char *slash, *name;
5094                                 name = unc;
5095                                 if (unc[0] == '\\' && unc[1] == '\\') {
5096                                         unc +=2;
5097                                 }
5098                                 slash = strchr(unc, '\\');
5099                                 if (slash) {
5100                                         slash++;
5101                                         name = slash;
5102                                 }
5103                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
5104                                         ret = false;
5105                                 }
5106                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
5107                                         ret = false;
5108                                 }
5109                         }
5110                 }
5111         }
5112
5113         return ret;
5114 }
5115
5116 static bool test_GetPrinterDriver(struct torture_context *tctx,
5117                                   struct dcerpc_binding_handle *b,
5118                                   struct policy_handle *handle,
5119                                   const char *driver_name)
5120 {
5121         struct spoolss_GetPrinterDriver r;
5122         uint32_t needed;
5123
5124         r.in.handle = handle;
5125         r.in.architecture = "W32X86";
5126         r.in.level = 1;
5127         r.in.buffer = NULL;
5128         r.in.offered = 0;
5129         r.out.needed = &needed;
5130
5131         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5132
5133         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5134                 "failed to call GetPrinterDriver");
5135         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5136                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5137                 r.in.buffer = &blob;
5138                 r.in.offered = needed;
5139                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5140                         "failed to call GetPrinterDriver");
5141         }
5142
5143         torture_assert_werr_ok(tctx, r.out.result,
5144                 "failed to call GetPrinterDriver");
5145
5146         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5147
5148         return true;
5149 }
5150
5151 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5152                                    struct dcerpc_binding_handle *b,
5153                                    struct policy_handle *handle,
5154                                    const char *driver_name,
5155                                    const char *architecture)
5156 {
5157         struct spoolss_GetPrinterDriver2 r;
5158         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5159         uint32_t needed;
5160         uint32_t server_major_version;
5161         uint32_t server_minor_version;
5162         int i;
5163
5164         r.in.handle = handle;
5165         r.in.architecture = architecture;
5166         r.in.client_major_version = 3;
5167         r.in.client_minor_version = 0;
5168         r.out.needed = &needed;
5169         r.out.server_major_version = &server_major_version;
5170         r.out.server_minor_version = &server_minor_version;
5171
5172         for (i=0;i<ARRAY_SIZE(levels);i++) {
5173
5174                 r.in.buffer = NULL;
5175                 r.in.offered = 0;
5176                 r.in.level = levels[i];
5177
5178                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5179                         driver_name, r.in.level);
5180
5181                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5182                         "failed to call GetPrinterDriver2");
5183                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5184                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5185                         r.in.buffer = &blob;
5186                         r.in.offered = needed;
5187                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5188                                 "failed to call GetPrinterDriver2");
5189                 }
5190
5191                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5192                         switch (r.in.level) {
5193                         case 101:
5194                         case 8:
5195                                 continue;
5196                         default:
5197                                 break;
5198                         }
5199                 }
5200
5201                 torture_assert_werr_ok(tctx, r.out.result,
5202                         "failed to call GetPrinterDriver2");
5203
5204                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5205         }
5206
5207         return true;
5208 }
5209
5210 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
5211                                         struct dcerpc_pipe *p,
5212                                         const char *environment)
5213 {
5214         struct spoolss_EnumPrinterDrivers r;
5215         NTSTATUS status;
5216         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
5217         int i;
5218         struct dcerpc_binding_handle *b = p->binding_handle;
5219
5220         for (i=0;i<ARRAY_SIZE(levels);i++) {
5221
5222                 uint32_t needed;
5223                 uint32_t count;
5224                 union spoolss_DriverInfo *info;
5225
5226                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5227                 r.in.environment = environment;
5228                 r.in.level = levels[i];
5229                 r.in.buffer = NULL;
5230                 r.in.offered = 0;
5231                 r.out.needed = &needed;
5232                 r.out.count = &count;
5233                 r.out.info = &info;
5234
5235                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
5236
5237                 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
5238
5239                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
5240
5241                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5242                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5243                         r.in.buffer = &blob;
5244                         r.in.offered = needed;
5245                         status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
5246                 }
5247
5248                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
5249
5250                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
5251
5252                 if (!info) {
5253                         torture_comment(tctx, "No printer drivers returned\n");
5254                         break;
5255                 }
5256
5257                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5258         }
5259
5260         return true;
5261 }
5262
5263 static bool test_DeletePrinter(struct torture_context *tctx,
5264                                struct dcerpc_binding_handle *b,
5265                                struct policy_handle *handle)
5266 {
5267         struct spoolss_DeletePrinter r;
5268
5269         torture_comment(tctx, "Testing DeletePrinter\n");
5270
5271         r.in.handle = handle;
5272
5273         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
5274                 "failed to delete printer");
5275         torture_assert_werr_ok(tctx, r.out.result,
5276                 "failed to delete printer");
5277
5278         return true;
5279 }
5280
5281 static bool test_EnumPrinters_findname(struct torture_context *tctx,
5282                                        struct dcerpc_binding_handle *b,
5283                                        uint32_t flags,
5284                                        uint32_t level,
5285                                        const char *name,
5286                                        bool *found)
5287 {
5288         struct spoolss_EnumPrinters e;
5289         uint32_t count;
5290         union spoolss_PrinterInfo *info;
5291         uint32_t needed;
5292         int i;
5293
5294         *found = false;
5295
5296         e.in.flags = flags;
5297         e.in.server = NULL;
5298         e.in.level = level;
5299         e.in.buffer = NULL;
5300         e.in.offered = 0;
5301         e.out.count = &count;
5302         e.out.info = &info;
5303         e.out.needed = &needed;
5304
5305         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5306                 "failed to enum printers");
5307
5308         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
5309                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5310                 e.in.buffer = &blob;
5311                 e.in.offered = needed;
5312
5313                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5314                         "failed to enum printers");
5315         }
5316
5317         torture_assert_werr_ok(tctx, e.out.result,
5318                 "failed to enum printers");
5319
5320         for (i=0; i < count; i++) {
5321
5322                 const char *current = NULL;
5323                 const char *q;
5324
5325                 switch (level) {
5326                 case 1:
5327                         current = info[i].info1.name;
5328                         break;
5329                 }
5330
5331                 if (strequal(current, name)) {
5332                         *found = true;
5333                         break;
5334                 }
5335
5336                 q = strrchr(current, '\\');
5337                 if (q) {
5338                         if (!e.in.server) {
5339                                 torture_warning(tctx,
5340                                         "server returns printername %s incl. servername although we did not set servername", current);
5341                         }
5342                         q++;
5343                         if (strequal(q, name)) {
5344                                 *found = true;
5345                                 break;
5346                         }
5347                 }
5348         }
5349
5350         return true;
5351 }
5352
5353 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5354                                       struct dcerpc_pipe *p,
5355                                       const char *printername,
5356                                       bool ex)
5357 {
5358         WERROR result;
5359         struct spoolss_AddPrinter r;
5360         struct spoolss_AddPrinterEx rex;
5361         struct spoolss_SetPrinterInfoCtr info_ctr;
5362         struct spoolss_SetPrinterInfo1 info1;
5363         struct spoolss_DevmodeContainer devmode_ctr;
5364         struct sec_desc_buf secdesc_ctr;
5365         struct spoolss_UserLevelCtr userlevel_ctr;
5366         struct policy_handle handle;
5367         bool found = false;
5368         struct dcerpc_binding_handle *b = p->binding_handle;
5369
5370         ZERO_STRUCT(devmode_ctr);
5371         ZERO_STRUCT(secdesc_ctr);
5372         ZERO_STRUCT(userlevel_ctr);
5373         ZERO_STRUCT(info1);
5374
5375         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5376
5377         /* try to add printer to wellknown printer list (level 1) */
5378
5379         userlevel_ctr.level = 1;
5380
5381         info_ctr.info.info1 = &info1;
5382         info_ctr.level = 1;
5383
5384         rex.in.server = NULL;
5385         rex.in.info_ctr = &info_ctr;
5386         rex.in.devmode_ctr = &devmode_ctr;
5387         rex.in.secdesc_ctr = &secdesc_ctr;
5388         rex.in.userlevel_ctr = &userlevel_ctr;
5389         rex.out.handle = &handle;
5390
5391         r.in.server = NULL;
5392         r.in.info_ctr = &info_ctr;
5393         r.in.devmode_ctr = &devmode_ctr;
5394         r.in.secdesc_ctr = &secdesc_ctr;
5395         r.out.handle = &handle;
5396
5397         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5398                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5399                 "failed to add printer");
5400         result = ex ? rex.out.result : r.out.result;
5401         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5402                 "unexpected result code");
5403
5404         info1.name = printername;
5405         info1.flags = PRINTER_ATTRIBUTE_SHARED;
5406
5407         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5408                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5409                 "failed to add printer");
5410         result = ex ? rex.out.result : r.out.result;
5411         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5412                 "unexpected result code");
5413
5414         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5415            better do a real check to see the printer is really there */
5416
5417         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5418                                                         PRINTER_ENUM_NETWORK, 1,
5419                                                         printername,
5420                                                         &found),
5421                         "failed to enum printers");
5422
5423         torture_assert(tctx, found, "failed to find newly added printer");
5424
5425         info1.flags = 0;
5426
5427         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5428                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5429                 "failed to add printer");
5430         result = ex ? rex.out.result : r.out.result;
5431         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5432                 "unexpected result code");
5433
5434         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5435            better do a real check to see the printer has really been removed
5436            from the well known printer list */
5437
5438         found = false;
5439
5440         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5441                                                         PRINTER_ENUM_NETWORK, 1,
5442                                                         printername,
5443                                                         &found),
5444                         "failed to enum printers");
5445 #if 0
5446         torture_assert(tctx, !found, "printer still in well known printer list");
5447 #endif
5448         return true;
5449 }
5450
5451 static bool test_AddPrinter_normal(struct torture_context *tctx,
5452                                    struct dcerpc_pipe *p,
5453                                    struct policy_handle *handle_p,
5454                                    const char *printername,
5455                                    const char *drivername,
5456                                    const char *portname,
5457                                    bool ex)
5458 {
5459         WERROR result;
5460         struct spoolss_AddPrinter r;
5461         struct spoolss_AddPrinterEx rex;
5462         struct spoolss_SetPrinterInfoCtr info_ctr;
5463         struct spoolss_SetPrinterInfo2 info2;
5464         struct spoolss_DevmodeContainer devmode_ctr;
5465         struct sec_desc_buf secdesc_ctr;
5466         struct spoolss_UserLevelCtr userlevel_ctr;
5467         struct policy_handle handle;
5468         bool found = false;
5469         bool existing_printer_deleted = false;
5470         struct dcerpc_binding_handle *b = p->binding_handle;
5471
5472         ZERO_STRUCT(devmode_ctr);
5473         ZERO_STRUCT(secdesc_ctr);
5474         ZERO_STRUCT(userlevel_ctr);
5475
5476         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5477
5478         userlevel_ctr.level = 1;
5479
5480         rex.in.server = NULL;
5481         rex.in.info_ctr = &info_ctr;
5482         rex.in.devmode_ctr = &devmode_ctr;
5483         rex.in.secdesc_ctr = &secdesc_ctr;
5484         rex.in.userlevel_ctr = &userlevel_ctr;
5485         rex.out.handle = &handle;
5486
5487         r.in.server = NULL;
5488         r.in.info_ctr = &info_ctr;
5489         r.in.devmode_ctr = &devmode_ctr;
5490         r.in.secdesc_ctr = &secdesc_ctr;
5491         r.out.handle = &handle;
5492
5493  again:
5494
5495         /* try to add printer to printer list (level 2) */
5496
5497         ZERO_STRUCT(info2);
5498
5499         info_ctr.info.info2 = &info2;
5500         info_ctr.level = 2;
5501
5502         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5503                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5504                 "failed to add printer");
5505         result = ex ? rex.out.result : r.out.result;
5506         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5507                 "unexpected result code");
5508
5509         info2.printername = printername;
5510
5511         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5512                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5513                 "failed to add printer");
5514         result = ex ? rex.out.result : r.out.result;
5515
5516         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5517                 struct policy_handle printer_handle;
5518
5519                 if (existing_printer_deleted) {
5520                         torture_fail(tctx, "already deleted printer still existing?");
5521                 }
5522
5523                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5524                         "failed to open printer handle");
5525
5526                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5527                         "failed to delete printer");
5528
5529                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
5530                         "failed to close server handle");
5531
5532                 existing_printer_deleted = true;
5533
5534                 goto again;
5535         }
5536
5537         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
5538                 "unexpected result code");
5539
5540         info2.portname = portname;
5541
5542         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5543                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5544                 "failed to add printer");
5545         result = ex ? rex.out.result : r.out.result;
5546         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
5547                 "unexpected result code");
5548
5549         info2.drivername = drivername;
5550
5551         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5552                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5553                 "failed to add printer");
5554         result = ex ? rex.out.result : r.out.result;
5555
5556         /* w2k8r2 allows to add printer w/o defining printprocessor */
5557
5558         if (!W_ERROR_IS_OK(result)) {
5559                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
5560                         "unexpected result code");
5561
5562                 info2.printprocessor = "winprint";
5563
5564                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5565                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5566                         "failed to add printer");
5567                 result = ex ? rex.out.result : r.out.result;
5568                 torture_assert_werr_ok(tctx, result,
5569                         "failed to add printer");
5570         }
5571
5572         *handle_p = handle;
5573
5574         /* we are paranoid, really check if the printer is there now */
5575
5576         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5577                                                         PRINTER_ENUM_LOCAL, 1,
5578                                                         printername,
5579                                                         &found),
5580                         "failed to enum printers");
5581         torture_assert(tctx, found, "failed to find newly added printer");
5582
5583         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5584                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5585                 "failed to add printer");
5586         result = ex ? rex.out.result : r.out.result;
5587         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5588                 "unexpected result code");
5589
5590         return true;
5591 }
5592
5593 static bool test_AddPrinterEx(struct torture_context *tctx,
5594                               struct dcerpc_pipe *p,
5595                               struct policy_handle *handle_p,
5596                               const char *printername,
5597                               const char *drivername,
5598                               const char *portname)
5599 {
5600         bool ret = true;
5601
5602         if (!torture_setting_bool(tctx, "samba3", false)) {
5603                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
5604                         torture_comment(tctx, "failed to add printer to well known list\n");
5605                         ret = false;
5606                 }
5607         }
5608
5609         if (!test_AddPrinter_normal(tctx, p, handle_p,
5610                                     printername, drivername, portname,
5611                                     true)) {
5612                 torture_comment(tctx, "failed to add printer to printer list\n");
5613                 ret = false;
5614         }
5615
5616         return ret;
5617 }
5618
5619 static bool test_AddPrinter(struct torture_context *tctx,
5620                             struct dcerpc_pipe *p,
5621                             struct policy_handle *handle_p,
5622                             const char *printername,
5623                             const char *drivername,
5624                             const char *portname)
5625 {
5626         bool ret = true;
5627
5628         if (!torture_setting_bool(tctx, "samba3", false)) {
5629                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
5630                         torture_comment(tctx, "failed to add printer to well known list\n");
5631                         ret = false;
5632                 }
5633         }
5634
5635         if (!test_AddPrinter_normal(tctx, p, handle_p,
5636                                     printername, drivername, portname,
5637                                     false)) {
5638                 torture_comment(tctx, "failed to add printer to printer list\n");
5639                 ret = false;
5640         }
5641
5642         return ret;
5643 }
5644
5645 static bool test_printer_info(struct torture_context *tctx,
5646                               struct dcerpc_binding_handle *b,
5647                               struct policy_handle *handle)
5648 {
5649         bool ret = true;
5650
5651         if (torture_setting_bool(tctx, "samba3", false)) {
5652                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
5653         }
5654
5655         if (!test_PrinterInfo(tctx, b, handle)) {
5656                 ret = false;
5657         }
5658
5659         if (!test_SetPrinter_errors(tctx, b, handle)) {
5660                 ret = false;
5661         }
5662
5663         return ret;
5664 }
5665
5666 static bool test_EnumPrinterKey(struct torture_context *tctx,
5667                                 struct dcerpc_binding_handle *b,
5668                                 struct policy_handle *handle,
5669                                 const char *key_name,
5670                                 const char ***array)
5671 {
5672         struct spoolss_EnumPrinterKey r;
5673         uint32_t needed = 0;
5674         union spoolss_KeyNames key_buffer;
5675         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5676         uint32_t _ndr_size;
5677         int i;
5678
5679         r.in.handle = handle;
5680         r.in.key_name = key_name;
5681         r.out.key_buffer = &key_buffer;
5682         r.out.needed = &needed;
5683         r.out._ndr_size = &_ndr_size;
5684
5685         for (i=0; i < ARRAY_SIZE(offered); i++) {
5686
5687                 if (offered[i] < 0 && needed) {
5688                         if (needed <= 4) {
5689                                 continue;
5690                         }
5691                         r.in.offered = needed + offered[i];
5692                 } else {
5693                         r.in.offered = offered[i];
5694                 }
5695
5696                 ZERO_STRUCT(key_buffer);
5697
5698                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
5699
5700                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5701                         "failed to call EnumPrinterKey");
5702                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5703
5704                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
5705                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5706                                         _ndr_size, r.in.offered/2));
5707
5708                         r.in.offered = needed;
5709                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5710                                 "failed to call EnumPrinterKey");
5711                 }
5712
5713                 if (offered[i] > 0) {
5714                         torture_assert_werr_ok(tctx, r.out.result,
5715                                 "failed to call EnumPrinterKey");
5716                 }
5717
5718                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5719                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5720                                 _ndr_size, r.in.offered/2));
5721
5722                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5723                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5724
5725                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5726                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5727
5728                 if (key_buffer.string_array) {
5729                         uint32_t calc_needed = 0;
5730                         int s;
5731                         for (s=0; key_buffer.string_array[s]; s++) {
5732                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5733                         }
5734                         if (!key_buffer.string_array[0]) {
5735                                 calc_needed += 2;
5736                         }
5737                         calc_needed += 2;
5738
5739                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5740                                 "EnumPrinterKey unexpected size");
5741                 }
5742         }
5743
5744         if (array) {
5745                 *array = key_buffer.string_array;
5746         }
5747
5748         return true;
5749 }
5750
5751 bool test_printer_keys(struct torture_context *tctx,
5752                        struct dcerpc_binding_handle *b,
5753                        struct policy_handle *handle)
5754 {
5755         const char **key_array = NULL;
5756         int i;
5757
5758         torture_comment(tctx, "Testing Printer Keys\n");
5759
5760         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
5761                 "failed to call test_EnumPrinterKey");
5762
5763         for (i=0; key_array && key_array[i]; i++) {
5764                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
5765                         "failed to call test_EnumPrinterKey");
5766         }
5767         for (i=0; key_array && key_array[i]; i++) {
5768                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
5769                         "failed to call test_EnumPrinterDataEx");
5770         }
5771
5772         torture_comment(tctx, "Printer Keys test succeeded\n\n");
5773
5774         return true;
5775 }
5776
5777 static bool test_one_printer(struct torture_context *tctx,
5778                              struct dcerpc_pipe *p,
5779                              struct policy_handle *handle,
5780                              const char *name)
5781 {
5782         bool ret = true;
5783         struct dcerpc_binding_handle *b = p->binding_handle;
5784
5785         if (!test_PausePrinter(tctx, b, handle)) {
5786                 ret = false;
5787         }
5788
5789         if (!test_DoPrintTest(tctx, b, handle)) {
5790                 ret = false;
5791         }
5792
5793         if (!test_ResumePrinter(tctx, b, handle)) {
5794                 ret = false;
5795         }
5796
5797         if (!test_printer_info(tctx, b, handle)) {
5798                 ret = false;
5799         }
5800
5801         if (!test_PrinterInfo_SD(tctx, b, handle)) {
5802                 ret = false;
5803         }
5804
5805         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5806                 ret = false;
5807         }
5808
5809         if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
5810                 ret = false;
5811         }
5812
5813         if (!test_ChangeID(tctx, p, handle)) {
5814                 ret = false;
5815         }
5816
5817         if (!test_printer_keys(tctx, b, handle)) {
5818                 ret = false;
5819         }
5820
5821         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5822                 ret = false;
5823         }
5824
5825         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5826                 ret = false;
5827         }
5828
5829         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5830                 ret = false;
5831         }
5832
5833         if (!test_printer_rename(tctx, p, handle, name)) {
5834                 ret = false;
5835         }
5836
5837         return ret;
5838 }
5839
5840 static bool test_printer(struct torture_context *tctx,
5841                          struct dcerpc_pipe *p)
5842 {
5843         bool ret = true;
5844         struct policy_handle handle[2];
5845         bool found = false;
5846         const char *drivername = "Microsoft XPS Document Writer";
5847         const char *portname = "LPT1:";
5848         struct dcerpc_binding_handle *b = p->binding_handle;
5849
5850         /* test printer created via AddPrinter */
5851
5852         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5853                 return false;
5854         }
5855
5856         if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5857                 ret = false;
5858         }
5859
5860         if (!test_DeletePrinter(tctx, b, &handle[0])) {
5861                 ret = false;
5862         }
5863
5864         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5865                                         TORTURE_PRINTER, &found)) {
5866                 ret = false;
5867         }
5868
5869         torture_assert(tctx, !found, "deleted printer still there");
5870
5871         /* test printer created via AddPrinterEx */
5872
5873         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5874                 return false;
5875         }
5876
5877         if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5878                 ret = false;
5879         }
5880
5881         if (!test_DeletePrinter(tctx, b, &handle[1])) {
5882                 ret = false;
5883         }
5884
5885         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5886                                         TORTURE_PRINTER_EX, &found)) {
5887                 ret = false;
5888         }
5889
5890         torture_assert(tctx, !found, "deleted printer still there");
5891
5892         return ret;
5893 }
5894
5895 static bool test_architecture_buffer(struct torture_context *tctx,
5896                                      struct dcerpc_pipe *p)
5897 {
5898         struct spoolss_OpenPrinterEx r;
5899         struct spoolss_UserLevel1 u1;
5900         struct policy_handle handle;
5901         uint32_t architectures[] = {
5902                 PROCESSOR_ARCHITECTURE_INTEL,
5903                 PROCESSOR_ARCHITECTURE_IA64,
5904                 PROCESSOR_ARCHITECTURE_AMD64
5905         };
5906         uint32_t needed[3];
5907         int i;
5908         struct dcerpc_binding_handle *b = p->binding_handle;
5909
5910         for (i=0; i < ARRAY_SIZE(architectures); i++) {
5911
5912                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5913
5914                 u1.size = 0;
5915                 u1.client = NULL;
5916                 u1.user = NULL;
5917                 u1.build = 0;
5918                 u1.major = 3;
5919                 u1.minor = 0;
5920                 u1.processor = architectures[i];
5921
5922                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5923                 r.in.datatype           = NULL;
5924                 r.in.devmode_ctr.devmode= NULL;
5925                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5926                 r.in.level               = 1;
5927                 r.in.userlevel.level1   = &u1;
5928                 r.out.handle            = &handle;
5929
5930                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
5931                 torture_assert_werr_ok(tctx, r.out.result, "");
5932
5933                 {
5934                         struct spoolss_EnumPrinters e;
5935                         uint32_t count;
5936                         union spoolss_PrinterInfo *info;
5937
5938                         e.in.flags = PRINTER_ENUM_LOCAL;
5939                         e.in.server = NULL;
5940                         e.in.level = 2;
5941                         e.in.buffer = NULL;
5942                         e.in.offered = 0;
5943                         e.out.count = &count;
5944                         e.out.info = &info;
5945                         e.out.needed = &needed[i];
5946
5947                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
5948 #if 0
5949                         torture_comment(tctx, "needed was %d\n", needed[i]);
5950 #endif
5951                 }
5952
5953                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
5954         }
5955
5956         for (i=1; i < ARRAY_SIZE(architectures); i++) {
5957                 if (needed[i-1] != needed[i]) {
5958                         torture_fail(tctx,
5959                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5960                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5961                 }
5962         }
5963
5964         return true;
5965 }
5966
5967 bool torture_rpc_spoolss(struct torture_context *torture)
5968 {
5969         NTSTATUS status;
5970         struct dcerpc_pipe *p;
5971         struct dcerpc_binding_handle *b;
5972         bool ret = true;
5973         struct test_spoolss_context *ctx;
5974         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5975
5976         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5977         if (!NT_STATUS_IS_OK(status)) {
5978                 return false;
5979         }
5980         b = p->binding_handle;
5981
5982         ctx = talloc_zero(torture, struct test_spoolss_context);
5983
5984         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5985         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5986         ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
5987         ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
5988         ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
5989         ret &= test_EnumPorts(torture, b, ctx);
5990         ret &= test_GetPrinterDriverDirectory(torture, p, environment);
5991         ret &= test_GetPrintProcessorDirectory(torture, p, environment);
5992         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5993         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5994         ret &= test_EnumMonitors(torture, b, ctx);
5995         ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
5996         ret &= test_EnumPrintProcDataTypes(torture, b);
5997         ret &= test_EnumPrinters(torture, b, ctx);
5998         ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
5999
6000         ret &= test_AddPort(torture, p);
6001         ret &= test_EnumPorts_old(torture, p);
6002         ret &= test_EnumPrinters_old(torture, p, environment);
6003         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
6004         ret &= test_architecture_buffer(torture, p);
6005
6006         return ret;
6007 }
6008
6009 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
6010 {
6011         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
6012
6013         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
6014                                                         "printer", &ndr_table_spoolss);
6015
6016         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
6017
6018         return suite;
6019 }