fe9436fbfbadf696c41a5d0e79eac802386e645c
[kai/samba.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/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
41
42 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
43 #define TORTURE_PRINTER                 "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX              "torture_printer_ex"
46 #define TORTURE_DRIVER                  "torture_driver"
47 #define TORTURE_DRIVER_EX               "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE            "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE         "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
51
52 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
53 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
54 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
55 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
56 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
57 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
58
59 struct test_spoolss_context {
60         struct dcerpc_pipe *spoolss_pipe;
61
62         /* server environment */
63         const char *environment;
64
65         /* print server handle */
66         struct policy_handle server_handle;
67
68         /* for EnumPorts */
69         uint32_t port_count[3];
70         union spoolss_PortInfo *ports[3];
71
72         /* for EnumPrinterDrivers */
73         uint32_t driver_count[8];
74         union spoolss_DriverInfo *drivers[8];
75
76         /* for EnumMonitors */
77         uint32_t monitor_count[3];
78         union spoolss_MonitorInfo *monitors[3];
79
80         /* for EnumPrintProcessors */
81         uint32_t print_processor_count[2];
82         union spoolss_PrintProcessorInfo *print_processors[2];
83
84         /* for EnumPrinters */
85         uint32_t printer_count[6];
86         union spoolss_PrinterInfo *printers[6];
87 };
88
89 struct torture_driver_context {
90         struct {
91                 const char *driver_directory;
92                 const char *environment;
93         } local;
94         struct {
95                 const char *driver_directory;
96                 const char *environment;
97         } remote;
98         struct spoolss_AddDriverInfo8 info8;
99         bool ex;
100 };
101
102 struct torture_printer_context {
103         struct dcerpc_pipe *spoolss_pipe;
104         struct spoolss_SetPrinterInfo2 info2;
105         struct torture_driver_context driver;
106         bool ex;
107         bool wellknown;
108         bool added_driver;
109         bool have_driver;
110         struct spoolss_DeviceMode *devmode;
111         struct policy_handle handle;
112 };
113
114 static bool upload_printer_driver(struct torture_context *tctx,
115                                   const char *server_name,
116                                   struct torture_driver_context *d);
117 static bool remove_printer_driver(struct torture_context *tctx,
118                                   const char *server_name,
119                                   struct torture_driver_context *d);
120 static bool fillup_printserver_info(struct torture_context *tctx,
121                                     struct dcerpc_pipe *p,
122                                     struct torture_driver_context *d);
123 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
124                                                struct dcerpc_binding_handle *b,
125                                                const char *server_name,
126                                                struct spoolss_AddDriverInfo8 *r,
127                                                uint32_t flags,
128                                                bool ex);
129
130 #define COMPARE_STRING(tctx, c,r,e) \
131         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
132
133 /* not every compiler supports __typeof__() */
134 #if (__GNUC__ >= 3)
135 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
136         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
137                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
138         }\
139         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
140                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
141         }\
142 } while(0)
143 #else
144 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
145 #endif
146
147 #define COMPARE_UINT32(tctx, c, r, e) do {\
148         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
149         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
150 } while(0)
151
152 #define COMPARE_UINT64(tctx, c, r, e) do {\
153         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
154         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
155 } while(0)
156
157
158 #define COMPARE_NTTIME(tctx, c, r, e) do {\
159         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
160         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
161 } while(0)
162
163 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
164         int __i; \
165         if (!c.e && !r.e) { \
166                 break; \
167         } \
168         if (c.e && !r.e) { \
169                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
170         } \
171         if (!c.e && r.e) { \
172                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
173         } \
174         for (__i=0;c.e[__i] != NULL; __i++) { \
175                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
176         } \
177 } while(0)
178
179 #define CHECK_ALIGN(size, n) do {\
180         if (size % n) {\
181                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
182                         size, n, size + n - (size % n));\
183         }\
184 } while(0)
185
186 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
187
188 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
189         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
190         uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
191         uint32_t round_size = DO_ROUND(size, align);\
192         if (round_size != needed) {\
193                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
194                 CHECK_ALIGN(size, align);\
195         }\
196         }\
197 } while(0)
198
199 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
200         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201         uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
202         uint32_t round_size = DO_ROUND(size, align);\
203         if (round_size != needed) {\
204                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
205                 CHECK_ALIGN(size, align);\
206         }\
207         }\
208 } while(0)
209
210 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
211         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
212         uint32_t size = ndr_size_##fn(info, level, 0);\
213         uint32_t round_size = DO_ROUND(size, align);\
214         if (round_size != needed) {\
215                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
216                 CHECK_ALIGN(size, align);\
217         }\
218         }\
219 } while(0)
220
221 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
222                                           const union spoolss_PrinterInfo *i,
223                                           uint32_t level,
224                                           union spoolss_SetPrinterInfo *s)
225 {
226         switch (level) {
227         case 0:
228                 s->info0                        = talloc(tctx, struct spoolss_SetPrinterInfo0);
229                 break;
230         case 2:
231                 s->info2                        = talloc(tctx, struct spoolss_SetPrinterInfo2);
232                 s->info2->servername            = i->info2.servername;
233                 s->info2->printername           = i->info2.printername;
234                 s->info2->sharename             = i->info2.sharename;
235                 s->info2->portname              = i->info2.portname;
236                 s->info2->drivername            = i->info2.drivername;
237                 s->info2->comment               = i->info2.comment;
238                 s->info2->location              = i->info2.location;
239                 s->info2->devmode_ptr           = 0;
240                 s->info2->sepfile               = i->info2.sepfile;
241                 s->info2->printprocessor        = i->info2.printprocessor;
242                 s->info2->datatype              = i->info2.datatype;
243                 s->info2->parameters            = i->info2.parameters;
244                 s->info2->secdesc_ptr           = 0;
245                 s->info2->attributes            = i->info2.attributes;
246                 s->info2->priority              = i->info2.priority;
247                 s->info2->defaultpriority       = i->info2.defaultpriority;
248                 s->info2->starttime             = i->info2.starttime;
249                 s->info2->untiltime             = i->info2.untiltime;
250                 s->info2->status                = i->info2.status;
251                 s->info2->cjobs                 = i->info2.cjobs;
252                 s->info2->averageppm            = i->info2.averageppm;
253                 break;
254         case 3:
255         case 4:
256         case 5:
257         case 6:
258         case 7:
259         case 8:
260         case 9:
261         default:
262                 return false;
263         }
264
265         return true;
266 }
267
268 static bool test_OpenPrinter_server(struct torture_context *tctx,
269                                     struct dcerpc_pipe *p,
270                                     struct policy_handle *server_handle)
271 {
272         NTSTATUS status;
273         struct spoolss_OpenPrinter op;
274         struct dcerpc_binding_handle *b = p->binding_handle;
275
276         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
277         op.in.datatype          = NULL;
278         op.in.devmode_ctr.devmode= NULL;
279         op.in.access_mask       = 0;
280         op.out.handle           = server_handle;
281
282         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
283
284         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
285         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
286         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
287
288         return true;
289 }
290
291 static bool test_EnumPorts(struct torture_context *tctx,
292                            void *private_data)
293 {
294         struct test_spoolss_context *ctx =
295                 talloc_get_type_abort(private_data, struct test_spoolss_context);
296         struct dcerpc_pipe *p = ctx->spoolss_pipe;
297         struct dcerpc_binding_handle *b = p->binding_handle;
298         NTSTATUS status;
299         struct spoolss_EnumPorts r;
300         uint16_t levels[] = { 1, 2 };
301         int i, j;
302
303         for (i=0;i<ARRAY_SIZE(levels);i++) {
304                 int level = levels[i];
305                 DATA_BLOB blob;
306                 uint32_t needed;
307                 uint32_t count;
308                 union spoolss_PortInfo *info;
309
310                 r.in.servername = "";
311                 r.in.level = level;
312                 r.in.buffer = NULL;
313                 r.in.offered = 0;
314                 r.out.needed = &needed;
315                 r.out.count = &count;
316                 r.out.info = &info;
317
318                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
319
320                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
321                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
322                 if (W_ERROR_IS_OK(r.out.result)) {
323                         /* TODO: do some more checks here */
324                         continue;
325                 }
326                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
327                         "EnumPorts unexpected return code");
328
329                 blob = data_blob_talloc_zero(ctx, needed);
330                 r.in.buffer = &blob;
331                 r.in.offered = needed;
332
333                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
334                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
335
336                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
337
338                 torture_assert(tctx, info, "EnumPorts returned no info");
339
340                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
341
342                 ctx->port_count[level]  = count;
343                 ctx->ports[level]       = info;
344         }
345
346         for (i=1;i<ARRAY_SIZE(levels);i++) {
347                 int level = levels[i];
348                 int old_level = levels[i-1];
349                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
350                         "EnumPorts invalid value");
351         }
352         /* if the array sizes are not the same we would maybe segfault in the following code */
353
354         for (i=0;i<ARRAY_SIZE(levels);i++) {
355                 int level = levels[i];
356                 for (j=0;j<ctx->port_count[level];j++) {
357                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
358                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
359                         switch (level) {
360                         case 1:
361                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
362                                 break;
363                         case 2:
364                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
365                                 break;
366                         }
367                 }
368         }
369
370         return true;
371 }
372
373 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
374                                             void *private_data)
375 {
376         struct test_spoolss_context *ctx =
377                 talloc_get_type_abort(private_data, struct test_spoolss_context);
378
379         NTSTATUS status;
380         struct dcerpc_pipe *p = ctx->spoolss_pipe;
381         struct dcerpc_binding_handle *b = p->binding_handle;
382         struct spoolss_GetPrintProcessorDirectory r;
383         struct {
384                 uint16_t level;
385                 const char *server;
386         } levels[] = {{
387                         .level  = 1,
388                         .server = NULL
389                 },{
390                         .level  = 1,
391                         .server = ""
392                 },{
393                         .level  = 78,
394                         .server = ""
395                 },{
396                         .level  = 1,
397                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
398                 },{
399                         .level  = 1024,
400                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
401                 }
402         };
403         int i;
404         uint32_t needed;
405
406         for (i=0;i<ARRAY_SIZE(levels);i++) {
407                 int level = levels[i].level;
408                 DATA_BLOB blob;
409
410                 r.in.server             = levels[i].server;
411                 r.in.environment        = ctx->environment;
412                 r.in.level              = level;
413                 r.in.buffer             = NULL;
414                 r.in.offered            = 0;
415                 r.out.needed            = &needed;
416
417                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
418
419                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
420                 torture_assert_ntstatus_ok(tctx, status,
421                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
422                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
423                         "GetPrintProcessorDirectory unexpected return code");
424
425                 blob = data_blob_talloc_zero(tctx, needed);
426                 r.in.buffer = &blob;
427                 r.in.offered = needed;
428
429                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
430                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
431
432                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
433
434                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
435         }
436
437         return true;
438 }
439
440
441 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
442                                            void *private_data)
443 {
444         struct test_spoolss_context *ctx =
445                 talloc_get_type_abort(private_data, struct test_spoolss_context);
446
447         NTSTATUS status;
448         struct dcerpc_pipe *p = ctx->spoolss_pipe;
449         struct dcerpc_binding_handle *b = p->binding_handle;
450         struct spoolss_GetPrinterDriverDirectory r;
451         struct {
452                 uint16_t level;
453                 const char *server;
454         } levels[] = {{
455                         .level  = 1,
456                         .server = NULL
457                 },{
458                         .level  = 1,
459                         .server = ""
460                 },{
461                         .level  = 78,
462                         .server = ""
463                 },{
464                         .level  = 1,
465                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
466                 },{
467                         .level  = 1024,
468                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
469                 }
470         };
471         int i;
472         uint32_t needed;
473
474         for (i=0;i<ARRAY_SIZE(levels);i++) {
475                 int level = levels[i].level;
476                 DATA_BLOB blob;
477
478                 r.in.server             = levels[i].server;
479                 r.in.environment        = ctx->environment;
480                 r.in.level              = level;
481                 r.in.buffer             = NULL;
482                 r.in.offered            = 0;
483                 r.out.needed            = &needed;
484
485                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
486
487                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
488                 torture_assert_ntstatus_ok(tctx, status,
489                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
490                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
491                         "GetPrinterDriverDirectory unexpected return code");
492
493                 blob = data_blob_talloc_zero(tctx, needed);
494                 r.in.buffer = &blob;
495                 r.in.offered = needed;
496
497                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
498                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
499
500                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
501
502                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
503         }
504
505         return true;
506 }
507
508 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
509                                          struct dcerpc_binding_handle *b,
510                                          const char *server_name,
511                                          const char *environment,
512                                          uint32_t level,
513                                          uint32_t *count_p,
514                                          union spoolss_DriverInfo **info_p)
515 {
516         struct spoolss_EnumPrinterDrivers r;
517         uint32_t needed;
518         uint32_t count;
519         union spoolss_DriverInfo *info;
520
521         r.in.server             = server_name;
522         r.in.environment        = environment;
523         r.in.level              = level;
524         r.in.buffer             = NULL;
525         r.in.offered            = 0;
526         r.out.needed            = &needed;
527         r.out.count             = &count;
528         r.out.info              = &info;
529
530         torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
531                 r.in.environment, r.in.level);
532
533         torture_assert_ntstatus_ok(tctx,
534                 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
535                 "EnumPrinterDrivers failed");
536         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
537                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
538                 r.in.buffer = &blob;
539                 r.in.offered = needed;
540
541                 torture_assert_ntstatus_ok(tctx,
542                         dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543                         "EnumPrinterDrivers failed");
544         }
545
546         torture_assert_werr_ok(tctx, r.out.result,
547                 "EnumPrinterDrivers failed");
548
549         if (count_p) {
550                 *count_p = count;
551         }
552         if (info_p) {
553                 *info_p = info;
554         }
555
556         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
557
558         return true;
559
560 }
561
562 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
563                                             struct dcerpc_binding_handle *b,
564                                             const char *server_name,
565                                             const char *environment,
566                                             uint32_t level,
567                                             const char *driver_name)
568 {
569         uint32_t count;
570         union spoolss_DriverInfo *info;
571         int i;
572
573         torture_assert(tctx,
574                 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
575                 "failed to enumerate printer drivers");
576
577         for (i=0; i < count; i++) {
578                 const char *driver_name_ret;
579                 switch (level) {
580                 case 1:
581                         driver_name_ret = info[i].info1.driver_name;
582                         break;
583                 case 2:
584                         driver_name_ret = info[i].info2.driver_name;
585                         break;
586                 case 3:
587                         driver_name_ret = info[i].info3.driver_name;
588                         break;
589                 case 4:
590                         driver_name_ret = info[i].info4.driver_name;
591                         break;
592                 case 5:
593                         driver_name_ret = info[i].info5.driver_name;
594                         break;
595                 case 6:
596                         driver_name_ret = info[i].info6.driver_name;
597                         break;
598                 case 7:
599                         driver_name_ret = info[i].info7.driver_name;
600                         break;
601                 case 8:
602                         driver_name_ret = info[i].info8.driver_name;
603                         break;
604                 default:
605                         break;
606                 }
607                 if (strequal(driver_name, driver_name_ret)) {
608                         return true;
609                 }
610         }
611
612         return false;
613 }
614
615 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
616                                     void *private_data)
617 {
618         struct test_spoolss_context *ctx =
619                 talloc_get_type_abort(private_data, struct test_spoolss_context);
620         struct dcerpc_pipe *p = ctx->spoolss_pipe;
621         struct dcerpc_binding_handle *b = p->binding_handle;
622         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
623         int i, j, a;
624
625         /* FIXME: gd, come back and fix "" as server, and handle
626          * priority of returned error codes in torture test and samba 3
627          * server */
628         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
629         const char *environments[2];
630
631         environments[0] = SPOOLSS_ARCHITECTURE_ALL;
632         environments[1] = ctx->environment;
633
634         for (a=0;a<ARRAY_SIZE(environments);a++) {
635
636         for (i=0;i<ARRAY_SIZE(levels);i++) {
637                 int level = levels[i];
638                 uint32_t count;
639                 union spoolss_DriverInfo *info;
640
641                 torture_assert(tctx,
642                         test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
643                         "failed to enumerate drivers");
644
645                 ctx->driver_count[level]        = count;
646                 ctx->drivers[level]             = info;
647         }
648
649         for (i=1;i<ARRAY_SIZE(levels);i++) {
650                 int level = levels[i];
651                 int old_level = levels[i-1];
652
653                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
654                         "EnumPrinterDrivers invalid value");
655         }
656
657         for (i=0;i<ARRAY_SIZE(levels);i++) {
658                 int level = levels[i];
659
660                 for (j=0;j<ctx->driver_count[level];j++) {
661                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
662                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
663
664                         switch (level) {
665                         case 1:
666                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
667                                 break;
668                         case 2:
669                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
670                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
671                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
672                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
673                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
674                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
675                                 break;
676                         case 3:
677                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
678                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
679                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
680                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
681                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
682                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
683                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
684                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
685                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
686                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
687                                 break;
688                         case 4:
689                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
690                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
691                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
692                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
693                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
694                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
695                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
696                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
697                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
698                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
699                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
700                                 break;
701                         case 5:
702                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
703                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
704                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
705                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
706                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
707                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
708                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
709                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
710                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
711                                 break;
712                         case 6:
713                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
714                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
715                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
716                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
717                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
718                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
719                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
720                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
721                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
722                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
723                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
724                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
725                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
726                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
727                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
728                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
729                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
730                                 break;
731                         case 8:
732                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
733                                 break;
734                         }
735                 }
736         }
737         }
738
739         return true;
740 }
741
742 static bool test_EnumMonitors(struct torture_context *tctx,
743                               void *private_data)
744 {
745         struct test_spoolss_context *ctx =
746                 talloc_get_type_abort(private_data, struct test_spoolss_context);
747         struct dcerpc_pipe *p = ctx->spoolss_pipe;
748         struct dcerpc_binding_handle *b = p->binding_handle;
749         NTSTATUS status;
750         struct spoolss_EnumMonitors r;
751         uint16_t levels[] = { 1, 2 };
752         int i, j;
753
754         for (i=0;i<ARRAY_SIZE(levels);i++) {
755                 int level = levels[i];
756                 DATA_BLOB blob;
757                 uint32_t needed;
758                 uint32_t count;
759                 union spoolss_MonitorInfo *info;
760
761                 r.in.servername = "";
762                 r.in.level = level;
763                 r.in.buffer = NULL;
764                 r.in.offered = 0;
765                 r.out.needed = &needed;
766                 r.out.count = &count;
767                 r.out.info = &info;
768
769                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
770
771                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
772                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
773                 if (W_ERROR_IS_OK(r.out.result)) {
774                         /* TODO: do some more checks here */
775                         continue;
776                 }
777                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
778                         "EnumMonitors failed");
779
780                 blob = data_blob_talloc_zero(ctx, needed);
781                 r.in.buffer = &blob;
782                 r.in.offered = needed;
783
784                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
785                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
786
787                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
788
789                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
790
791                 ctx->monitor_count[level]       = count;
792                 ctx->monitors[level]            = info;
793         }
794
795         for (i=1;i<ARRAY_SIZE(levels);i++) {
796                 int level = levels[i];
797                 int old_level = levels[i-1];
798                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
799                                          "EnumMonitors invalid value");
800         }
801
802         for (i=0;i<ARRAY_SIZE(levels);i++) {
803                 int level = levels[i];
804                 for (j=0;j<ctx->monitor_count[level];j++) {
805                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
806                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
807                         switch (level) {
808                         case 1:
809                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
810                                 break;
811                         case 2:
812                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
813                                 break;
814                         }
815                 }
816         }
817
818         return true;
819 }
820
821 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
822                                            struct dcerpc_binding_handle *b,
823                                            const char *environment,
824                                            uint32_t level,
825                                            uint32_t *count_p,
826                                            union spoolss_PrintProcessorInfo **info_p,
827                                            WERROR expected_result)
828 {
829         struct spoolss_EnumPrintProcessors r;
830         DATA_BLOB blob;
831         uint32_t needed;
832         uint32_t count;
833         union spoolss_PrintProcessorInfo *info;
834
835         r.in.servername = "";
836         r.in.environment = environment;
837         r.in.level = level;
838         r.in.buffer = NULL;
839         r.in.offered = 0;
840         r.out.needed = &needed;
841         r.out.count = &count;
842         r.out.info = &info;
843
844         torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
845                 r.in.environment, r.in.level);
846
847         torture_assert_ntstatus_ok(tctx,
848                 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
849                 "EnumPrintProcessors failed");
850         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
851                 blob = data_blob_talloc_zero(tctx, needed);
852                 r.in.buffer = &blob;
853                 r.in.offered = needed;
854                 torture_assert_ntstatus_ok(tctx,
855                         dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
856                         "EnumPrintProcessors failed");
857         }
858         torture_assert_werr_equal(tctx, r.out.result, expected_result,
859                 "EnumPrintProcessors failed");
860
861         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
862
863         if (count_p) {
864                 *count_p = count;
865         }
866         if (info_p) {
867                 *info_p = info;
868         }
869
870         return true;
871 }
872
873 static bool test_EnumPrintProcessors(struct torture_context *tctx,
874                                      void *private_data)
875 {
876         struct test_spoolss_context *ctx =
877                 talloc_get_type_abort(private_data, struct test_spoolss_context);
878
879         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
880         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
881         int i;
882         struct dcerpc_pipe *p = ctx->spoolss_pipe;
883         struct dcerpc_binding_handle *b = p->binding_handle;
884
885         torture_assert(tctx,
886                 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
887                 "test_EnumPrintProcessors_level failed");
888
889         for (i=0;i<ARRAY_SIZE(levels);i++) {
890                 union spoolss_PrintProcessorInfo *info;
891                 uint32_t count;
892                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
893
894                 torture_assert(tctx,
895                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
896                         "test_EnumPrintProcessors_level failed");
897         }
898
899         return true;
900 }
901
902 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
903                                               struct dcerpc_binding_handle *b,
904                                               const char *print_processor_name,
905                                               uint32_t level,
906                                               uint32_t *count_p,
907                                               union spoolss_PrintProcDataTypesInfo **info_p,
908                                               WERROR expected_result)
909 {
910         struct spoolss_EnumPrintProcDataTypes r;
911         DATA_BLOB blob;
912         uint32_t needed;
913         uint32_t count;
914         union spoolss_PrintProcDataTypesInfo *info;
915
916         r.in.servername = "";
917         r.in.print_processor_name = print_processor_name;
918         r.in.level = level;
919         r.in.buffer = NULL;
920         r.in.offered = 0;
921         r.out.needed = &needed;
922         r.out.count = &count;
923         r.out.info = &info;
924
925         torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
926                 r.in.print_processor_name, r.in.level);
927
928         torture_assert_ntstatus_ok(tctx,
929                 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
930                 "EnumPrintProcDataTypes failed");
931         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
932                 blob = data_blob_talloc_zero(tctx, needed);
933                 r.in.buffer = &blob;
934                 r.in.offered = needed;
935                 torture_assert_ntstatus_ok(tctx,
936                         dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
937                         "EnumPrintProcDataTypes failed");
938         }
939         torture_assert_werr_equal(tctx, r.out.result, expected_result,
940                 "EnumPrintProcDataTypes failed");
941
942         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
943
944         if (count_p) {
945                 *count_p = count;
946         }
947         if (info_p) {
948                 *info_p = info;
949         }
950
951         return true;
952 }
953
954 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
955                                         void *private_data)
956 {
957         struct test_spoolss_context *ctx =
958                 talloc_get_type_abort(private_data, struct test_spoolss_context);
959
960         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
961         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
962         int i;
963         struct dcerpc_pipe *p = ctx->spoolss_pipe;
964         struct dcerpc_binding_handle *b = p->binding_handle;
965
966         torture_assert(tctx,
967                 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
968                 "test_EnumPrintProcDataTypes_level failed");
969
970         torture_assert(tctx,
971                 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
972                 "test_EnumPrintProcDataTypes_level failed");
973
974         for (i=0;i<ARRAY_SIZE(levels);i++) {
975                 int level = levels[i];
976                 uint32_t count;
977                 union spoolss_PrintProcDataTypesInfo *info;
978                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
979
980                 torture_assert(tctx,
981                         test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
982                         "test_EnumPrintProcDataTypes_level failed");
983         }
984
985         {
986                 union spoolss_PrintProcessorInfo *info;
987                 uint32_t count;
988
989                 torture_assert(tctx,
990                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
991                         "test_EnumPrintProcessors_level failed");
992
993                 for (i=0; i < count; i++) {
994                         torture_assert(tctx,
995                                 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
996                                 "test_EnumPrintProcDataTypes_level failed");
997                 }
998         }
999
1000
1001         return true;
1002 }
1003
1004 static bool test_EnumPrinters(struct torture_context *tctx,
1005                               void *private_data)
1006 {
1007         struct test_spoolss_context *ctx =
1008                 talloc_get_type_abort(private_data, struct test_spoolss_context);
1009         struct dcerpc_pipe *p = ctx->spoolss_pipe;
1010         struct dcerpc_binding_handle *b = p->binding_handle;
1011         struct spoolss_EnumPrinters r;
1012         NTSTATUS status;
1013         uint16_t levels[] = { 0, 1, 2, 4, 5 };
1014         int i, j;
1015
1016         for (i=0;i<ARRAY_SIZE(levels);i++) {
1017                 int level = levels[i];
1018                 DATA_BLOB blob;
1019                 uint32_t needed;
1020                 uint32_t count;
1021                 union spoolss_PrinterInfo *info;
1022
1023                 r.in.flags      = PRINTER_ENUM_LOCAL;
1024                 r.in.server     = "";
1025                 r.in.level      = level;
1026                 r.in.buffer     = NULL;
1027                 r.in.offered    = 0;
1028                 r.out.needed    = &needed;
1029                 r.out.count     = &count;
1030                 r.out.info      = &info;
1031
1032                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1033
1034                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1035                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1036                 if (W_ERROR_IS_OK(r.out.result)) {
1037                         /* TODO: do some more checks here */
1038                         continue;
1039                 }
1040                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1041                         "EnumPrinters unexpected return code");
1042
1043                 blob = data_blob_talloc_zero(ctx, needed);
1044                 r.in.buffer = &blob;
1045                 r.in.offered = needed;
1046
1047                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1048                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1049
1050                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1051
1052                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1053
1054                 ctx->printer_count[level]       = count;
1055                 ctx->printers[level]            = info;
1056         }
1057
1058         for (i=1;i<ARRAY_SIZE(levels);i++) {
1059                 int level = levels[i];
1060                 int old_level = levels[i-1];
1061                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1062                                          "EnumPrinters invalid value");
1063         }
1064
1065         for (i=0;i<ARRAY_SIZE(levels);i++) {
1066                 int level = levels[i];
1067                 for (j=0;j<ctx->printer_count[level];j++) {
1068                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1069                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1070                         switch (level) {
1071                         case 0:
1072                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1073                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1074                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1075                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1076                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1077                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1078                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1079                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1080                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1081                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1082                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1083                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1084                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1085                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1086                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1087                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1088                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1089                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1090                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1091                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1092                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1093                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1094                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1095                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1096                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1097                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1098                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1099                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1100                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1101                                 break;
1102                         case 1:
1103                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1104                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1105                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1106                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1107                                 break;
1108                         case 2:
1109                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
1110                                 break;
1111                         case 4:
1112                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1113                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1114                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1115                                 break;
1116                         case 5:
1117                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1118                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1119                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1120                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1121                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1122                                 break;
1123                         }
1124                 }
1125         }
1126
1127         /* TODO:
1128          *      - verify that the port of a printer was in the list returned by EnumPorts
1129          */
1130
1131         return true;
1132 }
1133
1134 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1135                                    struct dcerpc_binding_handle *b,
1136                                    struct policy_handle *handle,
1137                                    const char *driver_name,
1138                                    const char *environment);
1139
1140 bool test_GetPrinter_level(struct torture_context *tctx,
1141                            struct dcerpc_binding_handle *b,
1142                            struct policy_handle *handle,
1143                            uint32_t level,
1144                            union spoolss_PrinterInfo *info)
1145 {
1146         struct spoolss_GetPrinter r;
1147         uint32_t needed;
1148
1149         r.in.handle = handle;
1150         r.in.level = level;
1151         r.in.buffer = NULL;
1152         r.in.offered = 0;
1153         r.out.needed = &needed;
1154
1155         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1156
1157         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1158                 "GetPrinter failed");
1159
1160         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1161                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1162                 r.in.buffer = &blob;
1163                 r.in.offered = needed;
1164
1165                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1166                         "GetPrinter failed");
1167         }
1168
1169         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1170
1171         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1172
1173         if (info && r.out.info) {
1174                 *info = *r.out.info;
1175         }
1176
1177         return true;
1178 }
1179
1180
1181 static bool test_GetPrinter(struct torture_context *tctx,
1182                             struct dcerpc_binding_handle *b,
1183                             struct policy_handle *handle,
1184                             const char *environment)
1185 {
1186         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1187         int i;
1188
1189         for (i=0;i<ARRAY_SIZE(levels);i++) {
1190
1191                 union spoolss_PrinterInfo info;
1192
1193                 ZERO_STRUCT(info);
1194
1195                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1196                         "failed to call GetPrinter");
1197
1198                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1199                         torture_assert(tctx,
1200                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1201                                 "failed to call test_GetPrinterDriver2");
1202                 }
1203         }
1204
1205         return true;
1206 }
1207
1208 static bool test_SetPrinter(struct torture_context *tctx,
1209                             struct dcerpc_binding_handle *b,
1210                             struct policy_handle *handle,
1211                             struct spoolss_SetPrinterInfoCtr *info_ctr,
1212                             struct spoolss_DevmodeContainer *devmode_ctr,
1213                             struct sec_desc_buf *secdesc_ctr,
1214                             enum spoolss_PrinterControl command)
1215 {
1216         struct spoolss_SetPrinter r;
1217
1218         r.in.handle = handle;
1219         r.in.info_ctr = info_ctr;
1220         r.in.devmode_ctr = devmode_ctr;
1221         r.in.secdesc_ctr = secdesc_ctr;
1222         r.in.command = command;
1223
1224         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1225
1226         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1227                 "failed to call SetPrinter");
1228         torture_assert_werr_ok(tctx, r.out.result,
1229                 "failed to call SetPrinter");
1230
1231         return true;
1232 }
1233
1234 static bool test_SetPrinter_errors(struct torture_context *tctx,
1235                                    struct dcerpc_binding_handle *b,
1236                                    struct policy_handle *handle)
1237 {
1238         struct spoolss_SetPrinter r;
1239         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1240         int i;
1241
1242         struct spoolss_SetPrinterInfoCtr info_ctr;
1243         struct spoolss_DevmodeContainer devmode_ctr;
1244         struct sec_desc_buf secdesc_ctr;
1245
1246         info_ctr.level = 0;
1247         info_ctr.info.info0 = NULL;
1248
1249         ZERO_STRUCT(devmode_ctr);
1250         ZERO_STRUCT(secdesc_ctr);
1251
1252         r.in.handle = handle;
1253         r.in.info_ctr = &info_ctr;
1254         r.in.devmode_ctr = &devmode_ctr;
1255         r.in.secdesc_ctr = &secdesc_ctr;
1256         r.in.command = 0;
1257
1258         torture_comment(tctx, "Testing SetPrinter all zero\n");
1259
1260         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1261                 "failed to call SetPrinter");
1262         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1263                 "failed to call SetPrinter");
1264
1265  again:
1266         for (i=0; i < ARRAY_SIZE(levels); i++) {
1267
1268                 struct spoolss_SetPrinterInfo0 info0;
1269                 struct spoolss_SetPrinterInfo1 info1;
1270                 struct spoolss_SetPrinterInfo2 info2;
1271                 struct spoolss_SetPrinterInfo3 info3;
1272                 struct spoolss_SetPrinterInfo4 info4;
1273                 struct spoolss_SetPrinterInfo5 info5;
1274                 struct spoolss_SetPrinterInfo6 info6;
1275                 struct spoolss_SetPrinterInfo7 info7;
1276                 struct spoolss_SetPrinterInfo8 info8;
1277                 struct spoolss_SetPrinterInfo9 info9;
1278
1279
1280                 info_ctr.level = levels[i];
1281                 switch (levels[i]) {
1282                 case 0:
1283                         ZERO_STRUCT(info0);
1284                         info_ctr.info.info0 = &info0;
1285                         break;
1286                 case 1:
1287                         ZERO_STRUCT(info1);
1288                         info_ctr.info.info1 = &info1;
1289                         break;
1290                 case 2:
1291                         ZERO_STRUCT(info2);
1292                         info_ctr.info.info2 = &info2;
1293                         break;
1294                 case 3:
1295                         ZERO_STRUCT(info3);
1296                         info_ctr.info.info3 = &info3;
1297                         break;
1298                 case 4:
1299                         ZERO_STRUCT(info4);
1300                         info_ctr.info.info4 = &info4;
1301                         break;
1302                 case 5:
1303                         ZERO_STRUCT(info5);
1304                         info_ctr.info.info5 = &info5;
1305                         break;
1306                 case 6:
1307                         ZERO_STRUCT(info6);
1308                         info_ctr.info.info6 = &info6;
1309                         break;
1310                 case 7:
1311                         ZERO_STRUCT(info7);
1312                         info_ctr.info.info7 = &info7;
1313                         break;
1314                 case 8:
1315                         ZERO_STRUCT(info8);
1316                         info_ctr.info.info8 = &info8;
1317                         break;
1318                 case 9:
1319                         ZERO_STRUCT(info9);
1320                         info_ctr.info.info9 = &info9;
1321                         break;
1322                 }
1323
1324                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1325                         info_ctr.level, r.in.command);
1326
1327                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1328                         "failed to call SetPrinter");
1329
1330                 switch (r.in.command) {
1331                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1332                         /* is ignored for all levels other then 0 */
1333                         if (info_ctr.level > 0) {
1334                                 /* ignored then */
1335                                 break;
1336                         }
1337                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1338                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1339                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1340                         if (info_ctr.level > 0) {
1341                                 /* is invalid for all levels other then 0 */
1342                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1343                                         "unexpected error code returned");
1344                                 continue;
1345                         } else {
1346                                 torture_assert_werr_ok(tctx, r.out.result,
1347                                         "failed to call SetPrinter with non 0 command");
1348                                 continue;
1349                         }
1350                         break;
1351
1352                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1353                         /* FIXME: gd needs further investigation */
1354                 default:
1355                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1356                                 "unexpected error code returned");
1357                         continue;
1358                 }
1359
1360                 switch (info_ctr.level) {
1361                 case 1:
1362                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1363                                 "unexpected error code returned");
1364                         break;
1365                 case 2:
1366                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1367                                 "unexpected error code returned");
1368                         break;
1369                 case 3:
1370                 case 4:
1371                 case 5:
1372                 case 7:
1373                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1374                                 "unexpected error code returned");
1375                         break;
1376                 case 9:
1377                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1378                                 "unexpected error code returned");
1379                         break;
1380                 default:
1381                         torture_assert_werr_ok(tctx, r.out.result,
1382                                 "failed to call SetPrinter");
1383                         break;
1384                 }
1385         }
1386
1387         if (r.in.command < 5) {
1388                 r.in.command++;
1389                 goto again;
1390         }
1391
1392         return true;
1393 }
1394
1395 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1396 {
1397         if ((r->level == 2) && (r->info.info2)) {
1398                 r->info.info2->secdesc_ptr = 0;
1399                 r->info.info2->devmode_ptr = 0;
1400         }
1401 }
1402
1403 static bool test_PrinterInfo(struct torture_context *tctx,
1404                              struct dcerpc_binding_handle *b,
1405                              struct policy_handle *handle)
1406 {
1407         NTSTATUS status;
1408         struct spoolss_SetPrinter s;
1409         struct spoolss_GetPrinter q;
1410         struct spoolss_GetPrinter q0;
1411         struct spoolss_SetPrinterInfoCtr info_ctr;
1412         union spoolss_PrinterInfo info;
1413         struct spoolss_DevmodeContainer devmode_ctr;
1414         struct sec_desc_buf secdesc_ctr;
1415         uint32_t needed;
1416         bool ret = true;
1417         int i;
1418
1419         torture_skip(tctx, "Printer Info test is currently broken, skipping");
1420
1421         uint32_t status_list[] = {
1422                 /* these do not stick
1423                 PRINTER_STATUS_PAUSED,
1424                 PRINTER_STATUS_ERROR,
1425                 PRINTER_STATUS_PENDING_DELETION, */
1426                 PRINTER_STATUS_PAPER_JAM,
1427                 PRINTER_STATUS_PAPER_OUT,
1428                 PRINTER_STATUS_MANUAL_FEED,
1429                 PRINTER_STATUS_PAPER_PROBLEM,
1430                 PRINTER_STATUS_OFFLINE,
1431                 PRINTER_STATUS_IO_ACTIVE,
1432                 PRINTER_STATUS_BUSY,
1433                 PRINTER_STATUS_PRINTING,
1434                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1435                 PRINTER_STATUS_NOT_AVAILABLE,
1436                 PRINTER_STATUS_WAITING,
1437                 PRINTER_STATUS_PROCESSING,
1438                 PRINTER_STATUS_INITIALIZING,
1439                 PRINTER_STATUS_WARMING_UP,
1440                 PRINTER_STATUS_TONER_LOW,
1441                 PRINTER_STATUS_NO_TONER,
1442                 PRINTER_STATUS_PAGE_PUNT,
1443                 PRINTER_STATUS_USER_INTERVENTION,
1444                 PRINTER_STATUS_OUT_OF_MEMORY,
1445                 PRINTER_STATUS_DOOR_OPEN,
1446                 PRINTER_STATUS_SERVER_UNKNOWN,
1447                 PRINTER_STATUS_POWER_SAVE,
1448                 /* these do not stick
1449                 0x02000000,
1450                 0x04000000,
1451                 0x08000000,
1452                 0x10000000,
1453                 0x20000000,
1454                 0x40000000,
1455                 0x80000000 */
1456         };
1457         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1458         uint32_t attribute_list[] = {
1459                 PRINTER_ATTRIBUTE_QUEUED,
1460                 /* fails with WERR_INVALID_DATATYPE:
1461                 PRINTER_ATTRIBUTE_DIRECT, */
1462                 /* does not stick
1463                 PRINTER_ATTRIBUTE_DEFAULT, */
1464                 PRINTER_ATTRIBUTE_SHARED,
1465                 /* does not stick
1466                 PRINTER_ATTRIBUTE_NETWORK, */
1467                 PRINTER_ATTRIBUTE_HIDDEN,
1468                 PRINTER_ATTRIBUTE_LOCAL,
1469                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1470                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1471                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1472                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1473                 /* does not stick
1474                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1475                 /* fails with WERR_INVALID_DATATYPE:
1476                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1477                 /* these do not stick
1478                 PRINTER_ATTRIBUTE_PUBLISHED,
1479                 PRINTER_ATTRIBUTE_FAX,
1480                 PRINTER_ATTRIBUTE_TS,
1481                 0x00010000,
1482                 0x00020000,
1483                 0x00040000,
1484                 0x00080000,
1485                 0x00100000,
1486                 0x00200000,
1487                 0x00400000,
1488                 0x00800000,
1489                 0x01000000,
1490                 0x02000000,
1491                 0x04000000,
1492                 0x08000000,
1493                 0x10000000,
1494                 0x20000000,
1495                 0x40000000,
1496                 0x80000000 */
1497         };
1498
1499         ZERO_STRUCT(devmode_ctr);
1500         ZERO_STRUCT(secdesc_ctr);
1501
1502         s.in.handle = handle;
1503         s.in.command = 0;
1504         s.in.info_ctr = &info_ctr;
1505         s.in.devmode_ctr = &devmode_ctr;
1506         s.in.secdesc_ctr = &secdesc_ctr;
1507
1508         q.in.handle = handle;
1509         q.out.info = &info;
1510         q0 = q;
1511
1512 #define TESTGETCALL(call, r) \
1513                 r.in.buffer = NULL; \
1514                 r.in.offered = 0;\
1515                 r.out.needed = &needed; \
1516                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1517                 if (!NT_STATUS_IS_OK(status)) { \
1518                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1519                                r.in.level, nt_errstr(status), __location__); \
1520                         ret = false; \
1521                         break; \
1522                 }\
1523                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1524                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1525                         r.in.buffer = &blob; \
1526                         r.in.offered = needed; \
1527                 }\
1528                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1529                 if (!NT_STATUS_IS_OK(status)) { \
1530                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1531                                r.in.level, nt_errstr(status), __location__); \
1532                         ret = false; \
1533                         break; \
1534                 } \
1535                 if (!W_ERROR_IS_OK(r.out.result)) { \
1536                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1537                                r.in.level, win_errstr(r.out.result), __location__); \
1538                         ret = false; \
1539                         break; \
1540                 }
1541
1542
1543 #define TESTSETCALL_EXP(call, r, err) \
1544                 clear_info2(&info_ctr);\
1545                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1546                 if (!NT_STATUS_IS_OK(status)) { \
1547                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1548                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1549                         ret = false; \
1550                         break; \
1551                 } \
1552                 if (!W_ERROR_IS_OK(err)) { \
1553                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1554                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1555                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1556                                 ret = false; \
1557                         } \
1558                         break; \
1559                 } \
1560                 if (!W_ERROR_IS_OK(r.out.result)) { \
1561                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1562                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1563                         ret = false; \
1564                         break; \
1565                 }
1566
1567 #define TESTSETCALL(call, r) \
1568         TESTSETCALL_EXP(call, r, WERR_OK)
1569
1570 #define STRING_EQUAL(s1, s2, field) \
1571                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1572                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1573                                #field, s2, __location__); \
1574                         ret = false; \
1575                         break; \
1576                 }
1577
1578 #define MEM_EQUAL(s1, s2, length, field) \
1579                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1580                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1581                                #field, (const char *)s2, __location__); \
1582                         ret = false; \
1583                         break; \
1584                 }
1585
1586 #define INT_EQUAL(i1, i2, field) \
1587                 if (i1 != i2) { \
1588                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1589                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1590                         ret = false; \
1591                         break; \
1592                 }
1593
1594 #define SD_EQUAL(sd1, sd2, field) \
1595                 if (!security_descriptor_equal(sd1, sd2)) { \
1596                         torture_comment(tctx, "Failed to set %s (%s)\n", \
1597                                #field, __location__); \
1598                         ret = false; \
1599                         break; \
1600                 }
1601
1602 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1603                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1604                 q.in.level = lvl1; \
1605                 TESTGETCALL(GetPrinter, q) \
1606                 info_ctr.level = lvl1; \
1607                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1608                 info_ctr.info.info ## lvl1->field1 = value;\
1609                 TESTSETCALL_EXP(SetPrinter, s, err) \
1610                 info_ctr.info.info ## lvl1->field1 = ""; \
1611                 TESTGETCALL(GetPrinter, q) \
1612                 info_ctr.info.info ## lvl1->field1 = value; \
1613                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1614                 q.in.level = lvl2; \
1615                 TESTGETCALL(GetPrinter, q) \
1616                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1617                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1618         } while (0)
1619
1620 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1621         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1622         } while (0);
1623
1624 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1625                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626                 q.in.level = lvl1; \
1627                 TESTGETCALL(GetPrinter, q) \
1628                 info_ctr.level = lvl1; \
1629                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630                 info_ctr.info.info ## lvl1->field1 = value; \
1631                 TESTSETCALL(SetPrinter, s) \
1632                 info_ctr.info.info ## lvl1->field1 = 0; \
1633                 TESTGETCALL(GetPrinter, q) \
1634                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1635                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1636                 q.in.level = lvl2; \
1637                 TESTGETCALL(GetPrinter, q) \
1638                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1640         } while (0)
1641
1642 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1643         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1644         } while (0)
1645
1646         q0.in.level = 0;
1647         do { TESTGETCALL(GetPrinter, q0) } while (0);
1648
1649         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1650         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1651
1652         /* level 0 printername does not stick */
1653 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1654         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1655         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1656         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1657         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1658 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1659         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1660         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1661         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1662         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1663 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1664         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1665         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1666         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1667         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1668
1669         /* servername can be set but does not stick
1670         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1671         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1672         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1673         */
1674
1675         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1676         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1677         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1678         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1679         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1680
1681         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1682         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1683         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1684         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1685         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1686         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1687         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1688         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1689         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1690         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1691
1692         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1693 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1694                         attribute_list[i],
1695                         (attribute_list[i] | default_attribute)
1696                         ); */
1697                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1698                         attribute_list[i],
1699                         (attribute_list[i] | default_attribute)
1700                         );
1701                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1702                         attribute_list[i],
1703                         (attribute_list[i] | default_attribute)
1704                         );
1705                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1706                         attribute_list[i],
1707                         (attribute_list[i] | default_attribute)
1708                         );
1709 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1710                         attribute_list[i],
1711                         (attribute_list[i] | default_attribute)
1712                         ); */
1713                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1714                         attribute_list[i],
1715                         (attribute_list[i] | default_attribute)
1716                         );
1717                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1718                         attribute_list[i],
1719                         (attribute_list[i] | default_attribute)
1720                         );
1721                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1722                         attribute_list[i],
1723                         (attribute_list[i] | default_attribute)
1724                         );
1725 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1726                         attribute_list[i],
1727                         (attribute_list[i] | default_attribute)
1728                         ); */
1729                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1730                         attribute_list[i],
1731                         (attribute_list[i] | default_attribute)
1732                         );
1733                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1734                         attribute_list[i],
1735                         (attribute_list[i] | default_attribute)
1736                         );
1737                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1738                         attribute_list[i],
1739                         (attribute_list[i] | default_attribute)
1740                         );
1741         }
1742
1743         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1744                 /* level 2 sets do not stick
1745                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1746                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1747                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1748                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1749                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1750                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1751         }
1752
1753         /* priorities need to be between 0 and 99
1754            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1755         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1756         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1757         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1758         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1759         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1760         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1761         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1762         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1763
1764         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1765         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1766
1767         /* does not stick
1768         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1769         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1770
1771         /* does not stick
1772         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1773         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1774
1775         /* FIXME: gd also test devmode and secdesc behavior */
1776
1777         {
1778                 /* verify composition of level 1 description field */
1779                 const char *description;
1780                 const char *tmp;
1781
1782                 q0.in.level = 1;
1783                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1784
1785                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1786
1787                 q0.in.level = 2;
1788                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1789
1790                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1791                         q0.out.info->info2.printername,
1792                         q0.out.info->info2.drivername,
1793                         q0.out.info->info2.location);
1794
1795                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1796         }
1797
1798         return ret;
1799 }
1800
1801 static bool test_security_descriptor_equal(struct torture_context *tctx,
1802                                            const struct security_descriptor *sd1,
1803                                            const struct security_descriptor *sd2)
1804 {
1805         if (sd1 == sd2) {
1806                 return true;
1807         }
1808
1809         if (!sd1 || !sd2) {
1810                 torture_comment(tctx, "%s\n", __location__);
1811                 return false;
1812         }
1813
1814         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1815         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1816
1817         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1818         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1819
1820         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1821                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1822                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1823                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1824                 return false;
1825         }
1826         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1827                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1828                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1829                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1830                 return false;
1831         }
1832
1833         return true;
1834 }
1835
1836 static bool test_sd_set_level(struct torture_context *tctx,
1837                               struct dcerpc_binding_handle *b,
1838                               struct policy_handle *handle,
1839                               uint32_t level,
1840                               struct security_descriptor *sd)
1841 {
1842         struct spoolss_SetPrinterInfoCtr info_ctr;
1843         struct spoolss_DevmodeContainer devmode_ctr;
1844         struct sec_desc_buf secdesc_ctr;
1845         union spoolss_SetPrinterInfo sinfo;
1846
1847         ZERO_STRUCT(devmode_ctr);
1848         ZERO_STRUCT(secdesc_ctr);
1849
1850         switch (level) {
1851         case 2: {
1852                 union spoolss_PrinterInfo info;
1853                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1854                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1855
1856                 info_ctr.level = 2;
1857                 info_ctr.info = sinfo;
1858
1859                 break;
1860         }
1861         case 3: {
1862                 struct spoolss_SetPrinterInfo3 info3;
1863
1864                 info3.sec_desc_ptr = 0;
1865
1866                 info_ctr.level = 3;
1867                 info_ctr.info.info3 = &info3;
1868
1869                 break;
1870         }
1871         default:
1872                 return false;
1873         }
1874
1875         secdesc_ctr.sd = sd;
1876
1877         torture_assert(tctx,
1878                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1879
1880         return true;
1881 }
1882
1883 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1884                                  struct dcerpc_binding_handle *b,
1885                                  struct policy_handle *handle)
1886 {
1887         union spoolss_PrinterInfo info;
1888         struct security_descriptor *sd1, *sd2;
1889         int i;
1890
1891         /* just compare level 2 and level 3 */
1892
1893         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1894
1895         sd1 = info.info2.secdesc;
1896
1897         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1898
1899         sd2 = info.info3.secdesc;
1900
1901         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1902                 "SD level 2 != SD level 3");
1903
1904
1905         /* query level 2, set level 2, query level 2 */
1906
1907         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1908
1909         sd1 = info.info2.secdesc;
1910
1911         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1912
1913         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1914
1915         sd2 = info.info2.secdesc;
1916         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1917                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1918                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1919         }
1920
1921         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1922                 "SD level 2 != SD level 2 after SD has been set via level 2");
1923
1924
1925         /* query level 2, set level 3, query level 2 */
1926
1927         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1928
1929         sd1 = info.info2.secdesc;
1930
1931         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1932
1933         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1934
1935         sd2 = info.info2.secdesc;
1936
1937         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1938                 "SD level 2 != SD level 2 after SD has been set via level 3");
1939
1940         /* set modified sd level 3, query level 2 */
1941
1942         for (i=0; i < 93; i++) {
1943                 struct security_ace a;
1944                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1945                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1946                 a.flags = 0;
1947                 a.size = 0; /* autogenerated */
1948                 a.access_mask = 0;
1949                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1950                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1951         }
1952
1953         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1954
1955         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1956         sd2 = info.info2.secdesc;
1957
1958         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1959                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1960                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1961         }
1962
1963         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1964                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1965
1966
1967         return true;
1968 }
1969
1970 /*
1971  * wrapper call that saves original sd, runs tests, and restores sd
1972  */
1973
1974 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1975                                 struct dcerpc_binding_handle *b,
1976                                 struct policy_handle *handle)
1977 {
1978         union spoolss_PrinterInfo info;
1979         struct security_descriptor *sd;
1980         bool ret = true;
1981
1982         torture_comment(tctx, "Testing Printer Security Descriptors\n");
1983
1984         /* save original sd */
1985
1986         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1987                 "failed to get initial security descriptor");
1988
1989         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1990
1991         /* run tests */
1992
1993         ret = test_PrinterInfo_SDs(tctx, b, handle);
1994
1995         /* restore original sd */
1996
1997         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1998                 "failed to restore initial security descriptor");
1999
2000         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2001                 ret ? "succeeded" : "failed");
2002
2003
2004         return ret;
2005 }
2006
2007 static bool test_devmode_set_level(struct torture_context *tctx,
2008                                    struct dcerpc_binding_handle *b,
2009                                    struct policy_handle *handle,
2010                                    uint32_t level,
2011                                    struct spoolss_DeviceMode *devmode)
2012 {
2013         struct spoolss_SetPrinterInfoCtr info_ctr;
2014         struct spoolss_DevmodeContainer devmode_ctr;
2015         struct sec_desc_buf secdesc_ctr;
2016         union spoolss_SetPrinterInfo sinfo;
2017
2018         ZERO_STRUCT(devmode_ctr);
2019         ZERO_STRUCT(secdesc_ctr);
2020
2021         switch (level) {
2022         case 2: {
2023                 union spoolss_PrinterInfo info;
2024                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2025                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2026
2027                 info_ctr.level = 2;
2028                 info_ctr.info = sinfo;
2029
2030                 break;
2031         }
2032         case 8: {
2033                 struct spoolss_SetPrinterInfo8 info8;
2034
2035                 info8.devmode_ptr = 0;
2036
2037                 info_ctr.level = 8;
2038                 info_ctr.info.info8 = &info8;
2039
2040                 break;
2041         }
2042         default:
2043                 return false;
2044         }
2045
2046         devmode_ctr.devmode = devmode;
2047
2048         torture_assert(tctx,
2049                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2050
2051         return true;
2052 }
2053
2054
2055 static bool test_devicemode_equal(struct torture_context *tctx,
2056                                   const struct spoolss_DeviceMode *d1,
2057                                   const struct spoolss_DeviceMode *d2)
2058 {
2059         if (d1 == d2) {
2060                 return true;
2061         }
2062
2063         if (!d1 || !d2) {
2064                 torture_comment(tctx, "%s\n", __location__);
2065                 return false;
2066         }
2067         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2068         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2069         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2070         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2071         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2072         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2073         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2074         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2075         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2076         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2077         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2078         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2079         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2080         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2081         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2082         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2083         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2084         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2085         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2086         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2087         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2088         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2089         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2090         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2091         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2092         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2093         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2094         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2095         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2096         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2097         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2098         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2099         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2100         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2101         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2102
2103         return true;
2104 }
2105
2106 static bool test_devicemode_full(struct torture_context *tctx,
2107                                  struct dcerpc_binding_handle *b,
2108                                  struct policy_handle *handle)
2109 {
2110         struct spoolss_SetPrinter s;
2111         struct spoolss_GetPrinter q;
2112         struct spoolss_GetPrinter q0;
2113         struct spoolss_SetPrinterInfoCtr info_ctr;
2114         struct spoolss_SetPrinterInfo8 info8;
2115         union spoolss_PrinterInfo info;
2116         struct spoolss_DevmodeContainer devmode_ctr;
2117         struct sec_desc_buf secdesc_ctr;
2118         uint32_t needed;
2119         bool ret = true;
2120         NTSTATUS status;
2121
2122 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2123                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2124                 q.in.level = lvl1; \
2125                 TESTGETCALL(GetPrinter, q) \
2126                 info_ctr.level = lvl1; \
2127                 if (lvl1 == 2) {\
2128                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2129                 } else if (lvl1 == 8) {\
2130                         info_ctr.info.info ## lvl1 = &info8; \
2131                 }\
2132                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2133                 devmode_ctr.devmode->field1 = value; \
2134                 TESTSETCALL(SetPrinter, s) \
2135                 TESTGETCALL(GetPrinter, q) \
2136                 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2137                 q.in.level = lvl2; \
2138                 TESTGETCALL(GetPrinter, q) \
2139                 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2140         } while (0)
2141
2142 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2143         TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2144         } while (0)
2145
2146         ZERO_STRUCT(devmode_ctr);
2147         ZERO_STRUCT(secdesc_ctr);
2148         ZERO_STRUCT(info8);
2149
2150         s.in.handle = handle;
2151         s.in.command = 0;
2152         s.in.info_ctr = &info_ctr;
2153         s.in.devmode_ctr = &devmode_ctr;
2154         s.in.secdesc_ctr = &secdesc_ctr;
2155
2156         q.in.handle = handle;
2157         q.out.info = &info;
2158         q0 = q;
2159
2160 #if 0
2161         const char *devicename;/* [charset(UTF16)] */
2162         enum spoolss_DeviceModeSpecVersion specversion;
2163         uint16_t driverversion;
2164         uint16_t size;
2165         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2166         uint32_t fields;
2167 #endif
2168
2169         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
2170         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
2171         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
2172         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
2173         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
2174         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
2175         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
2176         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
2177         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
2178         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
2179         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
2180         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
2181         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
2182 #if 0
2183         const char *formname;/* [charset(UTF16)] */
2184 #endif
2185         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
2186         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
2187         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
2188         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
2189         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
2190         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
2191         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
2192         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
2193         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
2194         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
2195         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
2196         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
2197         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
2198         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
2199
2200         return ret;
2201 }
2202
2203 static bool call_OpenPrinterEx(struct torture_context *tctx,
2204                                struct dcerpc_pipe *p,
2205                                const char *name,
2206                                struct spoolss_DeviceMode *devmode,
2207                                struct policy_handle *handle);
2208
2209 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2210                                       struct dcerpc_pipe *p,
2211                                       struct policy_handle *handle,
2212                                       const char *name)
2213 {
2214         union spoolss_PrinterInfo info;
2215         struct spoolss_DeviceMode *devmode;
2216         struct spoolss_DeviceMode *devmode2;
2217         struct policy_handle handle_devmode;
2218         struct dcerpc_binding_handle *b = p->binding_handle;
2219
2220         /* simply compare level8 and level2 devmode */
2221
2222         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2223
2224         devmode = info.info8.devmode;
2225
2226         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2227
2228         devmode2 = info.info2.devmode;
2229
2230         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2231                 "DM level 8 != DM level 2");
2232
2233
2234         /* set devicemode level 8 and see if it persists */
2235
2236         devmode->copies = 93;
2237         devmode->formname = talloc_strdup(tctx, "Legal");
2238
2239         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2240
2241         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2242
2243         devmode2 = info.info8.devmode;
2244
2245         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2246                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2247
2248         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2249
2250         devmode2 = info.info2.devmode;
2251
2252         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2253                 "modified DM level 8 != DM level 2");
2254
2255
2256         /* set devicemode level 2 and see if it persists */
2257
2258         devmode->copies = 39;
2259         devmode->formname = talloc_strdup(tctx, "Executive");
2260
2261         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2262
2263         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264
2265         devmode2 = info.info8.devmode;
2266
2267         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2268                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2269
2270         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2271
2272         devmode2 = info.info2.devmode;
2273
2274         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2275                 "modified DM level 8 != DM level 2");
2276
2277
2278         /* check every single bit in public part of devicemode */
2279
2280         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2281                 "failed to set every single devicemode component");
2282
2283
2284         /* change formname upon open and see if it persists in getprinter calls */
2285
2286         devmode->formname = talloc_strdup(tctx, "A4");
2287         devmode->copies = 42;
2288
2289         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2290                 "failed to open printer handle");
2291
2292         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2293
2294         devmode2 = info.info8.devmode;
2295
2296         if (strequal(devmode->devicename, devmode2->devicename)) {
2297                 torture_warning(tctx, "devicenames are the same\n");
2298         } else {
2299                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2300                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2301         }
2302
2303         if (strequal(devmode->formname, devmode2->formname)) {
2304                 torture_warning(tctx, "formname are the same\n");
2305         } else {
2306                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2307                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2308         }
2309
2310         if (devmode->copies == devmode2->copies) {
2311                 torture_warning(tctx, "copies are the same\n");
2312         } else {
2313                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2314                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2315         }
2316
2317         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2318
2319         devmode2 = info.info2.devmode;
2320
2321         if (strequal(devmode->devicename, devmode2->devicename)) {
2322                 torture_warning(tctx, "devicenames are the same\n");
2323         } else {
2324                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2325                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2326         }
2327
2328         if (strequal(devmode->formname, devmode2->formname)) {
2329                 torture_warning(tctx, "formname is the same\n");
2330         } else {
2331                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2332                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2333         }
2334
2335         if (devmode->copies == devmode2->copies) {
2336                 torture_warning(tctx, "copies are the same\n");
2337         } else {
2338                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2339                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2340         }
2341
2342         test_ClosePrinter(tctx, b, &handle_devmode);
2343
2344         return true;
2345 }
2346
2347 /*
2348  * wrapper call that saves original devmode, runs tests, and restores devmode
2349  */
2350
2351 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2352                                      struct dcerpc_pipe *p,
2353                                      struct policy_handle *handle,
2354                                      const char *name,
2355                                      struct spoolss_DeviceMode *addprinter_devmode)
2356 {
2357         union spoolss_PrinterInfo info;
2358         struct spoolss_DeviceMode *devmode;
2359         bool ret = true;
2360         struct dcerpc_binding_handle *b = p->binding_handle;
2361
2362         torture_comment(tctx, "Testing Printer Devicemodes\n");
2363
2364         /* save original devmode */
2365
2366         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2367                 "failed to get initial global devicemode");
2368
2369         devmode = info.info8.devmode;
2370
2371         if (addprinter_devmode) {
2372                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2373                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
2374                 }
2375         }
2376
2377         /* run tests */
2378
2379         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2380
2381         /* restore original devmode */
2382
2383         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2384                 "failed to restore initial global device mode");
2385
2386         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2387                 ret ? "succeeded" : "failed");
2388
2389
2390         return ret;
2391 }
2392
2393 bool test_ClosePrinter(struct torture_context *tctx,
2394                        struct dcerpc_binding_handle *b,
2395                        struct policy_handle *handle)
2396 {
2397         NTSTATUS status;
2398         struct spoolss_ClosePrinter r;
2399
2400         r.in.handle = handle;
2401         r.out.handle = handle;
2402
2403         torture_comment(tctx, "Testing ClosePrinter\n");
2404
2405         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2406         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2407         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2408
2409         return true;
2410 }
2411
2412 static bool test_GetForm_args(struct torture_context *tctx,
2413                               struct dcerpc_binding_handle *b,
2414                               struct policy_handle *handle,
2415                               const char *form_name,
2416                               uint32_t level,
2417                               union spoolss_FormInfo *info_p)
2418 {
2419         NTSTATUS status;
2420         struct spoolss_GetForm r;
2421         uint32_t needed;
2422
2423         r.in.handle = handle;
2424         r.in.form_name = form_name;
2425         r.in.level = level;
2426         r.in.buffer = NULL;
2427         r.in.offered = 0;
2428         r.out.needed = &needed;
2429
2430         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2431
2432         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2433         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2434
2435         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2436                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2437                 r.in.buffer = &blob;
2438                 r.in.offered = needed;
2439                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2440                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2441
2442                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2443
2444                 torture_assert(tctx, r.out.info, "No form info returned");
2445         }
2446
2447         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2448
2449         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2450
2451         if (info_p) {
2452                 *info_p = *r.out.info;
2453         }
2454
2455         return true;
2456 }
2457
2458 static bool test_GetForm(struct torture_context *tctx,
2459                          struct dcerpc_binding_handle *b,
2460                          struct policy_handle *handle,
2461                          const char *form_name,
2462                          uint32_t level)
2463 {
2464         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2465 }
2466
2467 static bool test_EnumForms(struct torture_context *tctx,
2468                            struct dcerpc_binding_handle *b,
2469                            struct policy_handle *handle,
2470                            bool print_server,
2471                            uint32_t level,
2472                            uint32_t *count_p,
2473                            union spoolss_FormInfo **info_p)
2474 {
2475         struct spoolss_EnumForms r;
2476         uint32_t needed;
2477         uint32_t count;
2478         union spoolss_FormInfo *info;
2479
2480         r.in.handle = handle;
2481         r.in.level = level;
2482         r.in.buffer = NULL;
2483         r.in.offered = 0;
2484         r.out.needed = &needed;
2485         r.out.count = &count;
2486         r.out.info = &info;
2487
2488         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2489
2490         torture_assert_ntstatus_ok(tctx,
2491                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2492                 "EnumForms failed");
2493
2494         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2495                 torture_skip(tctx, "EnumForms level 2 not supported");
2496         }
2497
2498         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2499                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2500         }
2501
2502         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2503                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2504                 r.in.buffer = &blob;
2505                 r.in.offered = needed;
2506
2507                 torture_assert_ntstatus_ok(tctx,
2508                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2509                         "EnumForms failed");
2510
2511                 torture_assert(tctx, info, "No forms returned");
2512         }
2513
2514         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2515
2516         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2517
2518         if (info_p) {
2519                 *info_p = info;
2520         }
2521         if (count_p) {
2522                 *count_p = count;
2523         }
2524
2525         return true;
2526 }
2527
2528 static bool test_EnumForms_all(struct torture_context *tctx,
2529                                struct dcerpc_binding_handle *b,
2530                                struct policy_handle *handle,
2531                                bool print_server)
2532 {
2533         uint32_t levels[] = { 1, 2 };
2534         int i, j;
2535
2536         for (i=0; i<ARRAY_SIZE(levels); i++) {
2537
2538                 uint32_t count = 0;
2539                 union spoolss_FormInfo *info = NULL;
2540
2541                 torture_assert(tctx,
2542                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2543                         "failed to enum forms");
2544
2545                 for (j = 0; j < count; j++) {
2546                         if (!print_server) {
2547                                 torture_assert(tctx,
2548                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2549                                         "failed to get form");
2550                         }
2551                 }
2552         }
2553
2554         return true;
2555 }
2556
2557 static bool test_EnumForms_find_one(struct torture_context *tctx,
2558                                     struct dcerpc_binding_handle *b,
2559                                     struct policy_handle *handle,
2560                                     bool print_server,
2561                                     const char *form_name)
2562 {
2563         union spoolss_FormInfo *info;
2564         uint32_t count;
2565         bool found = false;
2566         int i;
2567
2568         torture_assert(tctx,
2569                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2570                 "failed to enumerate forms");
2571
2572         for (i=0; i<count; i++) {
2573                 if (strequal(form_name, info[i].info1.form_name)) {
2574                         found = true;
2575                         break;
2576                 }
2577         }
2578
2579         return found;
2580 }
2581
2582 static bool test_DeleteForm(struct torture_context *tctx,
2583                             struct dcerpc_binding_handle *b,
2584                             struct policy_handle *handle,
2585                             const char *form_name,
2586                             WERROR expected_result)
2587 {
2588         struct spoolss_DeleteForm r;
2589
2590         r.in.handle = handle;
2591         r.in.form_name = form_name;
2592
2593         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2594
2595         torture_assert_ntstatus_ok(tctx,
2596                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2597                 "DeleteForm failed");
2598         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2599                 "DeleteForm gave unexpected result");
2600         if (W_ERROR_IS_OK(r.out.result)) {
2601                 torture_assert_ntstatus_ok(tctx,
2602                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2603                         "2nd DeleteForm failed");
2604                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2605                         "2nd DeleteForm failed");
2606         }
2607
2608         return true;
2609 }
2610
2611 static bool test_AddForm(struct torture_context *tctx,
2612                          struct dcerpc_binding_handle *b,
2613                          struct policy_handle *handle,
2614                          uint32_t level,
2615                          union spoolss_AddFormInfo *info,
2616                          WERROR expected_result)
2617 {
2618         struct spoolss_AddForm r;
2619
2620         if (level != 1) {
2621                 torture_skip(tctx, "only level 1 supported");
2622         }
2623
2624         r.in.handle     = handle;
2625         r.in.level      = level;
2626         r.in.info       = *info;
2627
2628         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2629                 r.in.info.info1->form_name, r.in.level,
2630                 r.in.info.info1->flags);
2631
2632         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2633                 "AddForm failed");
2634         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2635                 "AddForm gave unexpected result");
2636
2637         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2638                 "2nd AddForm failed");
2639         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2640                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2641                         "2nd AddForm gave unexpected result");
2642         } else {
2643                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2644                         "2nd AddForm gave unexpected result");
2645         }
2646
2647         return true;
2648 }
2649
2650 static bool test_SetForm(struct torture_context *tctx,
2651                          struct dcerpc_binding_handle *b,
2652                          struct policy_handle *handle,
2653                          const char *form_name,
2654                          uint32_t level,
2655                          union spoolss_AddFormInfo *info)
2656 {
2657         struct spoolss_SetForm r;
2658
2659         r.in.handle     = handle;
2660         r.in.form_name  = form_name;
2661         r.in.level      = level;
2662         r.in.info       = *info;
2663
2664         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2665                 form_name, r.in.level);
2666
2667         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2668                 "SetForm failed");
2669
2670         torture_assert_werr_ok(tctx, r.out.result,
2671                 "SetForm failed");
2672
2673         return true;
2674 }
2675
2676 static bool test_GetForm_winreg(struct torture_context *tctx,
2677                                 struct dcerpc_binding_handle *b,
2678                                 struct policy_handle *handle,
2679                                 const char *key_name,
2680                                 const char *form_name,
2681                                 enum winreg_Type *w_type,
2682                                 uint32_t *w_size,
2683                                 uint32_t *w_length,
2684                                 uint8_t **w_data);
2685
2686 static bool test_Forms_args(struct torture_context *tctx,
2687                             struct dcerpc_binding_handle *b,
2688                             struct policy_handle *handle,
2689                             bool print_server,
2690                             const char *printer_name,
2691                             struct dcerpc_binding_handle *winreg_handle,
2692                             struct policy_handle *hive_handle,
2693                             const char *form_name,
2694                             struct spoolss_AddFormInfo1 *info1,
2695                             WERROR expected_add_result,
2696                             WERROR expected_delete_result)
2697 {
2698         union spoolss_FormInfo info;
2699         union spoolss_AddFormInfo add_info;
2700
2701         enum winreg_Type w_type;
2702         uint32_t w_size;
2703         uint32_t w_length;
2704         uint8_t *w_data;
2705
2706         add_info.info1 = info1;
2707
2708         torture_assert(tctx,
2709                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2710                 "failed to add form");
2711
2712         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2713
2714                 struct spoolss_FormInfo1 i1;
2715
2716                 torture_assert(tctx,
2717                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2718                         "failed to get form via winreg");
2719
2720                 i1.size.width   = IVAL(w_data, 0);
2721                 i1.size.height  = IVAL(w_data, 4);
2722                 i1.area.left    = IVAL(w_data, 8);
2723                 i1.area.top     = IVAL(w_data, 12);
2724                 i1.area.right   = IVAL(w_data, 16);
2725                 i1.area.bottom  = IVAL(w_data, 20);
2726                 /* skip index here */
2727                 i1.flags        = IVAL(w_data, 28);
2728
2729                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2730                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2731                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2732                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2733                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2734                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2735                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2736                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2737                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2738                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2739         }
2740
2741         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2742                 torture_assert(tctx,
2743                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2744                         "failed to get added form");
2745
2746                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2747                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2748                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2749                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2750                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2751                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2752                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2753
2754                 if (winreg_handle && hive_handle) {
2755
2756                         struct spoolss_FormInfo1 i1;
2757
2758                         i1.size.width   = IVAL(w_data, 0);
2759                         i1.size.height  = IVAL(w_data, 4);
2760                         i1.area.left    = IVAL(w_data, 8);
2761                         i1.area.top     = IVAL(w_data, 12);
2762                         i1.area.right   = IVAL(w_data, 16);
2763                         i1.area.bottom  = IVAL(w_data, 20);
2764                         /* skip index here */
2765                         i1.flags        = IVAL(w_data, 28);
2766
2767                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2768                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2769                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2770                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2771                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2772                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2773                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2774                 }
2775
2776                 add_info.info1->size.width = 1234;
2777
2778                 torture_assert(tctx,
2779                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2780                         "failed to set form");
2781                 torture_assert(tctx,
2782                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2783                         "failed to get setted form");
2784
2785                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2786         }
2787
2788         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2789                 torture_assert(tctx,
2790                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2791                         "Newly added form not found in enum call");
2792         }
2793
2794         torture_assert(tctx,
2795                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2796                 "failed to delete form");
2797
2798         return true;
2799 }
2800
2801 static bool test_Forms(struct torture_context *tctx,
2802                        struct dcerpc_binding_handle *b,
2803                        struct policy_handle *handle,
2804                        bool print_server,
2805                        const char *printer_name,
2806                        struct dcerpc_binding_handle *winreg_handle,
2807                        struct policy_handle *hive_handle)
2808 {
2809         const struct spoolss_FormSize size = {
2810                 .width  = 50,
2811                 .height = 25
2812         };
2813         const struct spoolss_FormArea area = {
2814                 .left   = 5,
2815                 .top    = 10,
2816                 .right  = 45,
2817                 .bottom = 15
2818         };
2819         int i;
2820
2821         struct {
2822                 struct spoolss_AddFormInfo1 info1;
2823                 WERROR expected_add_result;
2824                 WERROR expected_delete_result;
2825         } forms[] = {
2826                 {
2827                         .info1 = {
2828                                 .flags          = SPOOLSS_FORM_USER,
2829                                 .form_name      = "testform_user",
2830                                 .size           = size,
2831                                 .area           = area,
2832                         },
2833                         .expected_add_result    = WERR_OK,
2834                         .expected_delete_result = WERR_OK
2835                 },
2836 /*
2837                 weird, we can add a builtin form but we can never remove it
2838                 again - gd
2839
2840                 {
2841                         .info1 = {
2842                                 .flags          = SPOOLSS_FORM_BUILTIN,
2843                                 .form_name      = "testform_builtin",
2844                                 .size           = size,
2845                                 .area           = area,
2846                         },
2847                         .expected_add_result    = WERR_OK,
2848                         .expected_delete_result = WERR_INVALID_PARAM,
2849                 },
2850 */
2851                 {
2852                         .info1 = {
2853                                 .flags          = SPOOLSS_FORM_PRINTER,
2854                                 .form_name      = "testform_printer",
2855                                 .size           = size,
2856                                 .area           = area,
2857                         },
2858                         .expected_add_result    = WERR_OK,
2859                         .expected_delete_result = WERR_OK
2860                 },
2861                 {
2862                         .info1 = {
2863                                 .flags          = SPOOLSS_FORM_USER,
2864                                 .form_name      = "Letter",
2865                                 .size           = size,
2866                                 .area           = area,
2867                         },
2868                         .expected_add_result    = WERR_FILE_EXISTS,
2869                         .expected_delete_result = WERR_INVALID_PARAM
2870                 },
2871                 {
2872                         .info1 = {
2873                                 .flags          = SPOOLSS_FORM_BUILTIN,
2874                                 .form_name      = "Letter",
2875                                 .size           = size,
2876                                 .area           = area,
2877                         },
2878                         .expected_add_result    = WERR_FILE_EXISTS,
2879                         .expected_delete_result = WERR_INVALID_PARAM
2880                 },
2881                 {
2882                         .info1 = {
2883                                 .flags          = SPOOLSS_FORM_PRINTER,
2884                                 .form_name      = "Letter",
2885                                 .size           = size,
2886                                 .area           = area,
2887                         },
2888                         .expected_add_result    = WERR_FILE_EXISTS,
2889                         .expected_delete_result = WERR_INVALID_PARAM
2890                 },
2891                 {
2892                         .info1 = {
2893                                 .flags          = 12345,
2894                                 .form_name      = "invalid_flags",
2895                                 .size           = size,
2896                                 .area           = area,
2897                         },
2898                         .expected_add_result    = WERR_INVALID_PARAM,
2899                         .expected_delete_result = WERR_INVALID_FORM_NAME
2900                 }
2901
2902         };
2903
2904         for (i=0; i < ARRAY_SIZE(forms); i++) {
2905                 torture_assert(tctx,
2906                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2907                                         winreg_handle, hive_handle,
2908                                         forms[i].info1.form_name,
2909                                         &forms[i].info1,
2910                                         forms[i].expected_add_result,
2911                                         forms[i].expected_delete_result),
2912                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2913         }
2914
2915         return true;
2916 }
2917
2918 static bool test_EnumPorts_old(struct torture_context *tctx,
2919                                void *private_data)
2920 {
2921         struct test_spoolss_context *ctx =
2922                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2923
2924         NTSTATUS status;
2925         struct spoolss_EnumPorts r;
2926         uint32_t needed;
2927         uint32_t count;
2928         union spoolss_PortInfo *info;
2929         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2930         struct dcerpc_binding_handle *b = p->binding_handle;
2931
2932         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2933                                           dcerpc_server_name(p));
2934         r.in.level = 2;
2935         r.in.buffer = NULL;
2936         r.in.offered = 0;
2937         r.out.needed = &needed;
2938         r.out.count = &count;
2939         r.out.info = &info;
2940
2941         torture_comment(tctx, "Testing EnumPorts\n");
2942
2943         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2944
2945         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2946
2947         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2948                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2949                 r.in.buffer = &blob;
2950                 r.in.offered = needed;
2951
2952                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2953                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2954                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2955
2956                 torture_assert(tctx, info, "No ports returned");
2957         }
2958
2959         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2960
2961         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2962
2963         return true;
2964 }
2965
2966 static bool test_AddPort(struct torture_context *tctx,
2967                          void *private_data)
2968 {
2969         struct test_spoolss_context *ctx =
2970                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2971
2972         NTSTATUS status;
2973         struct spoolss_AddPort r;
2974         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2975         struct dcerpc_binding_handle *b = p->binding_handle;
2976
2977         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2978                                            dcerpc_server_name(p));
2979         r.in.unknown = 0;
2980         r.in.monitor_name = "foo";
2981
2982         torture_comment(tctx, "Testing AddPort\n");
2983
2984         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2985
2986         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2987
2988         /* win2k3 returns WERR_NOT_SUPPORTED */
2989
2990 #if 0
2991
2992         if (!W_ERROR_IS_OK(r.out.result)) {
2993                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2994                 return false;
2995         }
2996
2997 #endif
2998
2999         return true;
3000 }
3001
3002 static bool test_GetJob_args(struct torture_context *tctx,
3003                              struct dcerpc_binding_handle *b,
3004                              struct policy_handle *handle,
3005                              uint32_t job_id,
3006                              uint32_t level,
3007                              union spoolss_JobInfo *info_p)
3008 {
3009         NTSTATUS status;
3010         struct spoolss_GetJob r;
3011         union spoolss_JobInfo info;
3012         uint32_t needed;
3013
3014         r.in.handle = handle;
3015         r.in.job_id = job_id;
3016         r.in.level = level;
3017         r.in.buffer = NULL;
3018         r.in.offered = 0;
3019         r.out.needed = &needed;
3020         r.out.info = &info;
3021
3022         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3023
3024         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3025         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3026         if (level == 0) {
3027                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3028         }
3029
3030         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3031                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3032                 r.in.buffer = &blob;
3033                 r.in.offered = needed;
3034
3035                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3036                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3037         }
3038
3039         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3040         torture_assert(tctx, r.out.info, "No job info returned");
3041
3042         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3043
3044         if (info_p) {
3045                 *info_p = *r.out.info;
3046         }
3047
3048         return true;
3049 }
3050
3051 static bool test_GetJob(struct torture_context *tctx,
3052                         struct dcerpc_binding_handle *b,
3053                         struct policy_handle *handle,
3054                         uint32_t job_id)
3055 {
3056         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3057         uint32_t i;
3058
3059         for (i=0; i < ARRAY_SIZE(levels); i++) {
3060                 torture_assert(tctx,
3061                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3062                         "GetJob failed");
3063         }
3064
3065         return true;
3066 }
3067
3068 static bool test_SetJob(struct torture_context *tctx,
3069                         struct dcerpc_binding_handle *b,
3070                         struct policy_handle *handle,
3071                         uint32_t job_id,
3072                         struct spoolss_JobInfoContainer *ctr,
3073                         enum spoolss_JobControl command)
3074 {
3075         NTSTATUS status;
3076         struct spoolss_SetJob r;
3077
3078         r.in.handle     = handle;
3079         r.in.job_id     = job_id;
3080         r.in.ctr        = ctr;
3081         r.in.command    = command;
3082
3083         switch (command) {
3084         case SPOOLSS_JOB_CONTROL_PAUSE:
3085                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3086                 break;
3087         case SPOOLSS_JOB_CONTROL_RESUME:
3088                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3089                 break;
3090         case SPOOLSS_JOB_CONTROL_CANCEL:
3091                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3092                 break;
3093         case SPOOLSS_JOB_CONTROL_RESTART:
3094                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3095                 break;
3096         case SPOOLSS_JOB_CONTROL_DELETE:
3097                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3098                 break;
3099         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3100                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3101                 break;
3102         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3103                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3104                 break;
3105         case SPOOLSS_JOB_CONTROL_RETAIN:
3106                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3107                 break;
3108         case SPOOLSS_JOB_CONTROL_RELEASE:
3109                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3110                 break;
3111         default:
3112                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3113                 break;
3114         }
3115
3116         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3117         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3118         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3119
3120         return true;
3121 }
3122
3123 static bool test_AddJob(struct torture_context *tctx,
3124                         struct dcerpc_binding_handle *b,
3125                         struct policy_handle *handle)
3126 {
3127         NTSTATUS status;
3128         struct spoolss_AddJob r;
3129         uint32_t needed;
3130
3131         r.in.level = 0;
3132         r.in.handle = handle;
3133         r.in.offered = 0;
3134         r.out.needed = &needed;
3135         r.in.buffer = r.out.buffer = NULL;
3136
3137         torture_comment(tctx, "Testing AddJob\n");
3138
3139         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3140         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3141
3142         r.in.level = 1;
3143
3144         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3145         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3146
3147         return true;
3148 }
3149
3150
3151 static bool test_EnumJobs_args(struct torture_context *tctx,
3152                                struct dcerpc_binding_handle *b,
3153                                struct policy_handle *handle,
3154                                uint32_t level,
3155                                uint32_t *count_p,
3156                                union spoolss_JobInfo **info_p)
3157 {
3158         NTSTATUS status;
3159         struct spoolss_EnumJobs r;
3160         uint32_t needed;
3161         uint32_t count;
3162         union spoolss_JobInfo *info;
3163
3164         r.in.handle = handle;
3165         r.in.firstjob = 0;
3166         r.in.numjobs = 0xffffffff;
3167         r.in.level = level;
3168         r.in.buffer = NULL;
3169         r.in.offered = 0;
3170         r.out.needed = &needed;
3171         r.out.count = &count;
3172         r.out.info = &info;
3173
3174         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3175
3176         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3177
3178         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3179
3180         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3181                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3182                 r.in.buffer = &blob;
3183                 r.in.offered = needed;
3184
3185                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3186
3187                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3188                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3189                 torture_assert(tctx, info, "No jobs returned");
3190
3191                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3192
3193         } else {
3194                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3195         }
3196
3197         if (count_p) {
3198                 *count_p = count;
3199         }
3200         if (info_p) {
3201                 *info_p = info;
3202         }
3203
3204         return true;
3205 }
3206
3207 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3208                                          struct dcerpc_binding_handle *b,
3209                                          struct policy_handle *handle,
3210                                          uint32_t *job_id)
3211 {
3212         NTSTATUS status;
3213         struct spoolss_StartDocPrinter s;
3214         struct spoolss_DocumentInfo1 info1;
3215         struct spoolss_StartPagePrinter sp;
3216         struct spoolss_WritePrinter w;
3217         struct spoolss_EndPagePrinter ep;
3218         struct spoolss_EndDocPrinter e;
3219         int i;
3220         uint32_t num_written;
3221
3222         torture_comment(tctx, "Testing StartDocPrinter\n");
3223
3224         s.in.handle             = handle;
3225         s.in.level              = 1;
3226         s.in.info.info1         = &info1;
3227         s.out.job_id            = job_id;
3228         info1.document_name     = "TorturePrintJob";
3229         info1.output_file       = NULL;
3230         info1.datatype          = "RAW";
3231
3232         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3233         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3234         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3235
3236         for (i=1; i < 4; i++) {
3237                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3238
3239                 sp.in.handle            = handle;
3240
3241                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3242                 torture_assert_ntstatus_ok(tctx, status,
3243                                            "dcerpc_spoolss_StartPagePrinter failed");
3244                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3245
3246                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3247
3248                 w.in.handle             = handle;
3249                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3250                 w.out.num_written       = &num_written;
3251
3252                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3253                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3254                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3255
3256                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3257
3258                 ep.in.handle            = handle;
3259
3260                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3261                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3262                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3263         }
3264
3265         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3266
3267         e.in.handle = handle;
3268
3269         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3270         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3271         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3272
3273         return true;
3274 }
3275
3276 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3277                                         struct dcerpc_binding_handle *b,
3278                                         struct policy_handle *handle,
3279                                         uint32_t num_jobs,
3280                                         uint32_t *job_ids)
3281 {
3282         uint32_t count;
3283         union spoolss_JobInfo *info = NULL;
3284         int i;
3285
3286         torture_assert(tctx,
3287                 test_AddJob(tctx, b, handle),
3288                 "AddJob failed");
3289
3290         torture_assert(tctx,
3291                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3292                 "EnumJobs level 1 failed");
3293
3294         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3295
3296         for (i=0; i < num_jobs; i++) {
3297                 union spoolss_JobInfo ginfo;
3298                 const char *document_name;
3299                 const char *new_document_name = "any_other_docname";
3300                 struct spoolss_JobInfoContainer ctr;
3301                 struct spoolss_SetJobInfo1 info1;
3302
3303                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3304
3305                 torture_assert(tctx,
3306                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3307                         "failed to call test_GetJob");
3308
3309                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3310
3311                 document_name = ginfo.info1.document_name;
3312
3313                 info1.job_id            = ginfo.info1.job_id;
3314                 info1.printer_name      = ginfo.info1.printer_name;
3315                 info1.server_name       = ginfo.info1.server_name;
3316                 info1.user_name         = ginfo.info1.user_name;
3317                 info1.document_name     = new_document_name;
3318                 info1.data_type         = ginfo.info1.data_type;
3319                 info1.text_status       = ginfo.info1.text_status;
3320                 info1.status            = ginfo.info1.status;
3321                 info1.priority          = ginfo.info1.priority;
3322                 info1.position          = ginfo.info1.position;
3323                 info1.total_pages       = ginfo.info1.total_pages;
3324                 info1.pages_printed     = ginfo.info1.pages_printed;
3325                 info1.submitted         = ginfo.info1.submitted;
3326
3327                 ctr.level = 1;
3328                 ctr.info.info1 = &info1;
3329
3330                 torture_assert(tctx,
3331                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3332                         "failed to call test_SetJob level 1");
3333
3334                 torture_assert(tctx,
3335                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3336                         "failed to call test_GetJob");
3337
3338                 if (strequal(ginfo.info1.document_name, document_name)) {
3339                         torture_warning(tctx,
3340                                         "document_name did *NOT* change from '%s' to '%s'\n",
3341                                         document_name, new_document_name);
3342                 }
3343         }
3344
3345         for (i=0; i < num_jobs; i++) {
3346                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3347                         torture_warning(tctx, "failed to pause printjob\n");
3348                 }
3349                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3350                         torture_warning(tctx, "failed to resume printjob\n");
3351                 }
3352         }
3353
3354         return true;
3355 }
3356
3357 static bool test_DoPrintTest(struct torture_context *tctx,
3358                              struct dcerpc_binding_handle *b,
3359                              struct policy_handle *handle)
3360 {
3361         bool ret = true;
3362         uint32_t num_jobs = 8;
3363         uint32_t *job_ids;
3364         int i;
3365
3366         torture_comment(tctx, "Testing real print operations\n");
3367
3368         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3369
3370         for (i=0; i < num_jobs; i++) {
3371                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3372         }
3373
3374         for (i=0; i < num_jobs; i++) {
3375                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3376         }
3377
3378         if (ret == true) {
3379                 torture_comment(tctx, "real print operations test succeeded\n\n");
3380         }
3381
3382         return ret;
3383 }
3384
3385 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3386                                       struct dcerpc_binding_handle *b,
3387                                       struct policy_handle *handle)
3388 {
3389         bool ret = true;
3390         uint32_t num_jobs = 8;
3391         uint32_t *job_ids;
3392         int i;
3393         torture_comment(tctx, "Testing real print operations (extended)\n");
3394
3395         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3396
3397         for (i=0; i < num_jobs; i++) {
3398                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3399         }
3400
3401         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3402
3403         for (i=0; i < num_jobs; i++) {
3404                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3405         }
3406
3407         if (ret == true) {
3408                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3409         }
3410
3411         return ret;
3412 }
3413
3414 static bool test_PausePrinter(struct torture_context *tctx,
3415                               struct dcerpc_binding_handle *b,
3416                               struct policy_handle *handle)
3417 {
3418         NTSTATUS status;
3419         struct spoolss_SetPrinter r;
3420         struct spoolss_SetPrinterInfoCtr info_ctr;
3421         struct spoolss_DevmodeContainer devmode_ctr;
3422         struct sec_desc_buf secdesc_ctr;
3423
3424         info_ctr.level = 0;
3425         info_ctr.info.info0 = NULL;
3426
3427         ZERO_STRUCT(devmode_ctr);
3428         ZERO_STRUCT(secdesc_ctr);
3429
3430         r.in.handle             = handle;
3431         r.in.info_ctr           = &info_ctr;
3432         r.in.devmode_ctr        = &devmode_ctr;
3433         r.in.secdesc_ctr        = &secdesc_ctr;
3434         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3435
3436         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3437
3438         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3439
3440         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3441
3442         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3443
3444         return true;
3445 }
3446
3447 static bool test_ResumePrinter(struct torture_context *tctx,
3448                                struct dcerpc_binding_handle *b,
3449                                struct policy_handle *handle)
3450 {
3451         NTSTATUS status;
3452         struct spoolss_SetPrinter r;
3453         struct spoolss_SetPrinterInfoCtr info_ctr;
3454         struct spoolss_DevmodeContainer devmode_ctr;
3455         struct sec_desc_buf secdesc_ctr;
3456
3457         info_ctr.level = 0;
3458         info_ctr.info.info0 = NULL;
3459
3460         ZERO_STRUCT(devmode_ctr);
3461         ZERO_STRUCT(secdesc_ctr);
3462
3463         r.in.handle             = handle;
3464         r.in.info_ctr           = &info_ctr;
3465         r.in.devmode_ctr        = &devmode_ctr;
3466         r.in.secdesc_ctr        = &secdesc_ctr;
3467         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3468
3469         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3470
3471         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3472
3473         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3474
3475         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3476