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