s4-smbtorture: re-arrange openprinterex tests.
[samba.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
41
42 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
43 #define TORTURE_PRINTER                 "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX              "torture_printer_ex"
46 #define TORTURE_DRIVER                  "torture_driver"
47 #define TORTURE_DRIVER_EX               "torture_driver_ex"
48
49 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
50 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
51 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
52 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
53 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
54 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
55
56 struct test_spoolss_context {
57         struct dcerpc_pipe *spoolss_pipe;
58
59         /* server environment */
60         const char *environment;
61
62         /* print server handle */
63         struct policy_handle server_handle;
64
65         /* for EnumPorts */
66         uint32_t port_count[3];
67         union spoolss_PortInfo *ports[3];
68
69         /* for EnumPrinterDrivers */
70         uint32_t driver_count[8];
71         union spoolss_DriverInfo *drivers[8];
72
73         /* for EnumMonitors */
74         uint32_t monitor_count[3];
75         union spoolss_MonitorInfo *monitors[3];
76
77         /* for EnumPrintProcessors */
78         uint32_t print_processor_count[2];
79         union spoolss_PrintProcessorInfo *print_processors[2];
80
81         /* for EnumPrinters */
82         uint32_t printer_count[6];
83         union spoolss_PrinterInfo *printers[6];
84 };
85
86 struct torture_driver_context {
87         struct {
88                 const char *driver_directory;
89                 const char *environment;
90         } local;
91         struct {
92                 const char *driver_directory;
93                 const char *environment;
94         } remote;
95         struct spoolss_AddDriverInfo8 info8;
96         bool ex;
97 };
98
99 struct torture_printer_context {
100         struct dcerpc_pipe *spoolss_pipe;
101         struct spoolss_SetPrinterInfo2 info2;
102         struct torture_driver_context driver;
103         bool ex;
104         bool wellknown;
105         bool added_driver;
106         bool have_driver;
107         struct spoolss_DeviceMode *devmode;
108         struct policy_handle handle;
109 };
110
111 static bool upload_printer_driver(struct torture_context *tctx,
112                                   const char *server_name,
113                                   struct torture_driver_context *d);
114 static bool remove_printer_driver(struct torture_context *tctx,
115                                   const char *server_name,
116                                   struct torture_driver_context *d);
117 static bool fillup_printserver_info(struct torture_context *tctx,
118                                     struct dcerpc_pipe *p,
119                                     struct torture_driver_context *d);
120 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
121                                                struct dcerpc_binding_handle *b,
122                                                const char *server_name,
123                                                struct spoolss_AddDriverInfo8 *r,
124                                                uint32_t flags,
125                                                bool ex);
126
127 #define COMPARE_STRING(tctx, c,r,e) \
128         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
129
130 /* not every compiler supports __typeof__() */
131 #if (__GNUC__ >= 3)
132 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
133         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
134                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
135         }\
136         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
137                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
138         }\
139 } while(0)
140 #else
141 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
142 #endif
143
144 #define COMPARE_UINT32(tctx, c, r, e) do {\
145         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
146         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
147 } while(0)
148
149 #define COMPARE_UINT64(tctx, c, r, e) do {\
150         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
151         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
152 } while(0)
153
154
155 #define COMPARE_NTTIME(tctx, c, r, e) do {\
156         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
157         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
159
160 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
161         int __i; \
162         if (!c.e && !r.e) { \
163                 break; \
164         } \
165         if (c.e && !r.e) { \
166                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
167         } \
168         if (!c.e && r.e) { \
169                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
170         } \
171         for (__i=0;c.e[__i] != NULL; __i++) { \
172                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
173         } \
174 } while(0)
175
176 #define CHECK_ALIGN(size, n) do {\
177         if (size % n) {\
178                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
179                         size, n, size + n - (size % n));\
180         }\
181 } while(0)
182
183 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
184
185 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
186         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
187         uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
188         uint32_t round_size = DO_ROUND(size, align);\
189         if (round_size != needed) {\
190                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
191                 CHECK_ALIGN(size, align);\
192         }\
193         }\
194 } while(0)
195
196 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
197         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198         uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
199         uint32_t round_size = DO_ROUND(size, align);\
200         if (round_size != needed) {\
201                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
202                 CHECK_ALIGN(size, align);\
203         }\
204         }\
205 } while(0)
206
207 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
208         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209         uint32_t size = ndr_size_##fn(info, level, 0);\
210         uint32_t round_size = DO_ROUND(size, align);\
211         if (round_size != needed) {\
212                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
213                 CHECK_ALIGN(size, align);\
214         }\
215         }\
216 } while(0)
217
218 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
219                                           const union spoolss_PrinterInfo *i,
220                                           uint32_t level,
221                                           union spoolss_SetPrinterInfo *s)
222 {
223         switch (level) {
224         case 0:
225                 s->info0                        = talloc(tctx, struct spoolss_SetPrinterInfo0);
226                 break;
227         case 2:
228                 s->info2                        = talloc(tctx, struct spoolss_SetPrinterInfo2);
229                 s->info2->servername            = i->info2.servername;
230                 s->info2->printername           = i->info2.printername;
231                 s->info2->sharename             = i->info2.sharename;
232                 s->info2->portname              = i->info2.portname;
233                 s->info2->drivername            = i->info2.drivername;
234                 s->info2->comment               = i->info2.comment;
235                 s->info2->location              = i->info2.location;
236                 s->info2->devmode_ptr           = 0;
237                 s->info2->sepfile               = i->info2.sepfile;
238                 s->info2->printprocessor        = i->info2.printprocessor;
239                 s->info2->datatype              = i->info2.datatype;
240                 s->info2->parameters            = i->info2.parameters;
241                 s->info2->secdesc_ptr           = 0;
242                 s->info2->attributes            = i->info2.attributes;
243                 s->info2->priority              = i->info2.priority;
244                 s->info2->defaultpriority       = i->info2.defaultpriority;
245                 s->info2->starttime             = i->info2.starttime;
246                 s->info2->untiltime             = i->info2.untiltime;
247                 s->info2->status                = i->info2.status;
248                 s->info2->cjobs                 = i->info2.cjobs;
249                 s->info2->averageppm            = i->info2.averageppm;
250                 break;
251         case 3:
252         case 4:
253         case 5:
254         case 6:
255         case 7:
256         case 8:
257         case 9:
258         default:
259                 return false;
260         }
261
262         return true;
263 }
264
265 static bool test_OpenPrinter_server(struct torture_context *tctx,
266                                     struct dcerpc_pipe *p,
267                                     struct policy_handle *server_handle)
268 {
269         NTSTATUS status;
270         struct spoolss_OpenPrinter op;
271         struct dcerpc_binding_handle *b = p->binding_handle;
272
273         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
274         op.in.datatype          = NULL;
275         op.in.devmode_ctr.devmode= NULL;
276         op.in.access_mask       = 0;
277         op.out.handle           = server_handle;
278
279         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
280
281         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
282         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
283         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
284
285         return true;
286 }
287
288 static bool test_EnumPorts(struct torture_context *tctx,
289                            void *private_data)
290 {
291         struct test_spoolss_context *ctx =
292                 talloc_get_type_abort(private_data, struct test_spoolss_context);
293         struct dcerpc_pipe *p = ctx->spoolss_pipe;
294         struct dcerpc_binding_handle *b = p->binding_handle;
295         NTSTATUS status;
296         struct spoolss_EnumPorts r;
297         uint16_t levels[] = { 1, 2 };
298         int i, j;
299
300         for (i=0;i<ARRAY_SIZE(levels);i++) {
301                 int level = levels[i];
302                 DATA_BLOB blob;
303                 uint32_t needed;
304                 uint32_t count;
305                 union spoolss_PortInfo *info;
306
307                 r.in.servername = "";
308                 r.in.level = level;
309                 r.in.buffer = NULL;
310                 r.in.offered = 0;
311                 r.out.needed = &needed;
312                 r.out.count = &count;
313                 r.out.info = &info;
314
315                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
316
317                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
318                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
319                 if (W_ERROR_IS_OK(r.out.result)) {
320                         /* TODO: do some more checks here */
321                         continue;
322                 }
323                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
324                         "EnumPorts unexpected return code");
325
326                 blob = data_blob_talloc_zero(ctx, needed);
327                 r.in.buffer = &blob;
328                 r.in.offered = needed;
329
330                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
331                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
332
333                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
334
335                 torture_assert(tctx, info, "EnumPorts returned no info");
336
337                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
338
339                 ctx->port_count[level]  = count;
340                 ctx->ports[level]       = info;
341         }
342
343         for (i=1;i<ARRAY_SIZE(levels);i++) {
344                 int level = levels[i];
345                 int old_level = levels[i-1];
346                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
347                         "EnumPorts invalid value");
348         }
349         /* if the array sizes are not the same we would maybe segfault in the following code */
350
351         for (i=0;i<ARRAY_SIZE(levels);i++) {
352                 int level = levels[i];
353                 for (j=0;j<ctx->port_count[level];j++) {
354                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
355                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
356                         switch (level) {
357                         case 1:
358                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
359                                 break;
360                         case 2:
361                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
362                                 break;
363                         }
364                 }
365         }
366
367         return true;
368 }
369
370 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
371                                             void *private_data)
372 {
373         struct test_spoolss_context *ctx =
374                 talloc_get_type_abort(private_data, struct test_spoolss_context);
375
376         NTSTATUS status;
377         struct dcerpc_pipe *p = ctx->spoolss_pipe;
378         struct dcerpc_binding_handle *b = p->binding_handle;
379         struct spoolss_GetPrintProcessorDirectory r;
380         struct {
381                 uint16_t level;
382                 const char *server;
383         } levels[] = {{
384                         .level  = 1,
385                         .server = NULL
386                 },{
387                         .level  = 1,
388                         .server = ""
389                 },{
390                         .level  = 78,
391                         .server = ""
392                 },{
393                         .level  = 1,
394                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
395                 },{
396                         .level  = 1024,
397                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
398                 }
399         };
400         int i;
401         uint32_t needed;
402
403         for (i=0;i<ARRAY_SIZE(levels);i++) {
404                 int level = levels[i].level;
405                 DATA_BLOB blob;
406
407                 r.in.server             = levels[i].server;
408                 r.in.environment        = ctx->environment;
409                 r.in.level              = level;
410                 r.in.buffer             = NULL;
411                 r.in.offered            = 0;
412                 r.out.needed            = &needed;
413
414                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
415
416                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
417                 torture_assert_ntstatus_ok(tctx, status,
418                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
419                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
420                         "GetPrintProcessorDirectory unexpected return code");
421
422                 blob = data_blob_talloc_zero(tctx, needed);
423                 r.in.buffer = &blob;
424                 r.in.offered = needed;
425
426                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
427                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
428
429                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
430
431                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
432         }
433
434         return true;
435 }
436
437
438 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
439                                            void *private_data)
440 {
441         struct test_spoolss_context *ctx =
442                 talloc_get_type_abort(private_data, struct test_spoolss_context);
443
444         NTSTATUS status;
445         struct dcerpc_pipe *p = ctx->spoolss_pipe;
446         struct dcerpc_binding_handle *b = p->binding_handle;
447         struct spoolss_GetPrinterDriverDirectory r;
448         struct {
449                 uint16_t level;
450                 const char *server;
451         } levels[] = {{
452                         .level  = 1,
453                         .server = NULL
454                 },{
455                         .level  = 1,
456                         .server = ""
457                 },{
458                         .level  = 78,
459                         .server = ""
460                 },{
461                         .level  = 1,
462                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
463                 },{
464                         .level  = 1024,
465                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
466                 }
467         };
468         int i;
469         uint32_t needed;
470
471         for (i=0;i<ARRAY_SIZE(levels);i++) {
472                 int level = levels[i].level;
473                 DATA_BLOB blob;
474
475                 r.in.server             = levels[i].server;
476                 r.in.environment        = ctx->environment;
477                 r.in.level              = level;
478                 r.in.buffer             = NULL;
479                 r.in.offered            = 0;
480                 r.out.needed            = &needed;
481
482                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
483
484                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
485                 torture_assert_ntstatus_ok(tctx, status,
486                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
487                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
488                         "GetPrinterDriverDirectory unexpected return code");
489
490                 blob = data_blob_talloc_zero(tctx, needed);
491                 r.in.buffer = &blob;
492                 r.in.offered = needed;
493
494                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
495                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
496
497                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
498
499                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
500         }
501
502         return true;
503 }
504
505 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
506                                          struct dcerpc_binding_handle *b,
507                                          const char *server_name,
508                                          const char *environment,
509                                          uint32_t level,
510                                          uint32_t *count_p,
511                                          union spoolss_DriverInfo **info_p)
512 {
513         struct spoolss_EnumPrinterDrivers r;
514         uint32_t needed;
515         uint32_t count;
516         union spoolss_DriverInfo *info;
517
518         r.in.server             = server_name;
519         r.in.environment        = environment;
520         r.in.level              = level;
521         r.in.buffer             = NULL;
522         r.in.offered            = 0;
523         r.out.needed            = &needed;
524         r.out.count             = &count;
525         r.out.info              = &info;
526
527         torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
528                 r.in.environment, r.in.level);
529
530         torture_assert_ntstatus_ok(tctx,
531                 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
532                 "EnumPrinterDrivers failed");
533         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
534                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
535                 r.in.buffer = &blob;
536                 r.in.offered = needed;
537
538                 torture_assert_ntstatus_ok(tctx,
539                         dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
540                         "EnumPrinterDrivers failed");
541         }
542
543         torture_assert_werr_ok(tctx, r.out.result,
544                 "EnumPrinterDrivers failed");
545
546         if (count_p) {
547                 *count_p = count;
548         }
549         if (info_p) {
550                 *info_p = info;
551         }
552
553         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
554
555         return true;
556
557 }
558
559 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
560                                             struct dcerpc_binding_handle *b,
561                                             const char *server_name,
562                                             const char *environment,
563                                             uint32_t level,
564                                             const char *driver_name)
565 {
566         uint32_t count;
567         union spoolss_DriverInfo *info;
568         int i;
569
570         torture_assert(tctx,
571                 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
572                 "failed to enumerate printer drivers");
573
574         for (i=0; i < count; i++) {
575                 const char *driver_name_ret;
576                 switch (level) {
577                 case 1:
578                         driver_name_ret = info[i].info1.driver_name;
579                         break;
580                 case 2:
581                         driver_name_ret = info[i].info2.driver_name;
582                         break;
583                 case 3:
584                         driver_name_ret = info[i].info3.driver_name;
585                         break;
586                 case 4:
587                         driver_name_ret = info[i].info4.driver_name;
588                         break;
589                 case 5:
590                         driver_name_ret = info[i].info5.driver_name;
591                         break;
592                 case 6:
593                         driver_name_ret = info[i].info6.driver_name;
594                         break;
595                 case 7:
596                         driver_name_ret = info[i].info7.driver_name;
597                         break;
598                 case 8:
599                         driver_name_ret = info[i].info8.driver_name;
600                         break;
601                 default:
602                         break;
603                 }
604                 if (strequal(driver_name, driver_name_ret)) {
605                         return true;
606                 }
607         }
608
609         return false;
610 }
611
612 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
613                                     void *private_data)
614 {
615         struct test_spoolss_context *ctx =
616                 talloc_get_type_abort(private_data, struct test_spoolss_context);
617         struct dcerpc_pipe *p = ctx->spoolss_pipe;
618         struct dcerpc_binding_handle *b = p->binding_handle;
619         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
620         int i, j, a;
621
622         /* FIXME: gd, come back and fix "" as server, and handle
623          * priority of returned error codes in torture test and samba 3
624          * server */
625         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
626         const char *environments[2];
627
628         environments[0] = SPOOLSS_ARCHITECTURE_ALL;
629         environments[1] = ctx->environment;
630
631         for (a=0;a<ARRAY_SIZE(environments);a++) {
632
633         for (i=0;i<ARRAY_SIZE(levels);i++) {
634                 int level = levels[i];
635                 uint32_t count;
636                 union spoolss_DriverInfo *info;
637
638                 torture_assert(tctx,
639                         test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
640                         "failed to enumerate drivers");
641
642                 ctx->driver_count[level]        = count;
643                 ctx->drivers[level]             = info;
644         }
645
646         for (i=1;i<ARRAY_SIZE(levels);i++) {
647                 int level = levels[i];
648                 int old_level = levels[i-1];
649
650                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
651                         "EnumPrinterDrivers invalid value");
652         }
653
654         for (i=0;i<ARRAY_SIZE(levels);i++) {
655                 int level = levels[i];
656
657                 for (j=0;j<ctx->driver_count[level];j++) {
658                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
659                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
660
661                         switch (level) {
662                         case 1:
663                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
664                                 break;
665                         case 2:
666                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
667                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
668                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
669                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
670                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
671                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
672                                 break;
673                         case 3:
674                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
675                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
676                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
677                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
678                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
679                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
680                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
681                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
682                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
683                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
684                                 break;
685                         case 4:
686                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
687                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
688                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
689                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
690                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
691                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
692                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
693                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
694                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
695                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
696                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
697                                 break;
698                         case 5:
699                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
700                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
701                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
702                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
703                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
704                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
705                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
706                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
707                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
708                                 break;
709                         case 6:
710                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
711                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
712                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
713                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
714                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
715                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
716                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
717                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
718                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
719                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
720                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
721                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
722                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
723                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
724                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
725                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
726                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
727                                 break;
728                         case 8:
729                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
730                                 break;
731                         }
732                 }
733         }
734         }
735
736         return true;
737 }
738
739 static bool test_EnumMonitors(struct torture_context *tctx,
740                               void *private_data)
741 {
742         struct test_spoolss_context *ctx =
743                 talloc_get_type_abort(private_data, struct test_spoolss_context);
744         struct dcerpc_pipe *p = ctx->spoolss_pipe;
745         struct dcerpc_binding_handle *b = p->binding_handle;
746         NTSTATUS status;
747         struct spoolss_EnumMonitors r;
748         uint16_t levels[] = { 1, 2 };
749         int i, j;
750
751         for (i=0;i<ARRAY_SIZE(levels);i++) {
752                 int level = levels[i];
753                 DATA_BLOB blob;
754                 uint32_t needed;
755                 uint32_t count;
756                 union spoolss_MonitorInfo *info;
757
758                 r.in.servername = "";
759                 r.in.level = level;
760                 r.in.buffer = NULL;
761                 r.in.offered = 0;
762                 r.out.needed = &needed;
763                 r.out.count = &count;
764                 r.out.info = &info;
765
766                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
767
768                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
769                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
770                 if (W_ERROR_IS_OK(r.out.result)) {
771                         /* TODO: do some more checks here */
772                         continue;
773                 }
774                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
775                         "EnumMonitors failed");
776
777                 blob = data_blob_talloc_zero(ctx, needed);
778                 r.in.buffer = &blob;
779                 r.in.offered = needed;
780
781                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
782                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
783
784                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
785
786                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
787
788                 ctx->monitor_count[level]       = count;
789                 ctx->monitors[level]            = info;
790         }
791
792         for (i=1;i<ARRAY_SIZE(levels);i++) {
793                 int level = levels[i];
794                 int old_level = levels[i-1];
795                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
796                                          "EnumMonitors invalid value");
797         }
798
799         for (i=0;i<ARRAY_SIZE(levels);i++) {
800                 int level = levels[i];
801                 for (j=0;j<ctx->monitor_count[level];j++) {
802                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
803                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
804                         switch (level) {
805                         case 1:
806                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
807                                 break;
808                         case 2:
809                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
810                                 break;
811                         }
812                 }
813         }
814
815         return true;
816 }
817
818 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
819                                            struct dcerpc_binding_handle *b,
820                                            const char *environment,
821                                            uint32_t level,
822                                            uint32_t *count_p,
823                                            union spoolss_PrintProcessorInfo **info_p,
824                                            WERROR expected_result)
825 {
826         struct spoolss_EnumPrintProcessors r;
827         DATA_BLOB blob;
828         uint32_t needed;
829         uint32_t count;
830         union spoolss_PrintProcessorInfo *info;
831
832         r.in.servername = "";
833         r.in.environment = environment;
834         r.in.level = level;
835         r.in.buffer = NULL;
836         r.in.offered = 0;
837         r.out.needed = &needed;
838         r.out.count = &count;
839         r.out.info = &info;
840
841         torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
842                 r.in.environment, r.in.level);
843
844         torture_assert_ntstatus_ok(tctx,
845                 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
846                 "EnumPrintProcessors failed");
847         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
848                 blob = data_blob_talloc_zero(tctx, needed);
849                 r.in.buffer = &blob;
850                 r.in.offered = needed;
851                 torture_assert_ntstatus_ok(tctx,
852                         dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
853                         "EnumPrintProcessors failed");
854         }
855         torture_assert_werr_equal(tctx, r.out.result, expected_result,
856                 "EnumPrintProcessors failed");
857
858         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
859
860         if (count_p) {
861                 *count_p = count;
862         }
863         if (info_p) {
864                 *info_p = info;
865         }
866
867         return true;
868 }
869
870 static bool test_EnumPrintProcessors(struct torture_context *tctx,
871                                      void *private_data)
872 {
873         struct test_spoolss_context *ctx =
874                 talloc_get_type_abort(private_data, struct test_spoolss_context);
875
876         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
877         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
878         int i;
879         struct dcerpc_pipe *p = ctx->spoolss_pipe;
880         struct dcerpc_binding_handle *b = p->binding_handle;
881
882         torture_assert(tctx,
883                 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
884                 "test_EnumPrintProcessors_level failed");
885
886         for (i=0;i<ARRAY_SIZE(levels);i++) {
887                 union spoolss_PrintProcessorInfo *info;
888                 uint32_t count;
889                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
890
891                 torture_assert(tctx,
892                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
893                         "test_EnumPrintProcessors_level failed");
894         }
895
896         return true;
897 }
898
899 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
900                                               struct dcerpc_binding_handle *b,
901                                               const char *print_processor_name,
902                                               uint32_t level,
903                                               uint32_t *count_p,
904                                               union spoolss_PrintProcDataTypesInfo **info_p,
905                                               WERROR expected_result)
906 {
907         struct spoolss_EnumPrintProcDataTypes r;
908         DATA_BLOB blob;
909         uint32_t needed;
910         uint32_t count;
911         union spoolss_PrintProcDataTypesInfo *info;
912
913         r.in.servername = "";
914         r.in.print_processor_name = print_processor_name;
915         r.in.level = level;
916         r.in.buffer = NULL;
917         r.in.offered = 0;
918         r.out.needed = &needed;
919         r.out.count = &count;
920         r.out.info = &info;
921
922         torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
923                 r.in.print_processor_name, r.in.level);
924
925         torture_assert_ntstatus_ok(tctx,
926                 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
927                 "EnumPrintProcDataTypes failed");
928         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
929                 blob = data_blob_talloc_zero(tctx, needed);
930                 r.in.buffer = &blob;
931                 r.in.offered = needed;
932                 torture_assert_ntstatus_ok(tctx,
933                         dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
934                         "EnumPrintProcDataTypes failed");
935         }
936         torture_assert_werr_equal(tctx, r.out.result, expected_result,
937                 "EnumPrintProcDataTypes failed");
938
939         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
940
941         if (count_p) {
942                 *count_p = count;
943         }
944         if (info_p) {
945                 *info_p = info;
946         }
947
948         return true;
949 }
950
951 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
952                                         void *private_data)
953 {
954         struct test_spoolss_context *ctx =
955                 talloc_get_type_abort(private_data, struct test_spoolss_context);
956
957         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
958         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
959         int i;
960         struct dcerpc_pipe *p = ctx->spoolss_pipe;
961         struct dcerpc_binding_handle *b = p->binding_handle;
962
963         torture_assert(tctx,
964                 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
965                 "test_EnumPrintProcDataTypes_level failed");
966
967         torture_assert(tctx,
968                 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
969                 "test_EnumPrintProcDataTypes_level failed");
970
971         for (i=0;i<ARRAY_SIZE(levels);i++) {
972                 int level = levels[i];
973                 uint32_t count;
974                 union spoolss_PrintProcDataTypesInfo *info;
975                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
976
977                 torture_assert(tctx,
978                         test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
979                         "test_EnumPrintProcDataTypes_level failed");
980         }
981
982         {
983                 union spoolss_PrintProcessorInfo *info;
984                 uint32_t count;
985
986                 torture_assert(tctx,
987                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
988                         "test_EnumPrintProcessors_level failed");
989
990                 for (i=0; i < count; i++) {
991                         torture_assert(tctx,
992                                 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
993                                 "test_EnumPrintProcDataTypes_level failed");
994                 }
995         }
996
997
998         return true;
999 }
1000
1001 static bool test_EnumPrinters(struct torture_context *tctx,
1002                               void *private_data)
1003 {
1004         struct test_spoolss_context *ctx =
1005                 talloc_get_type_abort(private_data, struct test_spoolss_context);
1006         struct dcerpc_pipe *p = ctx->spoolss_pipe;
1007         struct dcerpc_binding_handle *b = p->binding_handle;
1008         struct spoolss_EnumPrinters r;
1009         NTSTATUS status;
1010         uint16_t levels[] = { 0, 1, 2, 4, 5 };
1011         int i, j;
1012
1013         for (i=0;i<ARRAY_SIZE(levels);i++) {
1014                 int level = levels[i];
1015                 DATA_BLOB blob;
1016                 uint32_t needed;
1017                 uint32_t count;
1018                 union spoolss_PrinterInfo *info;
1019
1020                 r.in.flags      = PRINTER_ENUM_LOCAL;
1021                 r.in.server     = "";
1022                 r.in.level      = level;
1023                 r.in.buffer     = NULL;
1024                 r.in.offered    = 0;
1025                 r.out.needed    = &needed;
1026                 r.out.count     = &count;
1027                 r.out.info      = &info;
1028
1029                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1030
1031                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1032                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1033                 if (W_ERROR_IS_OK(r.out.result)) {
1034                         /* TODO: do some more checks here */
1035                         continue;
1036                 }
1037                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1038                         "EnumPrinters unexpected return code");
1039
1040                 blob = data_blob_talloc_zero(ctx, needed);
1041                 r.in.buffer = &blob;
1042                 r.in.offered = needed;
1043
1044                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1045                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1046
1047                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1048
1049                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1050
1051                 ctx->printer_count[level]       = count;
1052                 ctx->printers[level]            = info;
1053         }
1054
1055         for (i=1;i<ARRAY_SIZE(levels);i++) {
1056                 int level = levels[i];
1057                 int old_level = levels[i-1];
1058                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1059                                          "EnumPrinters invalid value");
1060         }
1061
1062         for (i=0;i<ARRAY_SIZE(levels);i++) {
1063                 int level = levels[i];
1064                 for (j=0;j<ctx->printer_count[level];j++) {
1065                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1066                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1067                         switch (level) {
1068                         case 0:
1069                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1070                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1071                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1072                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1073                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1074                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1075                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1076                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1077                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1078                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1079                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1080                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1081                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1082                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1083                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1084                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1085                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1086                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1087                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1088                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1089                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1090                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1091                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1092                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1093                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1094                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1095                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1096                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1097                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1098                                 break;
1099                         case 1:
1100                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1101                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1102                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1103                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1104                                 break;
1105                         case 2:
1106                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
1107                                 break;
1108                         case 4:
1109                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1110                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1111                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1112                                 break;
1113                         case 5:
1114                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1115                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1116                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1117                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1118                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1119                                 break;
1120                         }
1121                 }
1122         }
1123
1124         /* TODO:
1125          *      - verify that the port of a printer was in the list returned by EnumPorts
1126          */
1127
1128         return true;
1129 }
1130
1131 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1132                                    struct dcerpc_binding_handle *b,
1133                                    struct policy_handle *handle,
1134                                    const char *driver_name,
1135                                    const char *environment);
1136
1137 bool test_GetPrinter_level(struct torture_context *tctx,
1138                            struct dcerpc_binding_handle *b,
1139                            struct policy_handle *handle,
1140                            uint32_t level,
1141                            union spoolss_PrinterInfo *info)
1142 {
1143         struct spoolss_GetPrinter r;
1144         uint32_t needed;
1145
1146         r.in.handle = handle;
1147         r.in.level = level;
1148         r.in.buffer = NULL;
1149         r.in.offered = 0;
1150         r.out.needed = &needed;
1151
1152         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1153
1154         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1155                 "GetPrinter failed");
1156
1157         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1158                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1159                 r.in.buffer = &blob;
1160                 r.in.offered = needed;
1161
1162                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1163                         "GetPrinter failed");
1164         }
1165
1166         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1167
1168         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1169
1170         if (info && r.out.info) {
1171                 *info = *r.out.info;
1172         }
1173
1174         return true;
1175 }
1176
1177
1178 static bool test_GetPrinter(struct torture_context *tctx,
1179                             struct dcerpc_binding_handle *b,
1180                             struct policy_handle *handle,
1181                             const char *environment)
1182 {
1183         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1184         int i;
1185
1186         for (i=0;i<ARRAY_SIZE(levels);i++) {
1187
1188                 union spoolss_PrinterInfo info;
1189
1190                 ZERO_STRUCT(info);
1191
1192                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1193                         "failed to call GetPrinter");
1194
1195                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1196                         torture_assert(tctx,
1197                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1198                                 "failed to call test_GetPrinterDriver2");
1199                 }
1200         }
1201
1202         return true;
1203 }
1204
1205 static bool test_SetPrinter(struct torture_context *tctx,
1206                             struct dcerpc_binding_handle *b,
1207                             struct policy_handle *handle,
1208                             struct spoolss_SetPrinterInfoCtr *info_ctr,
1209                             struct spoolss_DevmodeContainer *devmode_ctr,
1210                             struct sec_desc_buf *secdesc_ctr,
1211                             enum spoolss_PrinterControl command)
1212 {
1213         struct spoolss_SetPrinter r;
1214
1215         r.in.handle = handle;
1216         r.in.info_ctr = info_ctr;
1217         r.in.devmode_ctr = devmode_ctr;
1218         r.in.secdesc_ctr = secdesc_ctr;
1219         r.in.command = command;
1220
1221         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1222
1223         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1224                 "failed to call SetPrinter");
1225         torture_assert_werr_ok(tctx, r.out.result,
1226                 "failed to call SetPrinter");
1227
1228         return true;
1229 }
1230
1231 static bool test_SetPrinter_errors(struct torture_context *tctx,
1232                                    struct dcerpc_binding_handle *b,
1233                                    struct policy_handle *handle)
1234 {
1235         struct spoolss_SetPrinter r;
1236         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1237         int i;
1238
1239         struct spoolss_SetPrinterInfoCtr info_ctr;
1240         struct spoolss_DevmodeContainer devmode_ctr;
1241         struct sec_desc_buf secdesc_ctr;
1242
1243         info_ctr.level = 0;
1244         info_ctr.info.info0 = NULL;
1245
1246         ZERO_STRUCT(devmode_ctr);
1247         ZERO_STRUCT(secdesc_ctr);
1248
1249         r.in.handle = handle;
1250         r.in.info_ctr = &info_ctr;
1251         r.in.devmode_ctr = &devmode_ctr;
1252         r.in.secdesc_ctr = &secdesc_ctr;
1253         r.in.command = 0;
1254
1255         torture_comment(tctx, "Testing SetPrinter all zero\n");
1256
1257         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1258                 "failed to call SetPrinter");
1259         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1260                 "failed to call SetPrinter");
1261
1262  again:
1263         for (i=0; i < ARRAY_SIZE(levels); i++) {
1264
1265                 struct spoolss_SetPrinterInfo0 info0;
1266                 struct spoolss_SetPrinterInfo1 info1;
1267                 struct spoolss_SetPrinterInfo2 info2;
1268                 struct spoolss_SetPrinterInfo3 info3;
1269                 struct spoolss_SetPrinterInfo4 info4;
1270                 struct spoolss_SetPrinterInfo5 info5;
1271                 struct spoolss_SetPrinterInfo6 info6;
1272                 struct spoolss_SetPrinterInfo7 info7;
1273                 struct spoolss_SetPrinterInfo8 info8;
1274                 struct spoolss_SetPrinterInfo9 info9;
1275
1276
1277                 info_ctr.level = levels[i];
1278                 switch (levels[i]) {
1279                 case 0:
1280                         ZERO_STRUCT(info0);
1281                         info_ctr.info.info0 = &info0;
1282                         break;
1283                 case 1:
1284                         ZERO_STRUCT(info1);
1285                         info_ctr.info.info1 = &info1;
1286                         break;
1287                 case 2:
1288                         ZERO_STRUCT(info2);
1289                         info_ctr.info.info2 = &info2;
1290                         break;
1291                 case 3:
1292                         ZERO_STRUCT(info3);
1293                         info_ctr.info.info3 = &info3;
1294                         break;
1295                 case 4:
1296                         ZERO_STRUCT(info4);
1297                         info_ctr.info.info4 = &info4;
1298                         break;
1299                 case 5:
1300                         ZERO_STRUCT(info5);
1301                         info_ctr.info.info5 = &info5;
1302                         break;
1303                 case 6:
1304                         ZERO_STRUCT(info6);
1305                         info_ctr.info.info6 = &info6;
1306                         break;
1307                 case 7:
1308                         ZERO_STRUCT(info7);
1309                         info_ctr.info.info7 = &info7;
1310                         break;
1311                 case 8:
1312                         ZERO_STRUCT(info8);
1313                         info_ctr.info.info8 = &info8;
1314                         break;
1315                 case 9:
1316                         ZERO_STRUCT(info9);
1317                         info_ctr.info.info9 = &info9;
1318                         break;
1319                 }
1320
1321                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1322                         info_ctr.level, r.in.command);
1323
1324                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1325                         "failed to call SetPrinter");
1326
1327                 switch (r.in.command) {
1328                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1329                         /* is ignored for all levels other then 0 */
1330                         if (info_ctr.level > 0) {
1331                                 /* ignored then */
1332                                 break;
1333                         }
1334                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1335                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1336                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1337                         if (info_ctr.level > 0) {
1338                                 /* is invalid for all levels other then 0 */
1339                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1340                                         "unexpected error code returned");
1341                                 continue;
1342                         } else {
1343                                 torture_assert_werr_ok(tctx, r.out.result,
1344                                         "failed to call SetPrinter with non 0 command");
1345                                 continue;
1346                         }
1347                         break;
1348
1349                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1350                         /* FIXME: gd needs further investigation */
1351                 default:
1352                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1353                                 "unexpected error code returned");
1354                         continue;
1355                 }
1356
1357                 switch (info_ctr.level) {
1358                 case 1:
1359                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1360                                 "unexpected error code returned");
1361                         break;
1362                 case 2:
1363                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1364                                 "unexpected error code returned");
1365                         break;
1366                 case 3:
1367                 case 4:
1368                 case 5:
1369                 case 7:
1370                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1371                                 "unexpected error code returned");
1372                         break;
1373                 case 9:
1374                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1375                                 "unexpected error code returned");
1376                         break;
1377                 default:
1378                         torture_assert_werr_ok(tctx, r.out.result,
1379                                 "failed to call SetPrinter");
1380                         break;
1381                 }
1382         }
1383
1384         if (r.in.command < 5) {
1385                 r.in.command++;
1386                 goto again;
1387         }
1388
1389         return true;
1390 }
1391
1392 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1393 {
1394         if ((r->level == 2) && (r->info.info2)) {
1395                 r->info.info2->secdesc_ptr = 0;
1396                 r->info.info2->devmode_ptr = 0;
1397         }
1398 }
1399
1400 static bool test_PrinterInfo(struct torture_context *tctx,
1401                              struct dcerpc_binding_handle *b,
1402                              struct policy_handle *handle)
1403 {
1404         NTSTATUS status;
1405         struct spoolss_SetPrinter s;
1406         struct spoolss_GetPrinter q;
1407         struct spoolss_GetPrinter q0;
1408         struct spoolss_SetPrinterInfoCtr info_ctr;
1409         union spoolss_PrinterInfo info;
1410         struct spoolss_DevmodeContainer devmode_ctr;
1411         struct sec_desc_buf secdesc_ctr;
1412         uint32_t needed;
1413         bool ret = true;
1414         int i;
1415
1416         torture_skip(tctx, "Printer Info test is currently broken, skipping");
1417
1418         uint32_t status_list[] = {
1419                 /* these do not stick
1420                 PRINTER_STATUS_PAUSED,
1421                 PRINTER_STATUS_ERROR,
1422                 PRINTER_STATUS_PENDING_DELETION, */
1423                 PRINTER_STATUS_PAPER_JAM,
1424                 PRINTER_STATUS_PAPER_OUT,
1425                 PRINTER_STATUS_MANUAL_FEED,
1426                 PRINTER_STATUS_PAPER_PROBLEM,
1427                 PRINTER_STATUS_OFFLINE,
1428                 PRINTER_STATUS_IO_ACTIVE,
1429                 PRINTER_STATUS_BUSY,
1430                 PRINTER_STATUS_PRINTING,
1431                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1432                 PRINTER_STATUS_NOT_AVAILABLE,
1433                 PRINTER_STATUS_WAITING,
1434                 PRINTER_STATUS_PROCESSING,
1435                 PRINTER_STATUS_INITIALIZING,
1436                 PRINTER_STATUS_WARMING_UP,
1437                 PRINTER_STATUS_TONER_LOW,
1438                 PRINTER_STATUS_NO_TONER,
1439                 PRINTER_STATUS_PAGE_PUNT,
1440                 PRINTER_STATUS_USER_INTERVENTION,
1441                 PRINTER_STATUS_OUT_OF_MEMORY,
1442                 PRINTER_STATUS_DOOR_OPEN,
1443                 PRINTER_STATUS_SERVER_UNKNOWN,
1444                 PRINTER_STATUS_POWER_SAVE,
1445                 /* these do not stick
1446                 0x02000000,
1447                 0x04000000,
1448                 0x08000000,
1449                 0x10000000,
1450                 0x20000000,
1451                 0x40000000,
1452                 0x80000000 */
1453         };
1454         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1455         uint32_t attribute_list[] = {
1456                 PRINTER_ATTRIBUTE_QUEUED,
1457                 /* fails with WERR_INVALID_DATATYPE:
1458                 PRINTER_ATTRIBUTE_DIRECT, */
1459                 /* does not stick
1460                 PRINTER_ATTRIBUTE_DEFAULT, */
1461                 PRINTER_ATTRIBUTE_SHARED,
1462                 /* does not stick
1463                 PRINTER_ATTRIBUTE_NETWORK, */
1464                 PRINTER_ATTRIBUTE_HIDDEN,
1465                 PRINTER_ATTRIBUTE_LOCAL,
1466                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1467                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1468                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1469                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1470                 /* does not stick
1471                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1472                 /* fails with WERR_INVALID_DATATYPE:
1473                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1474                 /* these do not stick
1475                 PRINTER_ATTRIBUTE_PUBLISHED,
1476                 PRINTER_ATTRIBUTE_FAX,
1477                 PRINTER_ATTRIBUTE_TS,
1478                 0x00010000,
1479                 0x00020000,
1480                 0x00040000,
1481                 0x00080000,
1482                 0x00100000,
1483                 0x00200000,
1484                 0x00400000,
1485                 0x00800000,
1486                 0x01000000,
1487                 0x02000000,
1488                 0x04000000,
1489                 0x08000000,
1490                 0x10000000,
1491                 0x20000000,
1492                 0x40000000,
1493                 0x80000000 */
1494         };
1495
1496         ZERO_STRUCT(devmode_ctr);
1497         ZERO_STRUCT(secdesc_ctr);
1498
1499         s.in.handle = handle;
1500         s.in.command = 0;
1501         s.in.info_ctr = &info_ctr;
1502         s.in.devmode_ctr = &devmode_ctr;
1503         s.in.secdesc_ctr = &secdesc_ctr;
1504
1505         q.in.handle = handle;
1506         q.out.info = &info;
1507         q0 = q;
1508
1509 #define TESTGETCALL(call, r) \
1510                 r.in.buffer = NULL; \
1511                 r.in.offered = 0;\
1512                 r.out.needed = &needed; \
1513                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1514                 if (!NT_STATUS_IS_OK(status)) { \
1515                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1516                                r.in.level, nt_errstr(status), __location__); \
1517                         ret = false; \
1518                         break; \
1519                 }\
1520                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1521                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1522                         r.in.buffer = &blob; \
1523                         r.in.offered = needed; \
1524                 }\
1525                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1526                 if (!NT_STATUS_IS_OK(status)) { \
1527                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1528                                r.in.level, nt_errstr(status), __location__); \
1529                         ret = false; \
1530                         break; \
1531                 } \
1532                 if (!W_ERROR_IS_OK(r.out.result)) { \
1533                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1534                                r.in.level, win_errstr(r.out.result), __location__); \
1535                         ret = false; \
1536                         break; \
1537                 }
1538
1539
1540 #define TESTSETCALL_EXP(call, r, err) \
1541                 clear_info2(&info_ctr);\
1542                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1543                 if (!NT_STATUS_IS_OK(status)) { \
1544                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1545                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1546                         ret = false; \
1547                         break; \
1548                 } \
1549                 if (!W_ERROR_IS_OK(err)) { \
1550                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1551                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1552                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1553                                 ret = false; \
1554                         } \
1555                         break; \
1556                 } \
1557                 if (!W_ERROR_IS_OK(r.out.result)) { \
1558                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1560                         ret = false; \
1561                         break; \
1562                 }
1563
1564 #define TESTSETCALL(call, r) \
1565         TESTSETCALL_EXP(call, r, WERR_OK)
1566
1567 #define STRING_EQUAL(s1, s2, field) \
1568                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1569                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1570                                #field, s2, __location__); \
1571                         ret = false; \
1572                         break; \
1573                 }
1574
1575 #define MEM_EQUAL(s1, s2, length, field) \
1576                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1577                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1578                                #field, (const char *)s2, __location__); \
1579                         ret = false; \
1580                         break; \
1581                 }
1582
1583 #define INT_EQUAL(i1, i2, field) \
1584                 if (i1 != i2) { \
1585                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1586                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1587                         ret = false; \
1588                         break; \
1589                 }
1590
1591 #define SD_EQUAL(sd1, sd2, field) \
1592                 if (!security_descriptor_equal(sd1, sd2)) { \
1593                         torture_comment(tctx, "Failed to set %s (%s)\n", \
1594                                #field, __location__); \
1595                         ret = false; \
1596                         break; \
1597                 }
1598
1599 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1600                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1601                 q.in.level = lvl1; \
1602                 TESTGETCALL(GetPrinter, q) \
1603                 info_ctr.level = lvl1; \
1604                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1605                 info_ctr.info.info ## lvl1->field1 = value;\
1606                 TESTSETCALL_EXP(SetPrinter, s, err) \
1607                 info_ctr.info.info ## lvl1->field1 = ""; \
1608                 TESTGETCALL(GetPrinter, q) \
1609                 info_ctr.info.info ## lvl1->field1 = value; \
1610                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1611                 q.in.level = lvl2; \
1612                 TESTGETCALL(GetPrinter, q) \
1613                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1614                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1615         } while (0)
1616
1617 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1618         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1619         } while (0);
1620
1621 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1622                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1623                 q.in.level = lvl1; \
1624                 TESTGETCALL(GetPrinter, q) \
1625                 info_ctr.level = lvl1; \
1626                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1627                 info_ctr.info.info ## lvl1->field1 = value; \
1628                 TESTSETCALL(SetPrinter, s) \
1629                 info_ctr.info.info ## lvl1->field1 = 0; \
1630                 TESTGETCALL(GetPrinter, q) \
1631                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1632                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1633                 q.in.level = lvl2; \
1634                 TESTGETCALL(GetPrinter, q) \
1635                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1636                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1637         } while (0)
1638
1639 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1640         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1641         } while (0)
1642
1643         q0.in.level = 0;
1644         do { TESTGETCALL(GetPrinter, q0) } while (0);
1645
1646         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1647         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1648
1649         /* level 0 printername does not stick */
1650 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1651         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1652         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1653         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1654         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1655 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1656         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1657         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1658         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1659         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1660 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1661         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1662         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1663         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1664         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1665
1666         /* servername can be set but does not stick
1667         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1668         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1669         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1670         */
1671
1672         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1673         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1674         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1675         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1676         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1677
1678         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1679         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1680         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1681         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1682         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1683         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1684         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1685         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1686         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1687         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1688
1689         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1690 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1691                         attribute_list[i],
1692                         (attribute_list[i] | default_attribute)
1693                         ); */
1694                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1695                         attribute_list[i],
1696                         (attribute_list[i] | default_attribute)
1697                         );
1698                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1699                         attribute_list[i],
1700                         (attribute_list[i] | default_attribute)
1701                         );
1702                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1703                         attribute_list[i],
1704                         (attribute_list[i] | default_attribute)
1705                         );
1706 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1707                         attribute_list[i],
1708                         (attribute_list[i] | default_attribute)
1709                         ); */
1710                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1711                         attribute_list[i],
1712                         (attribute_list[i] | default_attribute)
1713                         );
1714                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1715                         attribute_list[i],
1716                         (attribute_list[i] | default_attribute)
1717                         );
1718                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1719                         attribute_list[i],
1720                         (attribute_list[i] | default_attribute)
1721                         );
1722 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1723                         attribute_list[i],
1724                         (attribute_list[i] | default_attribute)
1725                         ); */
1726                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1727                         attribute_list[i],
1728                         (attribute_list[i] | default_attribute)
1729                         );
1730                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1731                         attribute_list[i],
1732                         (attribute_list[i] | default_attribute)
1733                         );
1734                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1735                         attribute_list[i],
1736                         (attribute_list[i] | default_attribute)
1737                         );
1738         }
1739
1740         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1741                 /* level 2 sets do not stick
1742                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1743                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1744                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1745                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1746                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1747                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1748         }
1749
1750         /* priorities need to be between 0 and 99
1751            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1752         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1753         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1754         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1755         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1756         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1757         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1758         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1759         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1760
1761         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1762         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1763
1764         /* does not stick
1765         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1766         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1767
1768         /* does not stick
1769         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1770         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1771
1772         /* FIXME: gd also test devmode and secdesc behavior */
1773
1774         {
1775                 /* verify composition of level 1 description field */
1776                 const char *description;
1777                 const char *tmp;
1778
1779                 q0.in.level = 1;
1780                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1781
1782                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1783
1784                 q0.in.level = 2;
1785                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1786
1787                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1788                         q0.out.info->info2.printername,
1789                         q0.out.info->info2.drivername,
1790                         q0.out.info->info2.location);
1791
1792                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1793         }
1794
1795         return ret;
1796 }
1797
1798 static bool test_security_descriptor_equal(struct torture_context *tctx,
1799                                            const struct security_descriptor *sd1,
1800                                            const struct security_descriptor *sd2)
1801 {
1802         if (sd1 == sd2) {
1803                 return true;
1804         }
1805
1806         if (!sd1 || !sd2) {
1807                 torture_comment(tctx, "%s\n", __location__);
1808                 return false;
1809         }
1810
1811         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1812         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1813
1814         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1815         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1816
1817         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1818                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1819                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1820                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1821                 return false;
1822         }
1823         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1824                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1825                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1826                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1827                 return false;
1828         }
1829
1830         return true;
1831 }
1832
1833 static bool test_sd_set_level(struct torture_context *tctx,
1834                               struct dcerpc_binding_handle *b,
1835                               struct policy_handle *handle,
1836                               uint32_t level,
1837                               struct security_descriptor *sd)
1838 {
1839         struct spoolss_SetPrinterInfoCtr info_ctr;
1840         struct spoolss_DevmodeContainer devmode_ctr;
1841         struct sec_desc_buf secdesc_ctr;
1842         union spoolss_SetPrinterInfo sinfo;
1843
1844         ZERO_STRUCT(devmode_ctr);
1845         ZERO_STRUCT(secdesc_ctr);
1846
1847         switch (level) {
1848         case 2: {
1849                 union spoolss_PrinterInfo info;
1850                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1851                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1852
1853                 info_ctr.level = 2;
1854                 info_ctr.info = sinfo;
1855
1856                 break;
1857         }
1858         case 3: {
1859                 struct spoolss_SetPrinterInfo3 info3;
1860
1861                 info3.sec_desc_ptr = 0;
1862
1863                 info_ctr.level = 3;
1864                 info_ctr.info.info3 = &info3;
1865
1866                 break;
1867         }
1868         default:
1869                 return false;
1870         }
1871
1872         secdesc_ctr.sd = sd;
1873
1874         torture_assert(tctx,
1875                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1876
1877         return true;
1878 }
1879
1880 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1881                                  struct dcerpc_binding_handle *b,
1882                                  struct policy_handle *handle)
1883 {
1884         union spoolss_PrinterInfo info;
1885         struct security_descriptor *sd1, *sd2;
1886         int i;
1887
1888         /* just compare level 2 and level 3 */
1889
1890         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1891
1892         sd1 = info.info2.secdesc;
1893
1894         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1895
1896         sd2 = info.info3.secdesc;
1897
1898         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1899                 "SD level 2 != SD level 3");
1900
1901
1902         /* query level 2, set level 2, query level 2 */
1903
1904         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1905
1906         sd1 = info.info2.secdesc;
1907
1908         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1909
1910         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1911
1912         sd2 = info.info2.secdesc;
1913         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1914                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1915                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1916         }
1917
1918         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1919                 "SD level 2 != SD level 2 after SD has been set via level 2");
1920
1921
1922         /* query level 2, set level 3, query level 2 */
1923
1924         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1925
1926         sd1 = info.info2.secdesc;
1927
1928         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1929
1930         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931
1932         sd2 = info.info2.secdesc;
1933
1934         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1935                 "SD level 2 != SD level 2 after SD has been set via level 3");
1936
1937         /* set modified sd level 3, query level 2 */
1938
1939         for (i=0; i < 93; i++) {
1940                 struct security_ace a;
1941                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1942                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1943                 a.flags = 0;
1944                 a.size = 0; /* autogenerated */
1945                 a.access_mask = 0;
1946                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1947                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1948         }
1949
1950         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1951
1952         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1953         sd2 = info.info2.secdesc;
1954
1955         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1956                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1957                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1958         }
1959
1960         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1961                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1962
1963
1964         return true;
1965 }
1966
1967 /*
1968  * wrapper call that saves original sd, runs tests, and restores sd
1969  */
1970
1971 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1972                                 struct dcerpc_binding_handle *b,
1973                                 struct policy_handle *handle)
1974 {
1975         union spoolss_PrinterInfo info;
1976         struct security_descriptor *sd;
1977         bool ret = true;
1978
1979         torture_comment(tctx, "Testing Printer Security Descriptors\n");
1980
1981         /* save original sd */
1982
1983         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1984                 "failed to get initial security descriptor");
1985
1986         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1987
1988         /* run tests */
1989
1990         ret = test_PrinterInfo_SDs(tctx, b, handle);
1991
1992         /* restore original sd */
1993
1994         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1995                 "failed to restore initial security descriptor");
1996
1997         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1998                 ret ? "succeeded" : "failed");
1999
2000
2001         return ret;
2002 }
2003
2004 static bool test_devmode_set_level(struct torture_context *tctx,
2005                                    struct dcerpc_binding_handle *b,
2006                                    struct policy_handle *handle,
2007                                    uint32_t level,
2008                                    struct spoolss_DeviceMode *devmode)
2009 {
2010         struct spoolss_SetPrinterInfoCtr info_ctr;
2011         struct spoolss_DevmodeContainer devmode_ctr;
2012         struct sec_desc_buf secdesc_ctr;
2013         union spoolss_SetPrinterInfo sinfo;
2014
2015         ZERO_STRUCT(devmode_ctr);
2016         ZERO_STRUCT(secdesc_ctr);
2017
2018         switch (level) {
2019         case 2: {
2020                 union spoolss_PrinterInfo info;
2021                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2022                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2023
2024                 info_ctr.level = 2;
2025                 info_ctr.info = sinfo;
2026
2027                 break;
2028         }
2029         case 8: {
2030                 struct spoolss_SetPrinterInfo8 info8;
2031
2032                 info8.devmode_ptr = 0;
2033
2034                 info_ctr.level = 8;
2035                 info_ctr.info.info8 = &info8;
2036
2037                 break;
2038         }
2039         default:
2040                 return false;
2041         }
2042
2043         devmode_ctr.devmode = devmode;
2044
2045         torture_assert(tctx,
2046                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2047
2048         return true;
2049 }
2050
2051
2052 static bool test_devicemode_equal(struct torture_context *tctx,
2053                                   const struct spoolss_DeviceMode *d1,
2054                                   const struct spoolss_DeviceMode *d2)
2055 {
2056         if (d1 == d2) {
2057                 return true;
2058         }
2059
2060         if (!d1 || !d2) {
2061                 torture_comment(tctx, "%s\n", __location__);
2062                 return false;
2063         }
2064         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2065         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2066         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2067         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2068         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2069         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2070         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2071         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2072         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2073         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2074         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2075         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2076         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2077         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2078         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2079         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2080         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2081         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2082         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2083         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2084         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2085         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2086         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2087         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2088         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2089         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2090         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2091         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2092         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2093         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2094         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2095         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2096         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2097         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2098         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2099
2100         return true;
2101 }
2102
2103 static bool test_devicemode_full(struct torture_context *tctx,
2104                                  struct dcerpc_binding_handle *b,
2105                                  struct policy_handle *handle)
2106 {
2107         struct spoolss_SetPrinter s;
2108         struct spoolss_GetPrinter q;
2109         struct spoolss_GetPrinter q0;
2110         struct spoolss_SetPrinterInfoCtr info_ctr;
2111         struct spoolss_SetPrinterInfo8 info8;
2112         union spoolss_PrinterInfo info;
2113         struct spoolss_DevmodeContainer devmode_ctr;
2114         struct sec_desc_buf secdesc_ctr;
2115         uint32_t needed;
2116         bool ret = true;
2117         NTSTATUS status;
2118
2119 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2120                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2121                 q.in.level = lvl1; \
2122                 TESTGETCALL(GetPrinter, q) \
2123                 info_ctr.level = lvl1; \
2124                 if (lvl1 == 2) {\
2125                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2126                 } else if (lvl1 == 8) {\
2127                         info_ctr.info.info ## lvl1 = &info8; \
2128                 }\
2129                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2130                 devmode_ctr.devmode->field1 = value; \
2131                 TESTSETCALL(SetPrinter, s) \
2132                 TESTGETCALL(GetPrinter, q) \
2133                 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2134                 q.in.level = lvl2; \
2135                 TESTGETCALL(GetPrinter, q) \
2136                 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2137         } while (0)
2138
2139 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2140         TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2141         } while (0)
2142
2143         ZERO_STRUCT(devmode_ctr);
2144         ZERO_STRUCT(secdesc_ctr);
2145         ZERO_STRUCT(info8);
2146
2147         s.in.handle = handle;
2148         s.in.command = 0;
2149         s.in.info_ctr = &info_ctr;
2150         s.in.devmode_ctr = &devmode_ctr;
2151         s.in.secdesc_ctr = &secdesc_ctr;
2152
2153         q.in.handle = handle;
2154         q.out.info = &info;
2155         q0 = q;
2156
2157 #if 0
2158         const char *devicename;/* [charset(UTF16)] */
2159         enum spoolss_DeviceModeSpecVersion specversion;
2160         uint16_t driverversion;
2161         uint16_t size;
2162         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2163         uint32_t fields;
2164 #endif
2165
2166         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
2167         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
2168         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
2169         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
2170         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
2171         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
2172         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
2173         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
2174         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
2175         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
2176         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
2177         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
2178         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
2179 #if 0
2180         const char *formname;/* [charset(UTF16)] */
2181 #endif
2182         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
2183         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
2184         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
2185         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
2186         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
2187         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
2188         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
2189         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
2190         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
2191         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
2192         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
2193         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
2194         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
2195         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
2196
2197         return ret;
2198 }
2199
2200 static bool call_OpenPrinterEx(struct torture_context *tctx,
2201                                struct dcerpc_pipe *p,
2202                                const char *name,
2203                                struct spoolss_DeviceMode *devmode,
2204                                struct policy_handle *handle);
2205
2206 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2207                                       struct dcerpc_pipe *p,
2208                                       struct policy_handle *handle,
2209                                       const char *name)
2210 {
2211         union spoolss_PrinterInfo info;
2212         struct spoolss_DeviceMode *devmode;
2213         struct spoolss_DeviceMode *devmode2;
2214         struct policy_handle handle_devmode;
2215         struct dcerpc_binding_handle *b = p->binding_handle;
2216
2217         /* simply compare level8 and level2 devmode */
2218
2219         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2220
2221         devmode = info.info8.devmode;
2222
2223         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2224
2225         devmode2 = info.info2.devmode;
2226
2227         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2228                 "DM level 8 != DM level 2");
2229
2230
2231         /* set devicemode level 8 and see if it persists */
2232
2233         devmode->copies = 93;
2234         devmode->formname = talloc_strdup(tctx, "Legal");
2235
2236         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2237
2238         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2239
2240         devmode2 = info.info8.devmode;
2241
2242         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2243                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2244
2245         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2246
2247         devmode2 = info.info2.devmode;
2248
2249         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2250                 "modified DM level 8 != DM level 2");
2251
2252
2253         /* set devicemode level 2 and see if it persists */
2254
2255         devmode->copies = 39;
2256         devmode->formname = talloc_strdup(tctx, "Executive");
2257
2258         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2259
2260         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2261
2262         devmode2 = info.info8.devmode;
2263
2264         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2265                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2266
2267         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2268
2269         devmode2 = info.info2.devmode;
2270
2271         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2272                 "modified DM level 8 != DM level 2");
2273
2274
2275         /* check every single bit in public part of devicemode */
2276
2277         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2278                 "failed to set every single devicemode component");
2279
2280
2281         /* change formname upon open and see if it persists in getprinter calls */
2282
2283         devmode->formname = talloc_strdup(tctx, "A4");
2284         devmode->copies = 42;
2285
2286         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2287                 "failed to open printer handle");
2288
2289         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2290
2291         devmode2 = info.info8.devmode;
2292
2293         if (strequal(devmode->devicename, devmode2->devicename)) {
2294                 torture_warning(tctx, "devicenames are the same\n");
2295         } else {
2296                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2297                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2298         }
2299
2300         if (strequal(devmode->formname, devmode2->formname)) {
2301                 torture_warning(tctx, "formname are the same\n");
2302         } else {
2303                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2304                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2305         }
2306
2307         if (devmode->copies == devmode2->copies) {
2308                 torture_warning(tctx, "copies are the same\n");
2309         } else {
2310                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2311                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2312         }
2313
2314         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2315
2316         devmode2 = info.info2.devmode;
2317
2318         if (strequal(devmode->devicename, devmode2->devicename)) {
2319                 torture_warning(tctx, "devicenames are the same\n");
2320         } else {
2321                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2322                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2323         }
2324
2325         if (strequal(devmode->formname, devmode2->formname)) {
2326                 torture_warning(tctx, "formname is the same\n");
2327         } else {
2328                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2329                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2330         }
2331
2332         if (devmode->copies == devmode2->copies) {
2333                 torture_warning(tctx, "copies are the same\n");
2334         } else {
2335                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2336                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2337         }
2338
2339         test_ClosePrinter(tctx, b, &handle_devmode);
2340
2341         return true;
2342 }
2343
2344 /*
2345  * wrapper call that saves original devmode, runs tests, and restores devmode
2346  */
2347
2348 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2349                                      struct dcerpc_pipe *p,
2350                                      struct policy_handle *handle,
2351                                      const char *name,
2352                                      struct spoolss_DeviceMode *addprinter_devmode)
2353 {
2354         union spoolss_PrinterInfo info;
2355         struct spoolss_DeviceMode *devmode;
2356         bool ret = true;
2357         struct dcerpc_binding_handle *b = p->binding_handle;
2358
2359         torture_comment(tctx, "Testing Printer Devicemodes\n");
2360
2361         /* save original devmode */
2362
2363         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2364                 "failed to get initial global devicemode");
2365
2366         devmode = info.info8.devmode;
2367
2368         if (addprinter_devmode) {
2369                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2370                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
2371                 }
2372         }
2373
2374         /* run tests */
2375
2376         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2377
2378         /* restore original devmode */
2379
2380         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2381                 "failed to restore initial global device mode");
2382
2383         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2384                 ret ? "succeeded" : "failed");
2385
2386
2387         return ret;
2388 }
2389
2390 bool test_ClosePrinter(struct torture_context *tctx,
2391                        struct dcerpc_binding_handle *b,
2392                        struct policy_handle *handle)
2393 {
2394         NTSTATUS status;
2395         struct spoolss_ClosePrinter r;
2396
2397         r.in.handle = handle;
2398         r.out.handle = handle;
2399
2400         torture_comment(tctx, "Testing ClosePrinter\n");
2401
2402         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2403         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2404         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2405
2406         return true;
2407 }
2408
2409 static bool test_GetForm_args(struct torture_context *tctx,
2410                               struct dcerpc_binding_handle *b,
2411                               struct policy_handle *handle,
2412                               const char *form_name,
2413                               uint32_t level,
2414                               union spoolss_FormInfo *info_p)
2415 {
2416         NTSTATUS status;
2417         struct spoolss_GetForm r;
2418         uint32_t needed;
2419
2420         r.in.handle = handle;
2421         r.in.form_name = form_name;
2422         r.in.level = level;
2423         r.in.buffer = NULL;
2424         r.in.offered = 0;
2425         r.out.needed = &needed;
2426
2427         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2428
2429         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2430         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2431
2432         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2433                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2434                 r.in.buffer = &blob;
2435                 r.in.offered = needed;
2436                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2437                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2438
2439                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2440
2441                 torture_assert(tctx, r.out.info, "No form info returned");
2442         }
2443
2444         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2445
2446         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2447
2448         if (info_p) {
2449                 *info_p = *r.out.info;
2450         }
2451
2452         return true;
2453 }
2454
2455 static bool test_GetForm(struct torture_context *tctx,
2456                          struct dcerpc_binding_handle *b,
2457                          struct policy_handle *handle,
2458                          const char *form_name,
2459                          uint32_t level)
2460 {
2461         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2462 }
2463
2464 static bool test_EnumForms(struct torture_context *tctx,
2465                            struct dcerpc_binding_handle *b,
2466                            struct policy_handle *handle,
2467                            bool print_server,
2468                            uint32_t level,
2469                            uint32_t *count_p,
2470                            union spoolss_FormInfo **info_p)
2471 {
2472         struct spoolss_EnumForms r;
2473         uint32_t needed;
2474         uint32_t count;
2475         union spoolss_FormInfo *info;
2476
2477         r.in.handle = handle;
2478         r.in.level = level;
2479         r.in.buffer = NULL;
2480         r.in.offered = 0;
2481         r.out.needed = &needed;
2482         r.out.count = &count;
2483         r.out.info = &info;
2484
2485         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2486
2487         torture_assert_ntstatus_ok(tctx,
2488                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2489                 "EnumForms failed");
2490
2491         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2492                 torture_skip(tctx, "EnumForms level 2 not supported");
2493         }
2494
2495         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2496                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2497         }
2498
2499         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2500                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2501                 r.in.buffer = &blob;
2502                 r.in.offered = needed;
2503
2504                 torture_assert_ntstatus_ok(tctx,
2505                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2506                         "EnumForms failed");
2507
2508                 torture_assert(tctx, info, "No forms returned");
2509         }
2510
2511         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2512
2513         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2514
2515         if (info_p) {
2516                 *info_p = info;
2517         }
2518         if (count_p) {
2519                 *count_p = count;
2520         }
2521
2522         return true;
2523 }
2524
2525 static bool test_EnumForms_all(struct torture_context *tctx,
2526                                struct dcerpc_binding_handle *b,
2527                                struct policy_handle *handle,
2528                                bool print_server)
2529 {
2530         uint32_t levels[] = { 1, 2 };
2531         int i, j;
2532
2533         for (i=0; i<ARRAY_SIZE(levels); i++) {
2534
2535                 uint32_t count = 0;
2536                 union spoolss_FormInfo *info = NULL;
2537
2538                 torture_assert(tctx,
2539                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2540                         "failed to enum forms");
2541
2542                 for (j = 0; j < count; j++) {
2543                         if (!print_server) {
2544                                 torture_assert(tctx,
2545                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2546                                         "failed to get form");
2547                         }
2548                 }
2549         }
2550
2551         return true;
2552 }
2553
2554 static bool test_EnumForms_find_one(struct torture_context *tctx,
2555                                     struct dcerpc_binding_handle *b,
2556                                     struct policy_handle *handle,
2557                                     bool print_server,
2558                                     const char *form_name)
2559 {
2560         union spoolss_FormInfo *info;
2561         uint32_t count;
2562         bool found = false;
2563         int i;
2564
2565         torture_assert(tctx,
2566                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2567                 "failed to enumerate forms");
2568
2569         for (i=0; i<count; i++) {
2570                 if (strequal(form_name, info[i].info1.form_name)) {
2571                         found = true;
2572                         break;
2573                 }
2574         }
2575
2576         return found;
2577 }
2578
2579 static bool test_DeleteForm(struct torture_context *tctx,
2580                             struct dcerpc_binding_handle *b,
2581                             struct policy_handle *handle,
2582                             const char *form_name,
2583                             WERROR expected_result)
2584 {
2585         struct spoolss_DeleteForm r;
2586
2587         r.in.handle = handle;
2588         r.in.form_name = form_name;
2589
2590         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2591
2592         torture_assert_ntstatus_ok(tctx,
2593                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2594                 "DeleteForm failed");
2595         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2596                 "DeleteForm gave unexpected result");
2597         if (W_ERROR_IS_OK(r.out.result)) {
2598                 torture_assert_ntstatus_ok(tctx,
2599                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2600                         "2nd DeleteForm failed");
2601                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2602                         "2nd DeleteForm failed");
2603         }
2604
2605         return true;
2606 }
2607
2608 static bool test_AddForm(struct torture_context *tctx,
2609                          struct dcerpc_binding_handle *b,
2610                          struct policy_handle *handle,
2611                          uint32_t level,
2612                          union spoolss_AddFormInfo *info,
2613                          WERROR expected_result)
2614 {
2615         struct spoolss_AddForm r;
2616
2617         if (level != 1) {
2618                 torture_skip(tctx, "only level 1 supported");
2619         }
2620
2621         r.in.handle     = handle;
2622         r.in.level      = level;
2623         r.in.info       = *info;
2624
2625         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2626                 r.in.info.info1->form_name, r.in.level,
2627                 r.in.info.info1->flags);
2628
2629         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2630                 "AddForm failed");
2631         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2632                 "AddForm gave unexpected result");
2633
2634         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2635                 "2nd AddForm failed");
2636         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2637                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2638                         "2nd AddForm gave unexpected result");
2639         } else {
2640                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2641                         "2nd AddForm gave unexpected result");
2642         }
2643
2644         return true;
2645 }
2646
2647 static bool test_SetForm(struct torture_context *tctx,
2648                          struct dcerpc_binding_handle *b,
2649                          struct policy_handle *handle,
2650                          const char *form_name,
2651                          uint32_t level,
2652                          union spoolss_AddFormInfo *info)
2653 {
2654         struct spoolss_SetForm r;
2655
2656         r.in.handle     = handle;
2657         r.in.form_name  = form_name;
2658         r.in.level      = level;
2659         r.in.info       = *info;
2660
2661         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2662                 form_name, r.in.level);
2663
2664         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2665                 "SetForm failed");
2666
2667         torture_assert_werr_ok(tctx, r.out.result,
2668                 "SetForm failed");
2669
2670         return true;
2671 }
2672
2673 static bool test_GetForm_winreg(struct torture_context *tctx,
2674                                 struct dcerpc_binding_handle *b,
2675                                 struct policy_handle *handle,
2676                                 const char *key_name,
2677                                 const char *form_name,
2678                                 enum winreg_Type *w_type,
2679                                 uint32_t *w_size,
2680                                 uint32_t *w_length,
2681                                 uint8_t **w_data);
2682
2683 static bool test_Forms_args(struct torture_context *tctx,
2684                             struct dcerpc_binding_handle *b,
2685                             struct policy_handle *handle,
2686                             bool print_server,
2687                             const char *printer_name,
2688                             struct dcerpc_binding_handle *winreg_handle,
2689                             struct policy_handle *hive_handle,
2690                             const char *form_name,
2691                             struct spoolss_AddFormInfo1 *info1,
2692                             WERROR expected_add_result,
2693                             WERROR expected_delete_result)
2694 {
2695         union spoolss_FormInfo info;
2696         union spoolss_AddFormInfo add_info;
2697
2698         enum winreg_Type w_type;
2699         uint32_t w_size;
2700         uint32_t w_length;
2701         uint8_t *w_data;
2702
2703         add_info.info1 = info1;
2704
2705         torture_assert(tctx,
2706                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2707                 "failed to add form");
2708
2709         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2710
2711                 struct spoolss_FormInfo1 i1;
2712
2713                 torture_assert(tctx,
2714                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2715                         "failed to get form via winreg");
2716
2717                 i1.size.width   = IVAL(w_data, 0);
2718                 i1.size.height  = IVAL(w_data, 4);
2719                 i1.area.left    = IVAL(w_data, 8);
2720                 i1.area.top     = IVAL(w_data, 12);
2721                 i1.area.right   = IVAL(w_data, 16);
2722                 i1.area.bottom  = IVAL(w_data, 20);
2723                 /* skip index here */
2724                 i1.flags        = IVAL(w_data, 28);
2725
2726                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2727                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2728                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2729                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2730                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2731                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2732                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2733                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2734                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2735                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2736         }
2737
2738         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2739                 torture_assert(tctx,
2740                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2741                         "failed to get added form");
2742
2743                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2744                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2745                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2746                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2747                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2748                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2749                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2750
2751                 if (winreg_handle && hive_handle) {
2752
2753                         struct spoolss_FormInfo1 i1;
2754
2755                         i1.size.width   = IVAL(w_data, 0);
2756                         i1.size.height  = IVAL(w_data, 4);
2757                         i1.area.left    = IVAL(w_data, 8);
2758                         i1.area.top     = IVAL(w_data, 12);
2759                         i1.area.right   = IVAL(w_data, 16);
2760                         i1.area.bottom  = IVAL(w_data, 20);
2761                         /* skip index here */
2762                         i1.flags        = IVAL(w_data, 28);
2763
2764                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2765                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2766                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2767                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2768                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2769                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2770                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2771                 }
2772
2773                 add_info.info1->size.width = 1234;
2774
2775                 torture_assert(tctx,
2776                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2777                         "failed to set form");
2778                 torture_assert(tctx,
2779                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2780                         "failed to get setted form");
2781
2782                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2783         }
2784
2785         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2786                 torture_assert(tctx,
2787                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2788                         "Newly added form not found in enum call");
2789         }
2790
2791         torture_assert(tctx,
2792                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2793                 "failed to delete form");
2794
2795         return true;
2796 }
2797
2798 static bool test_Forms(struct torture_context *tctx,
2799                        struct dcerpc_binding_handle *b,
2800                        struct policy_handle *handle,
2801                        bool print_server,
2802                        const char *printer_name,
2803                        struct dcerpc_binding_handle *winreg_handle,
2804                        struct policy_handle *hive_handle)
2805 {
2806         const struct spoolss_FormSize size = {
2807                 .width  = 50,
2808                 .height = 25
2809         };
2810         const struct spoolss_FormArea area = {
2811                 .left   = 5,
2812                 .top    = 10,
2813                 .right  = 45,
2814                 .bottom = 15
2815         };
2816         int i;
2817
2818         struct {
2819                 struct spoolss_AddFormInfo1 info1;
2820                 WERROR expected_add_result;
2821                 WERROR expected_delete_result;
2822         } forms[] = {
2823                 {
2824                         .info1 = {
2825                                 .flags          = SPOOLSS_FORM_USER,
2826                                 .form_name      = "testform_user",
2827                                 .size           = size,
2828                                 .area           = area,
2829                         },
2830                         .expected_add_result    = WERR_OK,
2831                         .expected_delete_result = WERR_OK
2832                 },
2833 /*
2834                 weird, we can add a builtin form but we can never remove it
2835                 again - gd
2836
2837                 {
2838                         .info1 = {
2839                                 .flags          = SPOOLSS_FORM_BUILTIN,
2840                                 .form_name      = "testform_builtin",
2841                                 .size           = size,
2842                                 .area           = area,
2843                         },
2844                         .expected_add_result    = WERR_OK,
2845                         .expected_delete_result = WERR_INVALID_PARAM,
2846                 },
2847 */
2848                 {
2849                         .info1 = {
2850                                 .flags          = SPOOLSS_FORM_PRINTER,
2851                                 .form_name      = "testform_printer",
2852                                 .size           = size,
2853                                 .area           = area,
2854                         },
2855                         .expected_add_result    = WERR_OK,
2856                         .expected_delete_result = WERR_OK
2857                 },
2858                 {
2859                         .info1 = {
2860                                 .flags          = SPOOLSS_FORM_USER,
2861                                 .form_name      = "Letter",
2862                                 .size           = size,
2863                                 .area           = area,
2864                         },
2865                         .expected_add_result    = WERR_FILE_EXISTS,
2866                         .expected_delete_result = WERR_INVALID_PARAM
2867                 },
2868                 {
2869                         .info1 = {
2870                                 .flags          = SPOOLSS_FORM_BUILTIN,
2871                                 .form_name      = "Letter",
2872                                 .size           = size,
2873                                 .area           = area,
2874                         },
2875                         .expected_add_result    = WERR_FILE_EXISTS,
2876                         .expected_delete_result = WERR_INVALID_PARAM
2877                 },
2878                 {
2879                         .info1 = {
2880                                 .flags          = SPOOLSS_FORM_PRINTER,
2881                                 .form_name      = "Letter",
2882                                 .size           = size,
2883                                 .area           = area,
2884                         },
2885                         .expected_add_result    = WERR_FILE_EXISTS,
2886                         .expected_delete_result = WERR_INVALID_PARAM
2887                 },
2888                 {
2889                         .info1 = {
2890                                 .flags          = 12345,
2891                                 .form_name      = "invalid_flags",
2892                                 .size           = size,
2893                                 .area           = area,
2894                         },
2895                         .expected_add_result    = WERR_INVALID_PARAM,
2896                         .expected_delete_result = WERR_INVALID_FORM_NAME
2897                 }
2898
2899         };
2900
2901         for (i=0; i < ARRAY_SIZE(forms); i++) {
2902                 torture_assert(tctx,
2903                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2904                                         winreg_handle, hive_handle,
2905                                         forms[i].info1.form_name,
2906                                         &forms[i].info1,
2907                                         forms[i].expected_add_result,
2908                                         forms[i].expected_delete_result),
2909                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2910         }
2911
2912         return true;
2913 }
2914
2915 static bool test_EnumPorts_old(struct torture_context *tctx,
2916                                void *private_data)
2917 {
2918         struct test_spoolss_context *ctx =
2919                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2920
2921         NTSTATUS status;
2922         struct spoolss_EnumPorts r;
2923         uint32_t needed;
2924         uint32_t count;
2925         union spoolss_PortInfo *info;
2926         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2927         struct dcerpc_binding_handle *b = p->binding_handle;
2928
2929         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2930                                           dcerpc_server_name(p));
2931         r.in.level = 2;
2932         r.in.buffer = NULL;
2933         r.in.offered = 0;
2934         r.out.needed = &needed;
2935         r.out.count = &count;
2936         r.out.info = &info;
2937
2938         torture_comment(tctx, "Testing EnumPorts\n");
2939
2940         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2941
2942         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2943
2944         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2945                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2946                 r.in.buffer = &blob;
2947                 r.in.offered = needed;
2948
2949                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2950                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2951                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2952
2953                 torture_assert(tctx, info, "No ports returned");
2954         }
2955
2956         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2957
2958         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2959
2960         return true;
2961 }
2962
2963 static bool test_AddPort(struct torture_context *tctx,
2964                          void *private_data)
2965 {
2966         struct test_spoolss_context *ctx =
2967                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2968
2969         NTSTATUS status;
2970         struct spoolss_AddPort r;
2971         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2972         struct dcerpc_binding_handle *b = p->binding_handle;
2973
2974         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2975                                            dcerpc_server_name(p));
2976         r.in.unknown = 0;
2977         r.in.monitor_name = "foo";
2978
2979         torture_comment(tctx, "Testing AddPort\n");
2980
2981         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2982
2983         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2984
2985         /* win2k3 returns WERR_NOT_SUPPORTED */
2986
2987 #if 0
2988
2989         if (!W_ERROR_IS_OK(r.out.result)) {
2990                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2991                 return false;
2992         }
2993
2994 #endif
2995
2996         return true;
2997 }
2998
2999 static bool test_GetJob_args(struct torture_context *tctx,
3000                              struct dcerpc_binding_handle *b,
3001                              struct policy_handle *handle,
3002                              uint32_t job_id,
3003                              uint32_t level,
3004                              union spoolss_JobInfo *info_p)
3005 {
3006         NTSTATUS status;
3007         struct spoolss_GetJob r;
3008         union spoolss_JobInfo info;
3009         uint32_t needed;
3010
3011         r.in.handle = handle;
3012         r.in.job_id = job_id;
3013         r.in.level = level;
3014         r.in.buffer = NULL;
3015         r.in.offered = 0;
3016         r.out.needed = &needed;
3017         r.out.info = &info;
3018
3019         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3020
3021         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3022         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3023         if (level == 0) {
3024                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3025         }
3026
3027         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3028                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3029                 r.in.buffer = &blob;
3030                 r.in.offered = needed;
3031
3032                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3033                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3034         }
3035
3036         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3037         torture_assert(tctx, r.out.info, "No job info returned");
3038
3039         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3040
3041         if (info_p) {
3042                 *info_p = *r.out.info;
3043         }
3044
3045         return true;
3046 }
3047
3048 static bool test_GetJob(struct torture_context *tctx,
3049                         struct dcerpc_binding_handle *b,
3050                         struct policy_handle *handle,
3051                         uint32_t job_id)
3052 {
3053         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3054         uint32_t i;
3055
3056         for (i=0; i < ARRAY_SIZE(levels); i++) {
3057                 torture_assert(tctx,
3058                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3059                         "GetJob failed");
3060         }
3061
3062         return true;
3063 }
3064
3065 static bool test_SetJob(struct torture_context *tctx,
3066                         struct dcerpc_binding_handle *b,
3067                         struct policy_handle *handle,
3068                         uint32_t job_id,
3069                         struct spoolss_JobInfoContainer *ctr,
3070                         enum spoolss_JobControl command)
3071 {
3072         NTSTATUS status;
3073         struct spoolss_SetJob r;
3074
3075         r.in.handle     = handle;
3076         r.in.job_id     = job_id;
3077         r.in.ctr        = ctr;
3078         r.in.command    = command;
3079
3080         switch (command) {
3081         case SPOOLSS_JOB_CONTROL_PAUSE:
3082                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3083                 break;
3084         case SPOOLSS_JOB_CONTROL_RESUME:
3085                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3086                 break;
3087         case SPOOLSS_JOB_CONTROL_CANCEL:
3088                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3089                 break;
3090         case SPOOLSS_JOB_CONTROL_RESTART:
3091                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3092                 break;
3093         case SPOOLSS_JOB_CONTROL_DELETE:
3094                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3095                 break;
3096         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3097                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3098                 break;
3099         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3100                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3101                 break;
3102         case SPOOLSS_JOB_CONTROL_RETAIN:
3103                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3104                 break;
3105         case SPOOLSS_JOB_CONTROL_RELEASE:
3106                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3107                 break;
3108         default:
3109                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3110                 break;
3111         }
3112
3113         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3114         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3115         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3116
3117         return true;
3118 }
3119
3120 static bool test_AddJob(struct torture_context *tctx,
3121                         struct dcerpc_binding_handle *b,
3122                         struct policy_handle *handle)
3123 {
3124         NTSTATUS status;
3125         struct spoolss_AddJob r;
3126         uint32_t needed;
3127
3128         r.in.level = 0;
3129         r.in.handle = handle;
3130         r.in.offered = 0;
3131         r.out.needed = &needed;
3132         r.in.buffer = r.out.buffer = NULL;
3133
3134         torture_comment(tctx, "Testing AddJob\n");
3135
3136         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3137         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3138
3139         r.in.level = 1;
3140
3141         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3142         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3143
3144         return true;
3145 }
3146
3147
3148 static bool test_EnumJobs_args(struct torture_context *tctx,
3149                                struct dcerpc_binding_handle *b,
3150                                struct policy_handle *handle,
3151                                uint32_t level,
3152                                uint32_t *count_p,
3153                                union spoolss_JobInfo **info_p)
3154 {
3155         NTSTATUS status;
3156         struct spoolss_EnumJobs r;
3157         uint32_t needed;
3158         uint32_t count;
3159         union spoolss_JobInfo *info;
3160
3161         r.in.handle = handle;
3162         r.in.firstjob = 0;
3163         r.in.numjobs = 0xffffffff;
3164         r.in.level = level;
3165         r.in.buffer = NULL;
3166         r.in.offered = 0;
3167         r.out.needed = &needed;
3168         r.out.count = &count;
3169         r.out.info = &info;
3170
3171         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3172
3173         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3174
3175         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3176
3177         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3178                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3179                 r.in.buffer = &blob;
3180                 r.in.offered = needed;
3181
3182                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3183
3184                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3185                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3186                 torture_assert(tctx, info, "No jobs returned");
3187
3188                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3189
3190         } else {
3191                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3192         }
3193
3194         if (count_p) {
3195                 *count_p = count;
3196         }
3197         if (info_p) {
3198                 *info_p = info;
3199         }
3200
3201         return true;
3202 }
3203
3204 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3205                                          struct dcerpc_binding_handle *b,
3206                                          struct policy_handle *handle,
3207                                          uint32_t *job_id)
3208 {
3209         NTSTATUS status;
3210         struct spoolss_StartDocPrinter s;
3211         struct spoolss_DocumentInfo1 info1;
3212         struct spoolss_StartPagePrinter sp;
3213         struct spoolss_WritePrinter w;
3214         struct spoolss_EndPagePrinter ep;
3215         struct spoolss_EndDocPrinter e;
3216         int i;
3217         uint32_t num_written;
3218
3219         torture_comment(tctx, "Testing StartDocPrinter\n");
3220
3221         s.in.handle             = handle;
3222         s.in.level              = 1;
3223         s.in.info.info1         = &info1;
3224         s.out.job_id            = job_id;
3225         info1.document_name     = "TorturePrintJob";
3226         info1.output_file       = NULL;
3227         info1.datatype          = "RAW";
3228
3229         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3230         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3231         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3232
3233         for (i=1; i < 4; i++) {
3234                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3235
3236                 sp.in.handle            = handle;
3237
3238                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3239                 torture_assert_ntstatus_ok(tctx, status,
3240                                            "dcerpc_spoolss_StartPagePrinter failed");
3241                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3242
3243                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3244
3245                 w.in.handle             = handle;
3246                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3247                 w.out.num_written       = &num_written;
3248
3249                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3250                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3251                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3252
3253                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3254
3255                 ep.in.handle            = handle;
3256
3257                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3258                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3259                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3260         }
3261
3262         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3263
3264         e.in.handle = handle;
3265
3266         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3267         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3268         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3269
3270         return true;
3271 }
3272
3273 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3274                                         struct dcerpc_binding_handle *b,
3275                                         struct policy_handle *handle,
3276                                         uint32_t num_jobs,
3277                                         uint32_t *job_ids)
3278 {
3279         uint32_t count;
3280         union spoolss_JobInfo *info = NULL;
3281         int i;
3282
3283         torture_assert(tctx,
3284                 test_AddJob(tctx, b, handle),
3285                 "AddJob failed");
3286
3287         torture_assert(tctx,
3288                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3289                 "EnumJobs level 1 failed");
3290
3291         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3292
3293         for (i=0; i < num_jobs; i++) {
3294                 union spoolss_JobInfo ginfo;
3295                 const char *document_name;
3296                 const char *new_document_name = "any_other_docname";
3297                 struct spoolss_JobInfoContainer ctr;
3298                 struct spoolss_SetJobInfo1 info1;
3299
3300                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3301
3302                 torture_assert(tctx,
3303                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3304                         "failed to call test_GetJob");
3305
3306                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3307
3308                 document_name = ginfo.info1.document_name;
3309
3310                 info1.job_id            = ginfo.info1.job_id;
3311                 info1.printer_name      = ginfo.info1.printer_name;
3312                 info1.server_name       = ginfo.info1.server_name;
3313                 info1.user_name         = ginfo.info1.user_name;
3314                 info1.document_name     = new_document_name;
3315                 info1.data_type         = ginfo.info1.data_type;
3316                 info1.text_status       = ginfo.info1.text_status;
3317                 info1.status            = ginfo.info1.status;
3318                 info1.priority          = ginfo.info1.priority;
3319                 info1.position          = ginfo.info1.position;
3320                 info1.total_pages       = ginfo.info1.total_pages;
3321                 info1.pages_printed     = ginfo.info1.pages_printed;
3322                 info1.submitted         = ginfo.info1.submitted;
3323
3324                 ctr.level = 1;
3325                 ctr.info.info1 = &info1;
3326
3327                 torture_assert(tctx,
3328                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3329                         "failed to call test_SetJob level 1");
3330
3331                 torture_assert(tctx,
3332                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3333                         "failed to call test_GetJob");
3334
3335                 if (strequal(ginfo.info1.document_name, document_name)) {
3336                         torture_warning(tctx,
3337                                 talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
3338                                         document_name, new_document_name));
3339                 }
3340         }
3341
3342         for (i=0; i < num_jobs; i++) {
3343                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3344                         torture_warning(tctx, "failed to pause printjob\n");
3345                 }
3346                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3347                         torture_warning(tctx, "failed to resume printjob\n");
3348                 }
3349         }
3350
3351         return true;
3352 }
3353
3354 static bool test_DoPrintTest(struct torture_context *tctx,
3355                              struct dcerpc_binding_handle *b,
3356                              struct policy_handle *handle)
3357 {
3358         bool ret = true;
3359         uint32_t num_jobs = 8;
3360         uint32_t *job_ids;
3361         int i;
3362
3363         torture_comment(tctx, "Testing real print operations\n");
3364
3365         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3366
3367         for (i=0; i < num_jobs; i++) {
3368                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3369         }
3370
3371         for (i=0; i < num_jobs; i++) {
3372                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3373         }
3374
3375         if (ret == true) {
3376                 torture_comment(tctx, "real print operations test succeeded\n\n");
3377         }
3378
3379         return ret;
3380 }
3381
3382 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3383                                       struct dcerpc_binding_handle *b,
3384                                       struct policy_handle *handle)
3385 {
3386         bool ret = true;
3387         uint32_t num_jobs = 8;
3388         uint32_t *job_ids;
3389         int i;
3390         torture_comment(tctx, "Testing real print operations (extended)\n");
3391
3392         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3393
3394         for (i=0; i < num_jobs; i++) {
3395                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3396         }
3397
3398         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3399
3400         for (i=0; i < num_jobs; i++) {
3401                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3402         }
3403
3404         if (ret == true) {
3405                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3406         }
3407
3408         return ret;
3409 }
3410
3411 static bool test_PausePrinter(struct torture_context *tctx,
3412                               struct dcerpc_binding_handle *b,
3413                               struct policy_handle *handle)
3414 {
3415         NTSTATUS status;
3416         struct spoolss_SetPrinter r;
3417         struct spoolss_SetPrinterInfoCtr info_ctr;
3418         struct spoolss_DevmodeContainer devmode_ctr;
3419         struct sec_desc_buf secdesc_ctr;
3420
3421         info_ctr.level = 0;
3422         info_ctr.info.info0 = NULL;
3423
3424         ZERO_STRUCT(devmode_ctr);
3425         ZERO_STRUCT(secdesc_ctr);
3426
3427         r.in.handle             = handle;
3428         r.in.info_ctr           = &info_ctr;
3429         r.in.devmode_ctr        = &devmode_ctr;
3430         r.in.secdesc_ctr        = &secdesc_ctr;
3431         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3432
3433         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3434
3435         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3436
3437         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3438
3439         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3440
3441         return true;
3442 }
3443
3444 static bool test_ResumePrinter(struct torture_context *tctx,
3445                                struct dcerpc_binding_handle *b,
3446                                struct policy_handle *handle)
3447 {
3448         NTSTATUS status;
3449         struct spoolss_SetPrinter r;
3450         struct spoolss_SetPrinterInfoCtr info_ctr;
3451         struct spoolss_DevmodeContainer devmode_ctr;
3452         struct sec_desc_buf secdesc_ctr;
3453
3454         info_ctr.level = 0;
3455         info_ctr.info.info0 = NULL;
3456
3457         ZERO_STRUCT(devmode_ctr);
3458         ZERO_STRUCT(secdesc_ctr);
3459
3460         r.in.handle             = handle;
3461         r.in.info_ctr           = &info_ctr;
3462         r.in.devmode_ctr        = &devmode_ctr;
3463         r.in.secdesc_ctr        = &secdesc_ctr;
3464         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3465
3466         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3467
3468         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3469
3470         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3471
3472         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3473
3474         return true;
3475 }
3476
3477 static bool test_GetPrinterData(struct torture_context *tctx,
3478                                 struct dcerpc_binding_handle *b,
3479                                 struct policy_handle *handle,
3480                                 const char *value_name,
3481                                 enum winreg_Type *type_p,
3482                                 uint8_t **data_p,
3483                                 uint32_t *needed_p)
3484 {
3485         NTSTATUS status;
3486         struct spoolss_GetPrinterData r;
3487         uint32_t needed;
3488         enum winreg_Type type;
3489         union spoolss_PrinterData data;
3490
3491         r.in.handle = handle;
3492         r.in.value_name = value_name;
3493         r.in.offered = 0;
3494         r.out.needed = &needed;
3495         r.out.type = &type;
3496         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3497
3498         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3499
3500         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3501         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3502
3503         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3504                 r.in.offered = needed;
3505                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3506                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3507                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3508         }
3509
3510         torture_assert_werr_ok(tctx, r.out.result,
3511                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3512
3513         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3514
3515         if (type_p) {
3516                 *type_p = type;
3517         }
3518
3519         if (data_p) {
3520                 *data_p = r.out.data;
3521         }
3522
3523         if (needed_p) {
3524                 *needed_p = needed;
3525         }
3526
3527         return true;
3528 }
3529
3530 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3531                                   struct dcerpc_pipe *p,
3532                                   struct policy_handle *handle,
3533                                   const char *key_name,
3534                                   const char *value_name,
3535                                   enum winreg_Type *type_p,
3536                                   uint8_t **data_p,
3537                                   uint32_t *needed_p)
3538 {
3539         NTSTATUS status;
3540         struct spoolss_GetPrinterDataEx r;
3541         enum winreg_Type type;
3542         uint32_t needed;
3543         union spoolss_PrinterData data;
3544         struct dcerpc_binding_handle *b = p->binding_handle;
3545
3546         r.in.handle = handle;
3547         r.in.key_name = key_name;
3548         r.in.value_name = value_name;
3549         r.in.offered = 0;
3550         r.out.type = &type;
3551         r.out.needed = &needed;
3552         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3553
3554         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3555                 r.in.key_name, r.in.value_name);
3556
3557         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3558         if (!NT_STATUS_IS_OK(status)) {
3559                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3560                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3561                 }
3562                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3563         }
3564
3565         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3566                 r.in.offered = needed;
3567                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3568                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3569                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3570         }
3571
3572         torture_assert_werr_ok(tctx, r.out.result,
3573                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3574
3575         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3576
3577         if (type_p) {
3578                 *type_p = type;
3579         }
3580
3581         if (data_p) {
3582                 *data_p = r.out.data;
3583         }
3584
3585         if (needed_p) {
3586                 *needed_p = needed;
3587         }
3588
3589         return true;
3590 }
3591
3592 static bool test_get_environment(struct torture_context *tctx,
3593                                  struct dcerpc_binding_handle *b,
3594                                  struct policy_handle *handle,
3595                                  const char **architecture)
3596 {
3597         DATA_BLOB blob;
3598         enum winreg_Type type;
3599         uint8_t *data;
3600         uint32_t needed;
3601
3602         torture_assert(tctx,
3603                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3604                 "failed to get Architecture");
3605
3606         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3607
3608         blob = data_blob_const(data, needed);
3609         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3610
3611         return true;
3612 }
3613
3614 static bool test_GetPrinterData_list(struct torture_context *tctx,
3615                                      void *private_data)
3616 {
3617         struct test_spoolss_context *ctx =
3618                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3619         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3620         struct dcerpc_binding_handle *b = p->binding_handle;
3621         const char *list[] = {
3622                 "W3SvcInstalled",
3623                 "BeepEnabled",
3624                 "EventLog",
3625                 /* "NetPopup", not on w2k8 */
3626                 /* "NetPopupToComputer", not on w2k8 */
3627                 "MajorVersion",
3628                 "MinorVersion",
3629                 "DefaultSpoolDirectory",
3630                 "Architecture",
3631                 "DsPresent",
3632                 "OSVersion",
3633                 /* "OSVersionEx", not on s3 */
3634                 "DNSMachineName"
3635         };
3636         int i;
3637
3638         for (i=0; i < ARRAY_SIZE(list); i++) {
3639                 enum winreg_Type type, type_ex;
3640                 uint8_t *data, *data_ex;
3641                 uint32_t needed, needed_ex;
3642
3643                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3644                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3645                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3646                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3647                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3648                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3649                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3650         }
3651
3652         return true;
3653 }
3654
3655 static bool test_EnumPrinterData(struct torture_context *tctx,
3656                                  struct dcerpc_pipe *p,
3657                                  struct policy_handle *handle,
3658                                  uint32_t enum_index,
3659                                  uint32_t value_offered,
3660                                  uint32_t data_offered,
3661                                  enum winreg_Type *type_p,
3662                                  uint32_t *value_needed_p,
3663                                  uint32_t *data_needed_p,
3664                                  const char **value_name_p,
3665                                  uint8_t **data_p,
3666                                  WERROR *result_p)
3667 {
3668         struct spoolss_EnumPrinterData r;
3669         uint32_t data_needed;
3670         uint32_t value_needed;
3671         enum winreg_Type type;
3672         struct dcerpc_binding_handle *b = p->binding_handle;
3673
3674         r.in.handle = handle;
3675         r.in.enum_index = enum_index;
3676         r.in.value_offered = value_offered;
3677         r.in.data_offered = data_offered;
3678         r.out.data_needed = &data_needed;
3679         r.out.value_needed = &value_needed;
3680         r.out.type = &type;
3681         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3682         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3683
3684         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3685
3686         torture_assert_ntstatus_ok(tctx,
3687                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3688                 "EnumPrinterData failed");
3689
3690         if (type_p) {
3691                 *type_p = type;
3692         }
3693         if (value_needed_p) {
3694                 *value_needed_p = value_needed;
3695         }
3696         if (data_needed_p) {
3697                 *data_needed_p = data_needed;
3698         }
3699         if (value_name_p) {
3700                 *value_name_p = r.out.value_name;
3701         }
3702         if (data_p) {
3703                 *data_p = r.out.data;
3704         }
3705         if (result_p) {
3706                 *result_p = r.out.result;
3707         }
3708
3709         return true;
3710 }
3711
3712
3713 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3714                                      struct dcerpc_pipe *p,
3715                                      struct policy_handle *handle)
3716 {
3717         uint32_t enum_index = 0;
3718         enum winreg_Type type;
3719         uint32_t value_needed;
3720         uint32_t data_needed;
3721         uint8_t *data;
3722         const char *value_name;
3723         WERROR result;
3724
3725         torture_comment(tctx, "Testing EnumPrinterData\n");
3726
3727         do {
3728                 torture_assert(tctx,
3729                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3730                                              &type, &value_needed, &data_needed,
3731                                              &value_name, &data, &result),
3732                         "EnumPrinterData failed");
3733
3734                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3735                         break;
3736                 }
3737
3738                 torture_assert(tctx,
3739                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3740                                              &type, &value_needed, &data_needed,
3741                                              &value_name, &data, &result),
3742                         "EnumPrinterData failed");
3743
3744                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3745                         break;
3746                 }
3747
3748                 enum_index++;
3749
3750         } while (W_ERROR_IS_OK(result));
3751
3752         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3753
3754         return true;
3755 }
3756
3757 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3758                                    struct dcerpc_binding_handle *b,
3759                                    struct policy_handle *handle,
3760                                    const char *key_name,
3761                                    uint32_t *count_p,
3762                                    struct spoolss_PrinterEnumValues **info_p)
3763 {
3764         struct spoolss_EnumPrinterDataEx r;
3765         struct spoolss_PrinterEnumValues *info;
3766         uint32_t needed;
3767         uint32_t count;
3768
3769         r.in.handle = handle;
3770         r.in.key_name = key_name;
3771         r.in.offered = 0;
3772         r.out.needed = &needed;
3773         r.out.count = &count;
3774         r.out.info = &info;
3775
3776         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3777
3778         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3779                 "EnumPrinterDataEx failed");
3780         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3781                 r.in.offered = needed;
3782                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3783                         "EnumPrinterDataEx failed");
3784         }
3785
3786         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3787
3788         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3789
3790         if (count_p) {
3791                 *count_p = count;
3792         }
3793         if (info_p) {
3794                 *info_p = info;
3795         }
3796
3797         return true;
3798 }
3799
3800 static bool test_SetPrinterData(struct torture_context *tctx,
3801                                 struct dcerpc_binding_handle *b,
3802                                 struct policy_handle *handle,
3803                                 const char *value_name,
3804                                 enum winreg_Type type,
3805                                 uint8_t *data,
3806                                 uint32_t offered);
3807 static bool test_DeletePrinterData(struct torture_context *tctx,
3808                                    struct dcerpc_binding_handle *b,
3809                                    struct policy_handle *handle,
3810                                    const char *value_name);
3811
3812 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3813                                              struct dcerpc_pipe *p,
3814                                              struct policy_handle *handle)
3815 {
3816         uint32_t count;
3817         struct spoolss_PrinterEnumValues *info;
3818         int i;
3819         uint32_t value_needed, data_needed;
3820         uint32_t value_offered, data_offered;
3821         WERROR result;
3822         struct dcerpc_binding_handle *b = p->binding_handle;
3823
3824         enum winreg_Type type;
3825         DATA_BLOB blob;
3826
3827         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3828
3829         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3830         type = REG_SZ;
3831
3832         torture_assert(tctx,
3833                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3834                 "SetPrinterData failed");
3835
3836         blob = data_blob_string_const("torture_data2");
3837
3838         torture_assert(tctx,
3839                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3840                 "SetPrinterData failed");
3841
3842         blob = data_blob_talloc(tctx, NULL, 4);
3843         SIVAL(blob.data, 0, 0x11223344);
3844
3845         torture_assert(tctx,
3846                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3847                 "SetPrinterData failed");
3848
3849         torture_assert(tctx,
3850                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3851                 "failed to call EnumPrinterDataEx");
3852
3853         /* get the max sizes for value and data */
3854
3855         torture_assert(tctx,
3856                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3857                                      NULL, &value_needed, &data_needed,
3858                                      NULL, NULL, &result),
3859                 "EnumPrinterData failed");
3860         torture_assert_werr_ok(tctx, result, "unexpected result");
3861
3862         /* check if the reply from the EnumPrinterData really matches max values */
3863
3864         for (i=0; i < count; i++) {
3865                 if (info[i].value_name_len > value_needed) {
3866                         torture_fail(tctx,
3867                                 talloc_asprintf(tctx,
3868                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3869                                 info[i].value_name_len, value_needed));
3870                 }
3871                 if (info[i].data_length > data_needed) {
3872                         torture_fail(tctx,
3873                                 talloc_asprintf(tctx,
3874                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3875                                 info[i].data_length, data_needed));
3876                 }
3877         }
3878
3879         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3880          * sort or not sort the replies by value name, we should be able to do
3881          * the following entry comparison */
3882
3883         data_offered = data_needed;
3884         value_offered = value_needed;
3885
3886         for (i=0; i < count; i++) {
3887
3888                 const char *value_name;
3889                 uint8_t *data;
3890
3891                 torture_assert(tctx,
3892                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3893                                              &type, &value_needed, &data_needed,
3894                                              &value_name, &data, &result),
3895                         "EnumPrinterData failed");
3896
3897                 if (i -1 == count) {
3898                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3899                                 "unexpected result");
3900                         break;
3901                 } else {
3902                         torture_assert_werr_ok(tctx, result, "unexpected result");
3903                 }
3904
3905                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3906                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3907                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3908                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3909                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3910         }
3911
3912         torture_assert(tctx,
3913                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3914                 "DeletePrinterData failed");
3915         torture_assert(tctx,
3916                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3917                 "DeletePrinterData failed");
3918         torture_assert(tctx,
3919                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3920                 "DeletePrinterData failed");
3921
3922         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3923
3924         return true;
3925 }
3926
3927 static bool test_DeletePrinterData(struct torture_context *tctx,
3928                                    struct dcerpc_binding_handle *b,
3929                                    struct policy_handle *handle,
3930                                    const char *value_name)
3931 {
3932         NTSTATUS status;
3933         struct spoolss_DeletePrinterData r;
3934
3935         r.in.handle = handle;
3936         r.in.value_name = value_name;
3937
3938         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3939                 r.in.value_name);
3940
3941         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3942
3943         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3944         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3945
3946         return true;
3947 }
3948
3949 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3950                                      struct dcerpc_binding_handle *b,
3951                                      struct policy_handle *handle,
3952                                      const char *key_name,
3953                                      const char *value_name)
3954 {
3955         struct spoolss_DeletePrinterDataEx r;
3956
3957         r.in.handle = handle;
3958         r.in.key_name = key_name;
3959         r.in.value_name = value_name;
3960
3961         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3962                 r.in.key_name, r.in.value_name);
3963
3964         torture_assert_ntstatus_ok(tctx,
3965                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3966                 "DeletePrinterDataEx failed");
3967         torture_assert_werr_ok(tctx, r.out.result,
3968                 "DeletePrinterDataEx failed");
3969
3970         return true;
3971 }
3972
3973 static bool test_DeletePrinterKey(struct torture_context *tctx,
3974                                   struct dcerpc_binding_handle *b,
3975                                   struct policy_handle *handle,
3976                                   const char *key_name)
3977 {
3978         struct spoolss_DeletePrinterKey r;
3979
3980         r.in.handle = handle;
3981         r.in.key_name = key_name;
3982
3983         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3984
3985         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3986                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3987                 return true;
3988         }
3989
3990         torture_assert_ntstatus_ok(tctx,
3991                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3992                 "DeletePrinterKey failed");
3993         torture_assert_werr_ok(tctx, r.out.result,
3994                 "DeletePrinterKey failed");
3995
3996         return true;
3997 }
3998
3999 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4000                                  struct dcerpc_binding_handle *b,
4001                                  struct policy_handle *handle)
4002 {
4003         struct winreg_OpenHKLM r;
4004
4005         r.in.system_name = NULL;
4006         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4007         r.out.handle = handle;
4008
4009         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4010
4011         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4012         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4013
4014         return true;
4015 }
4016
4017 static void init_winreg_String(struct winreg_String *name, const char *s)
4018 {
4019         name->name = s;
4020         if (s) {
4021                 name->name_len = 2 * (strlen_m(s) + 1);
4022                 name->name_size = name->name_len;
4023         } else {
4024                 name->name_len = 0;
4025                 name->name_size = 0;
4026         }
4027 }
4028
4029 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4030                                      struct dcerpc_binding_handle *b,
4031                                      struct policy_handle *hive_handle,
4032                                      const char *keyname,
4033                                      uint32_t options,
4034                                      struct policy_handle *key_handle)
4035 {
4036         struct winreg_OpenKey r;
4037
4038         r.in.parent_handle = hive_handle;
4039         init_winreg_String(&r.in.keyname, keyname);
4040         r.in.options = options;
4041         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4042         r.out.handle = key_handle;
4043
4044         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4045
4046         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4047         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4048
4049         return true;
4050 }
4051
4052 static bool test_winreg_OpenKey(struct torture_context *tctx,
4053                                 struct dcerpc_binding_handle *b,
4054                                 struct policy_handle *hive_handle,
4055                                 const char *keyname,
4056                                 struct policy_handle *key_handle)
4057 {
4058         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4059                                         REG_OPTION_NON_VOLATILE, key_handle);
4060 }
4061
4062 static bool test_winreg_CloseKey(struct torture_context *tctx,
4063                                  struct dcerpc_binding_handle *b,
4064                                  struct policy_handle *handle)
4065 {
4066         struct winreg_CloseKey r;
4067
4068         r.in.handle = handle;
4069         r.out.handle = handle;
4070
4071         torture_comment(tctx, "Testing winreg_CloseKey\n");
4072
4073         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4074         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4075
4076         return true;
4077 }
4078
4079 bool test_winreg_QueryValue(struct torture_context *tctx,
4080                             struct dcerpc_binding_handle *b,
4081                             struct policy_handle *handle,
4082                             const char *value_name,
4083                             enum winreg_Type *type_p,
4084                             uint32_t *data_size_p,
4085                             uint32_t *data_length_p,
4086                             uint8_t **data_p)
4087 {
4088         struct winreg_QueryValue r;
4089         enum winreg_Type type = REG_NONE;
4090         uint32_t data_size = 0;
4091         uint32_t data_length = 0;
4092         struct winreg_String valuename;
4093         uint8_t *data = NULL;
4094
4095         init_winreg_String(&valuename, value_name);
4096
4097         data = talloc_zero_array(tctx, uint8_t, 0);
4098
4099         r.in.handle = handle;
4100         r.in.value_name = &valuename;
4101         r.in.type = &type;
4102         r.in.data_size = &data_size;
4103         r.in.data_length = &data_length;
4104         r.in.data = data;
4105         r.out.type = &type;
4106         r.out.data = data;
4107         r.out.data_size = &data_size;
4108         r.out.data_length = &data_length;
4109
4110         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4111
4112         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4113         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4114                 *r.in.data_size = *r.out.data_size;
4115                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4116                 r.in.data = data;
4117                 r.out.data = data;
4118                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4119         }
4120         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4121
4122         if (type_p) {
4123                 *type_p = *r.out.type;
4124         }
4125         if (data_size_p) {
4126                 *data_size_p = *r.out.data_size;
4127         }
4128         if (data_length_p) {
4129                 *data_length_p = *r.out.data_length;
4130         }
4131         if (data_p) {
4132                 *data_p = r.out.data;
4133         }
4134
4135         return true;
4136 }
4137
4138 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4139                                           struct dcerpc_binding_handle *b,
4140                                           struct policy_handle *handle,
4141                                           const char *printer_name,
4142                                           const char *key_name,
4143                                           const char *value_name,
4144                                           enum winreg_Type *w_type,
4145                                           uint32_t *w_size,
4146                                           uint32_t *w_length,
4147                                           uint8_t **w_data)
4148 {
4149         const char *printer_key;
4150         struct policy_handle key_handle;
4151
4152         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4153                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4154
4155         torture_assert(tctx,
4156                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4157
4158         torture_assert(tctx,
4159                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4160
4161         torture_assert(tctx,
4162                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4163
4164         return true;
4165 }
4166
4167 static bool test_GetForm_winreg(struct torture_context *tctx,
4168                                 struct dcerpc_binding_handle *b,
4169                                 struct policy_handle *handle,
4170                                 const char *key_name,
4171                                 const char *form_name,
4172                                 enum winreg_Type *w_type,
4173                                 uint32_t *w_size,
4174                                 uint32_t *w_length,
4175                                 uint8_t **w_data)
4176 {
4177         struct policy_handle key_handle;
4178
4179         torture_assert(tctx,
4180                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4181
4182         torture_assert(tctx,
4183                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4184
4185         torture_assert(tctx,
4186                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4187
4188         return true;
4189 }
4190
4191 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4192                                       struct dcerpc_binding_handle *b,
4193                                       struct policy_handle *handle,
4194                                       const char *symlink_keyname,
4195                                       const char *symlink_destination)
4196 {
4197         /* check if the first key is a symlink to the second key */
4198
4199         enum winreg_Type w_type;
4200         uint32_t w_size;
4201         uint32_t w_length;
4202         uint8_t *w_data;
4203         struct policy_handle key_handle;
4204         DATA_BLOB blob;
4205         const char *str;
4206
4207         if (torture_setting_bool(tctx, "samba3", false)) {
4208                 torture_skip(tctx, "skip winreg symlink test against samba");
4209         }
4210
4211         torture_assert(tctx,
4212                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4213                         "failed to open key link");
4214
4215         torture_assert(tctx,
4216                 test_winreg_QueryValue(tctx, b, &key_handle,
4217                                        "SymbolicLinkValue",
4218                                        &w_type, &w_size, &w_length, &w_data),
4219                 "failed to query for 'SymbolicLinkValue' attribute");
4220
4221         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4222
4223         blob = data_blob(w_data, w_size);
4224         str = reg_val_data_string(tctx, REG_SZ, blob);
4225
4226         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4227
4228         torture_assert(tctx,
4229                 test_winreg_CloseKey(tctx, b, &key_handle),
4230                 "failed to close key link");
4231
4232         return true;
4233 }
4234
4235 static const char *strip_unc(const char *unc)
4236 {
4237         char *name;
4238
4239         if (!unc) {
4240                 return NULL;
4241         }
4242
4243         if (unc[0] == '\\' && unc[1] == '\\') {
4244                 unc +=2;
4245         }
4246
4247         name = strchr(unc, '\\');
4248         if (name) {
4249                 return name+1;
4250         }
4251
4252         return unc;
4253 }
4254
4255 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4256                                        struct dcerpc_binding_handle *b,
4257                                        struct policy_handle *handle,
4258                                        const char *printer_name,
4259                                        struct dcerpc_binding_handle *winreg_handle,
4260                                        struct policy_handle *hive_handle)
4261 {
4262         union spoolss_PrinterInfo info;
4263         const char *keys[] = {
4264                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4265                 TOP_LEVEL_PRINT_PRINTERS_KEY
4266         };
4267         int i;
4268         const char *printername, *sharename;
4269
4270         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4271
4272         torture_assert(tctx,
4273                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4274                 "failed to get printer info level 2");
4275
4276         printername = strip_unc(info.info2.printername);
4277         sharename = strip_unc(info.info2.sharename);
4278
4279 #define test_sz(wname, iname) \
4280 do {\
4281         DATA_BLOB blob;\
4282         const char *str;\
4283         enum winreg_Type w_type;\
4284         uint32_t w_size;\
4285         uint32_t w_length;\
4286         uint8_t *w_data;\
4287         torture_assert(tctx,\
4288                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4289                                        &w_type, &w_size, &w_length, &w_data),\
4290                 "failed to query winreg");\
4291         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4292         blob = data_blob(w_data, w_size);\
4293         str = reg_val_data_string(tctx, REG_SZ, blob);\
4294         if (w_size == 2 && iname == NULL) {\
4295                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4296         } else {\
4297                 torture_assert_str_equal(tctx, str, iname,\
4298                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4299         }\
4300 } while(0);
4301
4302 #define test_dword(wname, iname) \
4303 do {\
4304         uint32_t value;\
4305         enum winreg_Type w_type;\
4306         uint32_t w_size;\
4307         uint32_t w_length;\
4308         uint8_t *w_data;\
4309         torture_assert(tctx,\
4310                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4311                                        &w_type, &w_size, &w_length, &w_data),\
4312                 "failed to query winreg");\
4313         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4314         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4315         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4316         value = IVAL(w_data, 0);\
4317         torture_assert_int_equal(tctx, value, iname,\
4318                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4319 } while(0);
4320
4321 #define test_dm(wname, iname) \
4322 do {\
4323         DATA_BLOB blob;\
4324         struct spoolss_DeviceMode dm;\
4325         enum ndr_err_code ndr_err;\
4326         enum winreg_Type w_type;\
4327         uint32_t w_size;\
4328         uint32_t w_length;\
4329         uint8_t *w_data;\
4330         torture_assert(tctx,\
4331                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4332                                        &w_type, &w_size, &w_length, &w_data),\
4333                 "failed to query winreg");\
4334         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4335         blob = data_blob(w_data, w_size);\
4336         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4337                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4338         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4339         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4340                 "dm unequal");\
4341 } while(0);
4342
4343 #define test_sd(wname, iname) \
4344 do {\
4345         DATA_BLOB blob;\
4346         struct security_descriptor sd;\
4347         enum ndr_err_code ndr_err;\
4348         enum winreg_Type w_type;\
4349         uint32_t w_size;\
4350         uint32_t w_length;\
4351         uint8_t *w_data;\
4352         torture_assert(tctx,\
4353                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4354                                        &w_type, &w_size, &w_length, &w_data),\
4355                 "failed to query winreg");\
4356         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4357         blob = data_blob(w_data, w_size);\
4358         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4359                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4360         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4361         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4362                 "sd unequal");\
4363 } while(0);
4364
4365 #define test_multi_sz(wname, iname) \
4366 do {\
4367         DATA_BLOB blob;\
4368         const char **array;\
4369         enum winreg_Type w_type;\
4370         uint32_t w_size;\
4371         uint32_t w_length;\
4372         uint8_t *w_data;\
4373         int i;\
4374         torture_assert(tctx,\
4375                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4376                                        &w_type, &w_size, &w_length, &w_data),\
4377                 "failed to query winreg");\
4378         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4379         blob = data_blob(w_data, w_size);\
4380         torture_assert(tctx, \
4381                 pull_reg_multi_sz(tctx, &blob, &array),\
4382                 "failed to pull multi sz");\
4383         for (i=0; array[i] != NULL; i++) {\
4384                 torture_assert_str_equal(tctx, array[i], iname[i],\
4385                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4386         }\
4387 } while(0);
4388
4389         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4390                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4391                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4392         {
4393                 torture_warning(tctx, "failed to check for winreg symlink");
4394         }
4395
4396         for (i=0; i < ARRAY_SIZE(keys); i++) {
4397
4398                 const char *printer_key;
4399                 struct policy_handle key_handle;
4400
4401                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4402                         keys[i], printer_name);
4403
4404                 torture_assert(tctx,
4405                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4406
4407                 test_sz("Name", printername);
4408                 test_sz("Share Name", sharename);
4409                 test_sz("Port", info.info2.portname);
4410                 test_sz("Printer Driver", info.info2.drivername);
4411                 test_sz("Description", info.info2.comment);
4412                 test_sz("Location", info.info2.location);
4413                 test_sz("Separator File", info.info2.sepfile);
4414                 test_sz("Print Processor", info.info2.printprocessor);
4415                 test_sz("Datatype", info.info2.datatype);
4416                 test_sz("Parameters", info.info2.parameters);
4417                 /* winreg: 0, spoolss not */
4418 /*              test_dword("Attributes", info.info2.attributes); */
4419                 test_dword("Priority", info.info2.priority);
4420                 test_dword("Default Priority", info.info2.defaultpriority);
4421                 /* winreg: 60, spoolss: 0 */
4422 /*              test_dword("StartTime", info.info2.starttime); */
4423 /*              test_dword("UntilTime", info.info2.untiltime); */
4424                 /* winreg != spoolss */
4425 /*              test_dword("Status", info.info2.status); */
4426                 test_dm("Default DevMode", info.info2.devmode);
4427                 test_sd("Security", info.info2.secdesc);
4428
4429                 torture_assert(tctx,
4430                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4431         }
4432
4433 #undef test_dm
4434 #undef test_sd
4435
4436         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4437
4438         return true;
4439 }
4440
4441 static bool test_PrintProcessors(struct torture_context *tctx,
4442                                  struct dcerpc_binding_handle *b,
4443                                  const char *environment,
4444                                  struct dcerpc_binding_handle *winreg_handle,
4445                                  struct policy_handle *hive_handle)
4446 {
4447         union spoolss_PrintProcessorInfo *info;
4448         uint32_t count;
4449         int i;
4450
4451         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4452
4453         torture_assert(tctx,
4454                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4455                 "failed to enum print processors level 1");
4456
4457         for (i=0; i < count; i++) {
4458
4459                 const char *processor_key;
4460                 struct policy_handle key_handle;
4461
4462                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4463                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4464                                                 environment,
4465                                                 info[i].info1.print_processor_name);
4466
4467                 torture_assert(tctx,
4468                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4469
4470                 /* nothing to check in there so far */
4471
4472                 torture_assert(tctx,
4473                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4474         }
4475
4476         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4477
4478         return true;
4479 }
4480
4481 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4482                                          struct dcerpc_binding_handle *b,
4483                                          struct policy_handle *handle,
4484                                          const char *driver_name,
4485                                          const char *architecture,
4486                                          uint32_t level,
4487                                          uint32_t client_major_version,
4488                                          uint32_t client_minor_version,
4489                                          union spoolss_DriverInfo *info_p,
4490                                          WERROR *result);
4491
4492 static const char *strip_path(const char *path)
4493 {
4494         char *p;
4495
4496         if (path == NULL) {
4497                 return NULL;
4498         }
4499
4500         p = strrchr(path, '\\');
4501         if (p) {
4502                 return p+1;
4503         }
4504
4505         return path;
4506 }
4507
4508 static const char **strip_paths(const char **path_array)
4509 {
4510         int i;
4511
4512         if (path_array == NULL) {
4513                 return NULL;
4514         }
4515
4516         for (i=0; path_array[i] != NULL; i++) {
4517                 path_array[i] = strip_path(path_array[i]);
4518         }
4519
4520         return path_array;
4521 }
4522
4523 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4524 {
4525         time_t t;
4526         struct tm *tm;
4527         t = nt_time_to_unix(nt);
4528         tm = localtime(&t);
4529
4530         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4531                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4532 }
4533
4534 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4535 {
4536         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4537                 (unsigned)((v >> 48) & 0xFFFF),
4538                 (unsigned)((v >> 32) & 0xFFFF),
4539                 (unsigned)((v >> 16) & 0xFFFF),
4540                 (unsigned)(v & 0xFFFF));
4541 }
4542
4543 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4544                                       struct dcerpc_binding_handle *b,
4545                                       struct policy_handle *handle,
4546                                       const char *printer_name,
4547                                       const char *driver_name,
4548                                       const char *environment,
4549                                       struct dcerpc_binding_handle *winreg_handle,
4550                                       struct policy_handle *hive_handle)
4551 {
4552         WERROR result;
4553         union spoolss_DriverInfo info;
4554         const char *driver_key;
4555         struct policy_handle key_handle;
4556
4557         const char *driver_path;
4558         const char *data_file;
4559         const char *config_file;
4560         const char *help_file;
4561         const char **dependent_files;
4562
4563         const char *driver_date;
4564         const char *inbox_driver_date;
4565
4566         const char *driver_version;
4567         const char *inbox_driver_version;
4568
4569         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4570
4571         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4572                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4573                                      environment,
4574                                      3,
4575                                      driver_name);
4576
4577         torture_assert(tctx,
4578                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4579                 "failed to open driver key");
4580
4581         if (torture_setting_bool(tctx, "samba3", false)) {
4582                 goto try_level3;
4583         }
4584
4585         torture_assert(tctx,
4586                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4587                 "failed to get driver info level 8");
4588
4589         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4590                 goto try_level6;
4591         }
4592
4593         driver_path     = strip_path(info.info8.driver_path);
4594         data_file       = strip_path(info.info8.data_file);
4595         config_file     = strip_path(info.info8.config_file);
4596         help_file       = strip_path(info.info8.help_file);
4597         dependent_files = strip_paths(info.info8.dependent_files);
4598
4599         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4600         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4601
4602         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4603         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4604
4605         test_sz("Configuration File",           config_file);
4606         test_sz("Data File",                    data_file);
4607         test_sz("Datatype",                     info.info8.default_datatype);
4608         test_sz("Driver",                       driver_path);
4609         test_sz("DriverDate",                   driver_date);
4610         test_sz("DriverVersion",                driver_version);
4611         test_sz("HardwareID",                   info.info8.hardware_id);
4612         test_sz("Help File",                    help_file);
4613         test_sz("InfPath",                      info.info8.inf_path);
4614         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4615         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4616         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4617         test_sz("Monitor",                      info.info8.monitor_name);
4618         test_sz("OEM URL",                      info.info8.manufacturer_url);
4619         test_sz("Print Processor",              info.info8.print_processor);
4620         test_sz("Provider",                     info.info8.provider);
4621         test_sz("VendorSetup",                  info.info8.vendor_setup);
4622         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4623         test_multi_sz("Dependent Files",        dependent_files);
4624         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4625         test_multi_sz("Previous Names",         info.info8.previous_names);
4626 /*      test_dword("Attributes",                ?); */
4627         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4628         test_dword("Version",                   info.info8.version);
4629 /*      test_dword("TempDir",                   ?); */
4630
4631  try_level6:
4632
4633         torture_assert(tctx,
4634                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4635                 "failed to get driver info level 6");
4636
4637         driver_path     = strip_path(info.info6.driver_path);
4638         data_file       = strip_path(info.info6.data_file);
4639         config_file     = strip_path(info.info6.config_file);
4640         help_file       = strip_path(info.info6.help_file);
4641         dependent_files = strip_paths(info.info6.dependent_files);
4642
4643         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4644
4645         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4646
4647         test_sz("Configuration File",           config_file);
4648         test_sz("Data File",                    data_file);
4649         test_sz("Datatype",                     info.info6.default_datatype);
4650         test_sz("Driver",                       driver_path);
4651         test_sz("DriverDate",                   driver_date);
4652         test_sz("DriverVersion",                driver_version);
4653         test_sz("HardwareID",                   info.info6.hardware_id);
4654         test_sz("Help File",                    help_file);
4655         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4656         test_sz("Monitor",                      info.info6.monitor_name);
4657         test_sz("OEM URL",                      info.info6.manufacturer_url);
4658         test_sz("Provider",                     info.info6.provider);
4659         test_multi_sz("Dependent Files",        dependent_files);
4660         test_multi_sz("Previous Names",         info.info6.previous_names);
4661 /*      test_dword("Attributes",                ?); */
4662         test_dword("Version",                   info.info6.version);
4663 /*      test_dword("TempDir",                   ?); */
4664
4665  try_level3:
4666
4667         torture_assert(tctx,
4668                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4669                 "failed to get driver info level 3");
4670
4671         driver_path     = strip_path(info.info3.driver_path);
4672         data_file       = strip_path(info.info3.data_file);
4673         config_file     = strip_path(info.info3.config_file);
4674         help_file       = strip_path(info.info3.help_file);
4675         dependent_files = strip_paths(info.info3.dependent_files);
4676
4677         test_sz("Configuration File",           config_file);
4678         test_sz("Data File",                    data_file);
4679         test_sz("Datatype",                     info.info3.default_datatype);
4680         test_sz("Driver",                       driver_path);
4681         test_sz("Help File",                    help_file);
4682         test_sz("Monitor",                      info.info3.monitor_name);
4683         test_multi_sz("Dependent Files",        dependent_files);
4684 /*      test_dword("Attributes",                ?); */
4685         test_dword("Version",                   info.info3.version);
4686 /*      test_dword("TempDir",                   ?); */
4687
4688
4689         torture_assert(tctx,
4690                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4691
4692         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4693
4694         return true;
4695 }
4696
4697 #undef test_sz
4698 #undef test_dword
4699
4700 static bool test_SetPrinterData(struct torture_context *tctx,
4701                                 struct dcerpc_binding_handle *b,
4702                                 struct policy_handle *handle,
4703                                 const char *value_name,
4704                                 enum winreg_Type type,
4705                                 uint8_t *data,
4706                                 uint32_t offered)
4707 {
4708         struct spoolss_SetPrinterData r;
4709
4710         r.in.handle = handle;
4711         r.in.value_name = value_name;
4712         r.in.type = type;
4713         r.in.data = data;
4714         r.in.offered = offered;
4715
4716         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4717                 r.in.value_name);
4718
4719         torture_assert_ntstatus_ok(tctx,
4720                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4721                 "SetPrinterData failed");
4722         torture_assert_werr_ok(tctx, r.out.result,
4723                 "SetPrinterData failed");
4724
4725         return true;
4726 }
4727
4728 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4729                                        struct dcerpc_binding_handle *b,
4730                                        struct policy_handle *handle,
4731                                        const char *printer_name,
4732                                        struct dcerpc_binding_handle *winreg_handle,
4733                                        struct policy_handle *hive_handle)
4734 {
4735         const char *values[] = {
4736                 "spootyfoot",
4737                 "spooty\\foot",
4738 #if 0
4739         /* FIXME: not working with s3 atm. */
4740                 "spooty,foot",
4741                 "spooty,fo,ot",
4742 #endif
4743                 "spooty foot",
4744 #if 0
4745         /* FIXME: not working with s3 atm. */
4746                 "spooty\\fo,ot",
4747                 "spooty,fo\\ot"
4748 #endif
4749         };
4750         int i;
4751
4752         for (i=0; i < ARRAY_SIZE(values); i++) {
4753
4754                 enum winreg_Type type;
4755                 DATA_BLOB blob;
4756                 uint8_t *data;
4757                 uint32_t needed;
4758
4759                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4760                 type = REG_SZ;
4761
4762                 torture_assert(tctx,
4763                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4764                         "SetPrinterData failed");
4765
4766                 torture_assert(tctx,
4767                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4768                         "GetPrinterData failed");
4769
4770                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4771                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4772                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4773
4774                 if (winreg_handle && hive_handle) {
4775
4776                         enum winreg_Type w_type;
4777                         uint32_t w_size;
4778                         uint32_t w_length;
4779                         uint8_t *w_data;
4780
4781                         torture_assert(tctx,
4782                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4783                                         printer_name, "PrinterDriverData", values[i],
4784                                         &w_type, &w_size, &w_length, &w_data), "");
4785
4786                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4787                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4788                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4789                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4790                 }
4791
4792                 torture_assert(tctx,
4793                         test_DeletePrinterData(tctx, b, handle, values[i]),
4794                         "DeletePrinterData failed");
4795         }
4796
4797         return true;
4798 }
4799
4800
4801 static bool test_EnumPrinterKey(struct torture_context *tctx,
4802                                 struct dcerpc_binding_handle *b,
4803                                 struct policy_handle *handle,
4804                                 const char *key_name,
4805                                 const char ***array);
4806
4807 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4808                                   struct dcerpc_binding_handle *b,
4809                                   struct policy_handle *handle,
4810                                   const char *key_name,
4811                                   const char *value_name,
4812                                   enum winreg_Type type,
4813                                   uint8_t *data,
4814                                   uint32_t offered)
4815 {
4816         NTSTATUS status;
4817         struct spoolss_SetPrinterDataEx r;
4818
4819         r.in.handle = handle;
4820         r.in.key_name = key_name;
4821         r.in.value_name = value_name;
4822         r.in.type = type;
4823         r.in.data = data;
4824         r.in.offered = offered;
4825
4826         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4827                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4828
4829         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4830
4831         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4832         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4833
4834         return true;
4835 }
4836
4837 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4838                                        struct dcerpc_pipe *p,
4839                                        struct policy_handle *handle)
4840 {
4841         struct dcerpc_binding_handle *b = p->binding_handle;
4842         const char *value_name = "dog";
4843         const char *keys[] = {
4844                 "torturedataex",
4845                 "torture data ex",
4846                 "torturedataex_with_subkey\\subkey",
4847                 "torturedataex_with_subkey\\subkey:0",
4848                 "torturedataex_with_subkey\\subkey:1",
4849                 "torturedataex_with_subkey\\subkey\\subsubkey",
4850                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4851                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4852                 "torture,data",
4853                 "torture,data,ex",
4854                 "torture,data\\ex",
4855                 "torture\\data,ex",
4856                 "torture/data",
4857                 "torture/data ex",
4858                 "torture/data ex/sub",
4859                 "torture//data",
4860                 "torture//data ex",
4861                 "torture//data ex/sub",
4862                 "torture//data ex//sub",
4863         };
4864         int i;
4865
4866         for (i=0; i < ARRAY_SIZE(keys); i++) {
4867
4868                 char *c;
4869                 const char *key;
4870                 enum winreg_Type type;
4871                 DATA_BLOB blob_in, blob_out;
4872                 const char **subkeys;
4873                 uint32_t ecount;
4874                 struct spoolss_PrinterEnumValues *einfo;
4875                 uint32_t needed;
4876
4877                 blob_in = data_blob_talloc(tctx, NULL, 42);
4878
4879                 generate_random_buffer(blob_in.data, blob_in.length);
4880
4881                 torture_assert(tctx,
4882                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4883                         "failed to call SetPrinterDataEx");
4884
4885                 torture_assert(tctx,
4886                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4887                         "failed to call GetPrinterDataEx");
4888
4889                 blob_out.length = needed;
4890                 torture_assert(tctx,
4891                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4892                         "failed to call EnumPrinterDataEx");
4893
4894                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4895                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4896                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4897
4898                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4899                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4900                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4901                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4902                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4903                 if (einfo[0].data_length > 0) {
4904                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4905                 }
4906
4907                 key = talloc_strdup(tctx, keys[i]);
4908
4909                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4910                         return false;
4911                 }
4912
4913                 c = strchr(key, '\\');
4914                 if (c) {
4915                         int k;
4916
4917                         /* we have subkeys */
4918
4919                         *c = 0;
4920
4921                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4922                                 return false;
4923                         }
4924
4925                         for (k=0; subkeys && subkeys[k]; k++) {
4926
4927                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4928
4929                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4930                                         return false;
4931                                 }
4932                         }
4933
4934                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4935                                 return false;
4936                         }
4937
4938                 } else {
4939                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4940                                 return false;
4941                         }
4942                 }
4943         }
4944
4945         return true;
4946 }
4947
4948 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
4949                                          struct dcerpc_pipe *p,
4950                                          struct policy_handle *handle)
4951 {
4952         struct dcerpc_binding_handle *b = p->binding_handle;
4953         const char *key = "torturedataex";
4954         const char *values[] = {
4955                 "torture_value",
4956                 "torture value",
4957                 "torture,value",
4958                 "torture/value",
4959                 "torture\\value",
4960                 "torture\\\\value"
4961         };
4962         int i;
4963
4964         for (i=0; i < ARRAY_SIZE(values); i++) {
4965
4966                 enum winreg_Type type;
4967                 DATA_BLOB blob_in, blob_out;
4968                 uint32_t ecount;
4969                 struct spoolss_PrinterEnumValues *einfo;
4970                 uint32_t needed;
4971
4972                 if (torture_setting_bool(tctx, "samba3", false)) {
4973                         char *q;
4974                         q = strrchr(values[i], ',');
4975                         if (q) {
4976                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
4977                                                 values[i]);
4978                                 continue;
4979                         }
4980                 }
4981
4982                 blob_in = data_blob_talloc(tctx, NULL, 42);
4983
4984                 generate_random_buffer(blob_in.data, blob_in.length);
4985
4986                 torture_assert(tctx,
4987                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
4988                         "failed to call SetPrinterDataEx");
4989
4990                 torture_assert(tctx,
4991                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
4992                         "failed to call GetPrinterDataEx");
4993
4994                 blob_out.length = needed;
4995                 torture_assert(tctx,
4996                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
4997                         "failed to call EnumPrinterDataEx");
4998
4999                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5000                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5001                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5002
5003                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5004                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5005                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5006                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5007                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5008                 if (einfo[0].data_length > 0) {
5009                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5010                 }
5011
5012                 torture_assert(tctx,
5013                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5014                         "failed to call DeletePrinterDataEx");
5015         }
5016
5017         return true;
5018 }
5019
5020
5021 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5022                                          struct dcerpc_pipe *p,
5023                                          struct policy_handle *handle,
5024                                          const char *printername,
5025                                          struct dcerpc_binding_handle *winreg_handle,
5026                                          struct policy_handle *hive_handle)
5027 {
5028         struct dcerpc_binding_handle *b = p->binding_handle;
5029         const char *value_name = "dog";
5030         const char *key_name = "torturedataex";
5031         enum winreg_Type types[] = {
5032                 REG_SZ,
5033                 REG_MULTI_SZ,
5034                 REG_DWORD,
5035                 REG_BINARY
5036         };
5037         const char *str = "abcdefghi";
5038         int t, s;
5039
5040         for (t=0; t < ARRAY_SIZE(types); t++) {
5041         for (s=0; s < strlen(str); s++) {
5042
5043                 enum winreg_Type type;
5044                 const char *string = talloc_strndup(tctx, str, s);
5045                 const char *array[2];
5046                 DATA_BLOB blob = data_blob_string_const(string);
5047                 DATA_BLOB data;
5048                 uint8_t *data_out;
5049                 uint32_t needed, offered = 0;
5050                 uint32_t ecount;
5051                 struct spoolss_PrinterEnumValues *einfo;
5052
5053                 array[0] = talloc_strdup(tctx, string);
5054                 array[1] = NULL;
5055
5056                 if (types[t] == REG_DWORD) {
5057                         s = 0xffff;
5058                 }
5059
5060                 switch (types[t]) {
5061                 case REG_BINARY:
5062                         data = blob;
5063                         offered = blob.length;
5064                         break;
5065                 case REG_DWORD:
5066                         data = data_blob_talloc(tctx, NULL, 4);
5067                         SIVAL(data.data, 0, 0x12345678);
5068                         offered = 4;
5069                         break;
5070                 case REG_SZ:
5071                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5072                         type = REG_SZ;
5073                         offered = data.length;
5074                         /*strlen_m_term(data.string)*2;*/
5075                         break;
5076                 case REG_MULTI_SZ:
5077                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5078                         type = REG_MULTI_SZ;
5079                         offered = data.length;
5080                         break;
5081                 default:
5082                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5083                 }
5084
5085                 torture_assert(tctx,
5086                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5087                         "failed to call SetPrinterDataEx");
5088
5089                 torture_assert(tctx,
5090                         test_GetPrinterDataEx(tctx, p, handle, key_name, value_name, &type, &data_out, &needed),
5091                         "failed to call GetPrinterDataEx");
5092
5093                 torture_assert(tctx,
5094                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5095                         "failed to call EnumPrinterDataEx");
5096
5097                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5098                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5099                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5100
5101                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5102                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5103                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5104                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5105                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5106                 if (einfo[0].data_length > 0) {
5107                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5108                 }
5109
5110                 if (winreg_handle && hive_handle) {
5111                         enum winreg_Type w_type;
5112                         uint32_t w_size;
5113                         uint32_t w_length;
5114                         uint8_t *w_data;
5115
5116                         torture_assert(tctx,
5117                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5118                                         printername, key_name, value_name,
5119                                         &w_type, &w_size, &w_length, &w_data), "");
5120
5121                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5122                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5123                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5124                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5125                 }
5126
5127                 torture_assert(tctx,
5128                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5129                         "failed to call DeletePrinterDataEx");
5130         }
5131         }
5132
5133         return true;
5134 }
5135
5136 static bool test_PrinterData_winreg(struct torture_context *tctx,
5137                                     struct dcerpc_pipe *p,
5138                                     struct policy_handle *handle,
5139                                     const char *printer_name)
5140 {
5141         struct dcerpc_binding_handle *b = p->binding_handle;
5142         struct dcerpc_pipe *p2;
5143         bool ret = true;
5144         struct policy_handle hive_handle;
5145         struct dcerpc_binding_handle *b2;
5146
5147         torture_assert_ntstatus_ok(tctx,
5148                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5149                 "could not open winreg pipe");
5150         b2 = p2->binding_handle;
5151
5152         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5153
5154         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5155         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5156
5157         test_winreg_CloseKey(tctx, b2, &hive_handle);
5158
5159         talloc_free(p2);
5160
5161         return ret;
5162 }
5163
5164 static bool test_Forms_winreg(struct torture_context *tctx,
5165                               struct dcerpc_binding_handle *b,
5166                               struct policy_handle *handle,
5167                               bool print_server,
5168                               const char *printer_name)
5169 {
5170         struct dcerpc_pipe *p2;
5171         bool ret = true;
5172         struct policy_handle hive_handle;
5173         struct dcerpc_binding_handle *b2;
5174
5175         torture_assert_ntstatus_ok(tctx,
5176                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5177                 "could not open winreg pipe");
5178         b2 = p2->binding_handle;
5179
5180         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5181
5182         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5183
5184         test_winreg_CloseKey(tctx, b2, &hive_handle);
5185
5186         talloc_free(p2);
5187
5188         return ret;
5189 }
5190
5191 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5192                                     struct dcerpc_pipe *p,
5193                                     struct policy_handle *handle,
5194                                     const char *printer_name)
5195 {
5196         struct dcerpc_binding_handle *b = p->binding_handle;
5197         struct dcerpc_pipe *p2;
5198         bool ret = true;
5199         struct policy_handle hive_handle;
5200         struct dcerpc_binding_handle *b2;
5201
5202         torture_assert_ntstatus_ok(tctx,
5203                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5204                 "could not open winreg pipe");
5205         b2 = p2->binding_handle;
5206
5207         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5208
5209         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5210
5211         test_winreg_CloseKey(tctx, b2, &hive_handle);
5212
5213         talloc_free(p2);
5214
5215         return ret;
5216 }
5217
5218 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5219                                    struct dcerpc_pipe *p,
5220                                    struct policy_handle *handle,
5221                                    const char *printer_name,
5222                                    const char *driver_name,
5223                                    const char *environment)
5224 {
5225         struct dcerpc_binding_handle *b = p->binding_handle;
5226         struct dcerpc_pipe *p2;
5227         bool ret = true;
5228         struct policy_handle hive_handle;
5229         struct dcerpc_binding_handle *b2;
5230
5231         torture_assert_ntstatus_ok(tctx,
5232                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5233                 "could not open winreg pipe");
5234         b2 = p2->binding_handle;
5235
5236         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5237
5238         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
5239
5240         test_winreg_CloseKey(tctx, b2, &hive_handle);
5241
5242         talloc_free(p2);
5243
5244         return ret;
5245 }
5246
5247 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5248                                         struct dcerpc_binding_handle *b,
5249                                         const char *environment)
5250 {
5251         struct dcerpc_pipe *p2;
5252         bool ret = true;
5253         struct policy_handle hive_handle;
5254         struct dcerpc_binding_handle *b2;
5255
5256         torture_assert_ntstatus_ok(tctx,
5257                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5258                 "could not open winreg pipe");
5259         b2 = p2->binding_handle;
5260
5261         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5262
5263         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5264
5265         test_winreg_CloseKey(tctx, b2, &hive_handle);
5266
5267         talloc_free(p2);
5268
5269         return ret;
5270 }
5271
5272 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5273                                        struct dcerpc_pipe *p,
5274                                        struct policy_handle *handle,
5275                                        const char *printer_name)
5276 {
5277         struct spoolss_SetPrinterInfoCtr info_ctr;
5278         struct spoolss_DevmodeContainer devmode_ctr;
5279         struct sec_desc_buf secdesc_ctr;
5280         union spoolss_SetPrinterInfo sinfo;
5281         union spoolss_PrinterInfo info;
5282         struct dcerpc_binding_handle *b = p->binding_handle;
5283         const char *pname;
5284
5285         ZERO_STRUCT(info_ctr);
5286         ZERO_STRUCT(devmode_ctr);
5287         ZERO_STRUCT(secdesc_ctr);
5288
5289         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5290
5291         torture_assert(tctx,
5292                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5293                 "failed to query Printer level 2");
5294
5295         torture_assert(tctx,
5296                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5297                 "failed to convert");
5298
5299         info_ctr.level = 2;
5300         info_ctr.info = sinfo;
5301
5302 #define TEST_SZ(wname, iname) \
5303 do {\
5304         enum winreg_Type type;\
5305         uint8_t *data;\
5306         uint32_t needed;\
5307         DATA_BLOB blob;\
5308         const char *str;\
5309         torture_assert(tctx,\
5310                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5311                 "failed to query");\
5312         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5313         blob = data_blob_const(data, needed);\
5314         torture_assert(tctx,\
5315                 pull_reg_sz(tctx, &blob, &str),\
5316                 "failed to pull REG_SZ");\
5317         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5318 } while(0);
5319
5320
5321 #define TEST_SET_SZ(wname, iname, val) \
5322 do {\
5323         enum winreg_Type type;\
5324         uint8_t *data;\
5325         uint32_t needed;\
5326         DATA_BLOB blob;\
5327         const char *str;\
5328         sinfo.info2->iname = val;\
5329         torture_assert(tctx,\
5330                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5331                 "failed to call SetPrinter");\
5332         torture_assert(tctx,\
5333                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5334                 "failed to query");\
5335         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5336         blob = data_blob_const(data, needed);\
5337         torture_assert(tctx,\
5338                 pull_reg_sz(tctx, &blob, &str),\
5339                 "failed to pull REG_SZ");\
5340         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5341 } while(0);
5342
5343 #define TEST_SET_DWORD(wname, iname, val) \
5344 do {\
5345         enum winreg_Type type;\
5346         uint8_t *data;\
5347         uint32_t needed;\
5348         uint32_t value;\
5349         sinfo.info2->iname = val;\
5350         torture_assert(tctx,\
5351                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5352                 "failed to call SetPrinter");\
5353         torture_assert(tctx,\
5354                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5355                 "failed to query");\
5356         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5357         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5358         value = IVAL(data, 0); \
5359         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5360 } while(0);
5361
5362         TEST_SET_SZ("description", comment, "newval");
5363         TEST_SET_SZ("location", location, "newval");
5364 /*      TEST_SET_DWORD("priority", priority, 25); */
5365
5366         torture_assert(tctx,
5367                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5368                 "failed to query Printer level 2");
5369
5370         TEST_SZ("description", info.info2.comment);
5371         TEST_SZ("driverName", info.info2.drivername);
5372         TEST_SZ("location", info.info2.location);
5373
5374         pname = strrchr(info.info2.printername, '\\');
5375         if (pname == NULL) {
5376                 pname = info.info2.printername;
5377         } else {
5378                 pname++;
5379         }
5380         TEST_SZ("printerName", pname);
5381         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5382         /* TEST_SZ("printShareName", info.info2.sharename); */
5383
5384         /* FIXME gd: complete the list */
5385
5386 #undef TEST_SZ
5387 #undef TEST_SET_SZ
5388 #undef TEST_DWORD
5389
5390         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5391
5392         return true;
5393 }
5394
5395 static bool test_print_processors_winreg(struct torture_context *tctx,
5396                                          void *private_data)
5397 {
5398         struct test_spoolss_context *ctx =
5399                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5400         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5401         struct dcerpc_binding_handle *b = p->binding_handle;
5402
5403         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5404 }
5405
5406 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5407                                          struct dcerpc_binding_handle *b,
5408                                          struct policy_handle *handle,
5409                                          uint32_t *change_id)
5410 {
5411         enum winreg_Type type;
5412         uint8_t *data;
5413         uint32_t needed;
5414
5415         torture_assert(tctx,
5416                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5417                 "failed to call GetPrinterData");
5418
5419         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5420         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5421
5422         *change_id = IVAL(data, 0);
5423
5424         return true;
5425 }
5426
5427 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5428                                            struct dcerpc_pipe *p,
5429                                            struct policy_handle *handle,
5430                                            uint32_t *change_id)
5431 {
5432         enum winreg_Type type;
5433         uint8_t *data;
5434         uint32_t needed;
5435
5436         torture_assert(tctx,
5437                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5438                 "failed to call GetPrinterData");
5439
5440         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5441         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5442
5443         *change_id = IVAL(data, 0);
5444
5445         return true;
5446 }
5447
5448 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5449                                          struct dcerpc_binding_handle *b,
5450                                          struct policy_handle *handle,
5451                                          uint32_t *change_id)
5452 {
5453         union spoolss_PrinterInfo info;
5454
5455         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5456                 "failed to query Printer level 0");
5457
5458         *change_id = info.info0.change_id;
5459
5460         return true;
5461 }
5462
5463 static bool test_ChangeID(struct torture_context *tctx,
5464                           struct dcerpc_pipe *p,
5465                           struct policy_handle *handle)
5466 {
5467         uint32_t change_id, change_id_ex, change_id_info;
5468         uint32_t change_id2, change_id_ex2, change_id_info2;
5469         union spoolss_PrinterInfo info;
5470         const char *comment;
5471         struct dcerpc_binding_handle *b = p->binding_handle;
5472
5473         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5474
5475         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5476                 "failed to query for ChangeID");
5477         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5478                 "failed to query for ChangeID");
5479         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5480                 "failed to query for ChangeID");
5481
5482         torture_assert_int_equal(tctx, change_id, change_id_ex,
5483                 "change_ids should all be equal");
5484         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5485                 "change_ids should all be equal");
5486
5487
5488         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5489
5490         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5491                 "failed to query for ChangeID");
5492         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5493                 "failed to query Printer level 2");
5494         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5495                 "failed to query for ChangeID");
5496         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5497                 "failed to query for ChangeID");
5498         torture_assert_int_equal(tctx, change_id, change_id_ex,
5499                 "change_id should not have changed");
5500         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5501                 "change_id should not have changed");
5502
5503
5504         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5505
5506         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5507                 "failed to query for ChangeID");
5508         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5509                 "failed to query for ChangeID");
5510         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5511                 "failed to query for ChangeID");
5512         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5513                 "failed to query Printer level 2");
5514         comment = talloc_strdup(tctx, info.info2.comment);
5515
5516         {
5517                 struct spoolss_SetPrinterInfoCtr info_ctr;
5518                 struct spoolss_DevmodeContainer devmode_ctr;
5519                 struct sec_desc_buf secdesc_ctr;
5520                 union spoolss_SetPrinterInfo sinfo;
5521
5522                 ZERO_STRUCT(info_ctr);
5523                 ZERO_STRUCT(devmode_ctr);
5524                 ZERO_STRUCT(secdesc_ctr);
5525
5526
5527                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5528                 sinfo.info2->comment    = "torture_comment";
5529
5530                 info_ctr.level = 2;
5531                 info_ctr.info = sinfo;
5532
5533                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5534                         "failed to call SetPrinter");
5535
5536                 sinfo.info2->comment    = comment;
5537
5538                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5539                         "failed to call SetPrinter");
5540
5541         }
5542
5543         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5544                 "failed to query for ChangeID");
5545         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5546                 "failed to query for ChangeID");
5547         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5548                 "failed to query for ChangeID");
5549
5550         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5551                 "change_ids should all be equal");
5552         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5553                 "change_ids should all be equal");
5554
5555         torture_assert(tctx, (change_id < change_id2),
5556                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5557                 change_id2, change_id));
5558         torture_assert(tctx, (change_id_ex < change_id_ex2),
5559                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5560                 change_id_ex2, change_id_ex));
5561         torture_assert(tctx, (change_id_info < change_id_info2),
5562                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5563                 change_id_info2, change_id_info));
5564
5565         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5566
5567         return true;
5568 }
5569
5570 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5571                                        struct dcerpc_pipe *p,
5572                                        struct policy_handle *handle)
5573 {
5574         NTSTATUS status;
5575         struct dcerpc_binding *b;
5576         struct dcerpc_pipe *p2;
5577         struct spoolss_ClosePrinter cp;
5578
5579         /* only makes sense on SMB */
5580         if (p->conn->transport.transport != NCACN_NP) {
5581                 return true;
5582         }
5583
5584         torture_comment(tctx, "Testing close on secondary pipe\n");
5585
5586         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5587         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5588
5589         status = dcerpc_secondary_connection(p, &p2, b);
5590         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5591
5592         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5593         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5594
5595         cp.in.handle = handle;
5596         cp.out.handle = handle;
5597
5598         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5599         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5600                         "ERROR: Allowed close on secondary connection");
5601
5602         talloc_free(p2);
5603
5604         return true;
5605 }
5606
5607 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5608                                      struct dcerpc_binding_handle *b, const char *name)
5609 {
5610         NTSTATUS status;
5611         struct spoolss_OpenPrinter op;
5612         struct spoolss_OpenPrinterEx opEx;
5613         struct policy_handle handle;
5614         bool ret = true;
5615
5616         op.in.printername       = name;
5617         op.in.datatype          = NULL;
5618         op.in.devmode_ctr.devmode= NULL;
5619         op.in.access_mask       = 0;
5620         op.out.handle           = &handle;
5621
5622         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5623
5624         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5625         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5626         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5627                 "unexpected result");
5628
5629         if (W_ERROR_IS_OK(op.out.result)) {
5630                 ret &=test_ClosePrinter(tctx, b, &handle);
5631         }
5632
5633         opEx.in.printername             = name;
5634         opEx.in.datatype                = NULL;
5635         opEx.in.devmode_ctr.devmode     = NULL;
5636         opEx.in.access_mask             = 0;
5637         opEx.in.level                   = 1;
5638         opEx.in.userlevel.level1        = NULL;
5639         opEx.out.handle                 = &handle;
5640
5641         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5642
5643         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5644         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5645         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5646                 "unexpected result");
5647
5648         if (W_ERROR_IS_OK(opEx.out.result)) {
5649                 ret &=test_ClosePrinter(tctx, b, &handle);
5650         }
5651
5652         return ret;
5653 }
5654
5655 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5656                                           void *private_data)
5657 {
5658         struct test_spoolss_context *ctx =
5659                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5660
5661         const char *badnames[] = {
5662                 "__INVALID_PRINTER__",
5663                 "\\\\__INVALID_HOST__",
5664                 "",
5665                 "\\\\\\",
5666                 "\\\\\\__INVALID_PRINTER__"
5667         };
5668         const char *badname;
5669         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5670         const char *server_name = dcerpc_server_name(p);
5671         struct dcerpc_binding_handle *b = p->binding_handle;
5672         int i;
5673
5674         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5675                 torture_assert(tctx,
5676                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5677                         "");
5678         }
5679
5680         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5681         torture_assert(tctx,
5682                 test_OpenPrinter_badname(tctx, b, badname),
5683                 "");
5684
5685         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5686         torture_assert(tctx,
5687                 test_OpenPrinter_badname(tctx, b, badname),
5688                 "");
5689
5690         return true;
5691 }
5692
5693 static bool test_OpenPrinter(struct torture_context *tctx,
5694                              struct dcerpc_pipe *p,
5695                              const char *name,
5696                              const char *environment,
5697                              bool open_only)
5698 {
5699         NTSTATUS status;
5700         struct spoolss_OpenPrinter r;
5701         struct policy_handle handle;
5702         bool ret = true;
5703         struct dcerpc_binding_handle *b = p->binding_handle;
5704
5705         r.in.printername        = name;
5706         r.in.datatype           = NULL;
5707         r.in.devmode_ctr.devmode= NULL;
5708         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5709         r.out.handle            = &handle;
5710
5711         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5712
5713         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5714
5715         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5716
5717         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5718
5719         if (open_only) {
5720                 goto close_printer;
5721         }
5722
5723         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5724                 ret = false;
5725         }
5726
5727         if (!torture_setting_bool(tctx, "samba3", false)) {
5728                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5729                         ret = false;
5730                 }
5731         }
5732
5733  close_printer:
5734         if (!test_ClosePrinter(tctx, b, &handle)) {
5735                 ret = false;
5736         }
5737
5738         return ret;
5739 }
5740
5741 static bool test_OpenPrinterEx(struct torture_context *tctx,
5742                                struct dcerpc_binding_handle *b,
5743                                const char *printername,
5744                                const char *datatype,
5745                                struct spoolss_DeviceMode *devmode,
5746                                uint32_t access_mask,
5747                                uint32_t level,
5748                                union spoolss_UserLevel *userlevel,
5749                                struct policy_handle *handle,
5750                                WERROR expected_result)
5751 {
5752         struct spoolss_OpenPrinterEx r;
5753
5754         r.in.printername        = printername;
5755         r.in.datatype           = datatype;
5756         r.in.devmode_ctr.devmode= devmode;
5757         r.in.access_mask        = access_mask;
5758         r.in.level              = level;
5759         r.in.userlevel          = *userlevel;
5760         r.out.handle            = handle;
5761
5762         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5763
5764         torture_assert_ntstatus_ok(tctx,
5765                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5766                 "OpenPrinterEx failed");
5767
5768         torture_assert_werr_equal(tctx, r.out.result, expected_result,
5769                 "OpenPrinterEx failed");
5770
5771         return true;
5772 }
5773
5774 static bool call_OpenPrinterEx(struct torture_context *tctx,
5775                                struct dcerpc_pipe *p,
5776                                const char *name,
5777                                struct spoolss_DeviceMode *devmode,
5778                                struct policy_handle *handle)
5779 {
5780         struct spoolss_OpenPrinterEx r;
5781         union spoolss_UserLevel userlevel;
5782         struct spoolss_UserLevel1 userlevel1;
5783         NTSTATUS status;
5784         struct dcerpc_binding_handle *b = p->binding_handle;
5785
5786         userlevel1.size = 1234;
5787         userlevel1.client = "hello";
5788         userlevel1.user = "spottyfoot!";
5789         userlevel1.build = 1;
5790         userlevel1.major = 2;
5791         userlevel1.minor = 3;
5792         userlevel1.processor = 4;
5793
5794         userlevel.level1 = &userlevel1;
5795
5796         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5797                                   SEC_FLAG_MAXIMUM_ALLOWED,
5798                                   1,
5799                                   &userlevel,
5800                                   handle,
5801                                   WERR_OK);
5802 }
5803
5804 static bool test_printer_rename(struct torture_context *tctx,
5805                                 void *private_data)
5806 {
5807         struct torture_printer_context *t =
5808                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5809         struct dcerpc_pipe *p = t->spoolss_pipe;
5810
5811         bool ret = true;
5812         union spoolss_PrinterInfo info;
5813         union spoolss_SetPrinterInfo sinfo;
5814         struct spoolss_SetPrinterInfoCtr info_ctr;
5815         struct spoolss_DevmodeContainer devmode_ctr;
5816         struct sec_desc_buf secdesc_ctr;
5817         const char *printer_name;
5818         const char *printer_name_orig;
5819         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5820         struct policy_handle new_handle;
5821         const char *q;
5822         struct dcerpc_binding_handle *b = p->binding_handle;
5823
5824         ZERO_STRUCT(devmode_ctr);
5825         ZERO_STRUCT(secdesc_ctr);
5826
5827         torture_comment(tctx, "Testing Printer rename operations\n");
5828
5829         torture_assert(tctx,
5830                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5831                 "failed to call GetPrinter level 2");
5832
5833         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5834
5835         q = strrchr(info.info2.printername, '\\');
5836         if (q) {
5837                 torture_warning(tctx,
5838                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5839         }
5840
5841         torture_assert(tctx,
5842                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5843
5844         sinfo.info2->printername = printer_name_new;
5845
5846         info_ctr.level = 2;
5847         info_ctr.info = sinfo;
5848
5849         torture_assert(tctx,
5850                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5851                 "failed to call SetPrinter level 2");
5852
5853         torture_assert(tctx,
5854                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5855                 "failed to call GetPrinter level 2");
5856
5857         printer_name = talloc_strdup(tctx, info.info2.printername);
5858
5859         q = strrchr(info.info2.printername, '\\');
5860         if (q) {
5861                 torture_warning(tctx,
5862                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5863                 q++;
5864                 printer_name = q;
5865         }
5866
5867         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5868                 "new printer name was not set");
5869
5870         /* samba currently cannot fully rename printers */
5871         if (!torture_setting_bool(tctx, "samba3", false)) {
5872                 torture_assert(tctx,
5873                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5874                         "still can open printer with oldname after rename");
5875         } else {
5876                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5877         }
5878
5879         torture_assert(tctx,
5880                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5881                 "failed to open printer with new name");
5882
5883         torture_assert(tctx,
5884                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5885                 "failed to call GetPrinter level 2");
5886
5887         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
5888                 "new printer name was not set");
5889
5890         torture_assert(tctx,
5891                 test_ClosePrinter(tctx, b, &new_handle),
5892                 "failed to close printer");
5893
5894         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5895
5896         return ret;
5897 }
5898
5899
5900 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
5901                                                 struct dcerpc_pipe *p,
5902                                                 const char *name,
5903                                                 const char *environment)
5904 {
5905         struct policy_handle handle;
5906         bool ret = true;
5907         struct dcerpc_binding_handle *b = p->binding_handle;
5908
5909         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5910                 return false;
5911         }
5912
5913         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5914                 ret = false;
5915         }
5916
5917         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5918                 ret = false;
5919         }
5920
5921         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5922                 ret = false;
5923         }
5924
5925         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5926                 ret = false;
5927         }
5928
5929         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5930                 ret = false;
5931         }
5932
5933         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5934                 ret = false;
5935         }
5936
5937         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5938                 ret = false;
5939         }
5940
5941         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5942                 ret = false;
5943         }
5944
5945         if (!test_printer_all_keys(tctx, b, &handle)) {
5946                 ret = false;
5947         }
5948
5949         if (!test_PausePrinter(tctx, b, &handle)) {
5950                 ret = false;
5951         }
5952
5953         if (!test_DoPrintTest(tctx, b, &handle)) {
5954                 ret = false;
5955         }
5956
5957         if (!test_ResumePrinter(tctx, b, &handle)) {
5958                 ret = false;
5959         }
5960
5961         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5962                 ret = false;
5963         }
5964
5965         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5966                 ret = false;
5967         }
5968
5969         if (!torture_setting_bool(tctx, "samba3", false)) {
5970                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5971                         ret = false;
5972                 }
5973         }
5974
5975         if (!test_ClosePrinter(tctx, b, &handle)) {
5976                 ret = false;
5977         }
5978
5979         return ret;
5980 }
5981
5982 static bool test_EnumPrinters_old(struct torture_context *tctx,
5983                                   void *private_data)
5984 {
5985         struct test_spoolss_context *ctx =
5986                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5987         struct spoolss_EnumPrinters r;
5988         NTSTATUS status;
5989         uint16_t levels[] = {1, 2, 4, 5};
5990         int i;
5991         bool ret = true;
5992         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5993         struct dcerpc_binding_handle *b = p->binding_handle;
5994
5995         for (i=0;i<ARRAY_SIZE(levels);i++) {
5996                 union spoolss_PrinterInfo *info;
5997                 int j;
5998                 uint32_t needed;
5999                 uint32_t count;
6000
6001                 r.in.flags      = PRINTER_ENUM_LOCAL;
6002                 r.in.server     = "";
6003                 r.in.level      = levels[i];
6004                 r.in.buffer     = NULL;
6005                 r.in.offered    = 0;
6006                 r.out.needed    = &needed;
6007                 r.out.count     = &count;
6008                 r.out.info      = &info;
6009
6010                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6011
6012                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6013                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6014
6015                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6016                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6017                         r.in.buffer = &blob;
6018                         r.in.offered = needed;
6019                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6020                 }
6021
6022                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6023
6024                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6025
6026                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6027
6028                 if (!info) {
6029                         torture_comment(tctx, "No printers returned\n");
6030                         return true;
6031                 }
6032
6033                 for (j=0;j<count;j++) {
6034                         if (r.in.level == 1) {
6035                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
6036                                 char *slash, *name, *full_name;
6037                                 name = unc;
6038                                 if (unc[0] == '\\' && unc[1] == '\\') {
6039                                         unc +=2;
6040                                 }
6041                                 slash = strchr(unc, '\\');
6042                                 if (slash) {
6043                                         slash++;
6044                                         name = slash;
6045                                 }
6046                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6047                                                             dcerpc_server_name(p), name);
6048                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6049                                         ret = false;
6050                                 }
6051                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6052                                         ret = false;
6053                                 }
6054                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6055                                         ret = false;
6056                                 }
6057                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6058                                         ret = false;
6059                                 }
6060                         }
6061                 }
6062         }
6063
6064         return ret;
6065 }
6066
6067 static bool test_EnumPrinters_level(struct torture_context *tctx,
6068                                     struct dcerpc_binding_handle *b,
6069                                     uint32_t flags,
6070                                     const char *servername,
6071                                     uint32_t level,
6072                                     uint32_t *count_p,
6073                                     union spoolss_PrinterInfo **info_p)
6074 {
6075         struct spoolss_EnumPrinters r;
6076         union spoolss_PrinterInfo *info;
6077         uint32_t needed;
6078         uint32_t count;
6079
6080         r.in.flags      = flags;
6081         r.in.server     = servername;
6082         r.in.level      = level;
6083         r.in.buffer     = NULL;
6084         r.in.offered    = 0;
6085         r.out.needed    = &needed;
6086         r.out.count     = &count;
6087         r.out.info      = &info;
6088
6089         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6090                 r.in.server, r.in.level);
6091
6092         torture_assert_ntstatus_ok(tctx,
6093                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6094                 "EnumPrinters failed");
6095         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6096                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6097                 r.in.buffer = &blob;
6098                 r.in.offered = needed;
6099                 torture_assert_ntstatus_ok(tctx,
6100                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6101                         "EnumPrinters failed");
6102         }
6103
6104         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6105
6106         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6107
6108         if (count_p) {
6109                 *count_p = count;
6110         }
6111         if (info_p) {
6112                 *info_p = info;
6113         }
6114
6115         return true;
6116 }
6117
6118 static const char *get_short_printername(struct torture_context *tctx,
6119                                          const char *name)
6120 {
6121         const char *short_name;
6122
6123         if (name[0] == '\\' && name[1] == '\\') {
6124                 name += 2;
6125                 short_name = strchr(name, '\\');
6126                 if (short_name) {
6127                         return talloc_strdup(tctx, short_name+1);
6128                 }
6129         }
6130
6131         return name;
6132 }
6133
6134 static const char *get_full_printername(struct torture_context *tctx,
6135                                         const char *name)
6136 {
6137         const char *full_name = talloc_strdup(tctx, name);
6138         char *p;
6139
6140         if (name && name[0] == '\\' && name[1] == '\\') {
6141                 name += 2;
6142                 p = strchr(name, '\\');
6143                 if (p) {
6144                         return full_name;
6145                 }
6146         }
6147
6148         return NULL;
6149 }
6150
6151 static bool test_OnePrinter_servername(struct torture_context *tctx,
6152                                        struct dcerpc_pipe *p,
6153                                        struct dcerpc_binding_handle *b,
6154                                        const char *servername,
6155                                        const char *printername)
6156 {
6157         union spoolss_PrinterInfo info;
6158         const char *short_name = get_short_printername(tctx, printername);
6159         const char *full_name = get_full_printername(tctx, printername);
6160
6161         if (short_name) {
6162                 struct policy_handle handle;
6163                 torture_assert(tctx,
6164                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6165                         "failed to open printer");
6166
6167                 torture_assert(tctx,
6168                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6169                         "failed to get printer info");
6170
6171                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6172                         "unexpected servername");
6173                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6174                         "unexpected printername");
6175
6176                 if (info.info2.devmode) {
6177                         const char *expected_devicename;
6178                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6179                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6180                                 "unexpected devicemode devicename");
6181                 }
6182
6183                 torture_assert(tctx,
6184                         test_ClosePrinter(tctx, b, &handle),
6185                         "failed to close printer");
6186         }
6187
6188         if (full_name) {
6189                 struct policy_handle handle;
6190
6191                 torture_assert(tctx,
6192                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6193                         "failed to open printer");
6194
6195                 torture_assert(tctx,
6196                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6197                         "failed to get printer info");
6198
6199                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6200                         "unexpected servername");
6201                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6202                         "unexpected printername");
6203
6204                 if (info.info2.devmode) {
6205                         const char *expected_devicename;
6206                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6207                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6208                                 "unexpected devicemode devicename");
6209                 }
6210
6211                 torture_assert(tctx,
6212                         test_ClosePrinter(tctx, b, &handle),
6213                         "failed to close printer");
6214         }
6215
6216         return true;
6217 }
6218
6219 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6220                                          void *private_data)
6221 {
6222         struct test_spoolss_context *ctx =
6223                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6224         int i;
6225         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6226         struct dcerpc_binding_handle *b = p->binding_handle;
6227         uint32_t count;
6228         union spoolss_PrinterInfo *info;
6229         const char *servername;
6230         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6231
6232         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6233
6234         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6235
6236         torture_assert(tctx,
6237                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6238                 "failed to enumerate printers");
6239
6240         for (i=0; i < count; i++) {
6241
6242                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6243                         "unexpected servername");
6244
6245                 torture_assert(tctx,
6246                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6247                         "failed to check printer");
6248         }
6249
6250         servername = "";
6251
6252         torture_assert(tctx,
6253                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6254                 "failed to enumerate printers");
6255
6256         for (i=0; i < count; i++) {
6257
6258                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6259                         "unexpected servername");
6260
6261                 torture_assert(tctx,
6262                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6263                         "failed to check printer");
6264         }
6265
6266
6267         return true;
6268 }
6269
6270
6271 static bool test_GetPrinterDriver(struct torture_context *tctx,
6272                                   struct dcerpc_binding_handle *b,
6273                                   struct policy_handle *handle,
6274                                   const char *driver_name)
6275 {
6276         struct spoolss_GetPrinterDriver r;
6277         uint32_t needed;
6278
6279         r.in.handle = handle;
6280         r.in.architecture = "W32X86";
6281         r.in.level = 1;
6282         r.in.buffer = NULL;
6283         r.in.offered = 0;
6284         r.out.needed = &needed;
6285
6286         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6287
6288         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6289                 "failed to call GetPrinterDriver");
6290         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6291                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6292                 r.in.buffer = &blob;
6293                 r.in.offered = needed;
6294                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6295                         "failed to call GetPrinterDriver");
6296         }
6297
6298         torture_assert_werr_ok(tctx, r.out.result,
6299                 "failed to call GetPrinterDriver");
6300
6301         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6302
6303         return true;
6304 }
6305
6306 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6307                                          struct dcerpc_binding_handle *b,
6308                                          struct policy_handle *handle,
6309                                          const char *driver_name,
6310                                          const char *architecture,
6311                                          uint32_t level,
6312                                          uint32_t client_major_version,
6313                                          uint32_t client_minor_version,
6314                                          union spoolss_DriverInfo *info_p,
6315                                          WERROR *result_p)
6316
6317 {
6318         struct spoolss_GetPrinterDriver2 r;
6319         uint32_t needed;
6320         uint32_t server_major_version;
6321         uint32_t server_minor_version;
6322
6323         r.in.handle = handle;
6324         r.in.architecture = architecture;
6325         r.in.client_major_version = client_major_version;
6326         r.in.client_minor_version = client_minor_version;
6327         r.in.buffer = NULL;
6328         r.in.offered = 0;
6329         r.in.level = level;
6330         r.out.needed = &needed;
6331         r.out.server_major_version = &server_major_version;
6332         r.out.server_minor_version = &server_minor_version;
6333
6334         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6335                 driver_name, r.in.level);
6336
6337         torture_assert_ntstatus_ok(tctx,
6338                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6339                 "failed to call GetPrinterDriver2");
6340         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6341                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6342                 r.in.buffer = &blob;
6343                 r.in.offered = needed;
6344                 torture_assert_ntstatus_ok(tctx,
6345                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6346                         "failed to call GetPrinterDriver2");
6347         }
6348
6349         if (result_p) {
6350                 *result_p = r.out.result;
6351         }
6352
6353         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6354                 switch (r.in.level) {
6355                 case 101:
6356                 case 8:
6357                         torture_comment(tctx,
6358                                 "level %d not implemented, not considering as an error\n",
6359                                 r.in.level);
6360                         return true;
6361                 default:
6362                         break;
6363                 }
6364         }
6365
6366         torture_assert_werr_ok(tctx, r.out.result,
6367                 "failed to call GetPrinterDriver2");
6368
6369         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6370
6371         if (info_p) {
6372                 *info_p = *r.out.info;
6373         }
6374
6375         return true;
6376 }
6377
6378 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6379                                    struct dcerpc_binding_handle *b,
6380                                    struct policy_handle *handle,
6381                                    const char *driver_name,
6382                                    const char *architecture)
6383 {
6384         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6385         int i;
6386
6387
6388         for (i=0;i<ARRAY_SIZE(levels);i++) {
6389
6390                 torture_assert(tctx,
6391                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6392                         "");
6393         }
6394
6395         return true;
6396 }
6397
6398 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6399                                         void *private_data)
6400 {
6401         struct test_spoolss_context *ctx =
6402                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6403         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6404         int i;
6405         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6406         struct dcerpc_binding_handle *b = p->binding_handle;
6407         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6408
6409         for (i=0;i<ARRAY_SIZE(levels);i++) {
6410
6411                 uint32_t count;
6412                 union spoolss_DriverInfo *info;
6413
6414                 torture_assert(tctx,
6415                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6416                         "failed to enumerate drivers");
6417
6418                 if (!info) {
6419                         torture_comment(tctx, "No printer drivers returned\n");
6420                         break;
6421                 }
6422         }
6423
6424         return true;
6425 }
6426
6427 static bool test_DeletePrinter(struct torture_context *tctx,
6428                                struct dcerpc_binding_handle *b,
6429                                struct policy_handle *handle)
6430 {
6431         struct spoolss_DeletePrinter r;
6432
6433         torture_comment(tctx, "Testing DeletePrinter\n");
6434
6435         r.in.handle = handle;
6436
6437         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6438                 "failed to delete printer");
6439         torture_assert_werr_ok(tctx, r.out.result,
6440                 "failed to delete printer");
6441
6442         return true;
6443 }
6444
6445 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6446                                        struct dcerpc_binding_handle *b,
6447                                        uint32_t flags,
6448                                        uint32_t level,
6449                                        const char *name,
6450                                        bool *found)
6451 {
6452         struct spoolss_EnumPrinters e;
6453         uint32_t count;
6454         union spoolss_PrinterInfo *info;
6455         uint32_t needed;
6456         int i;
6457
6458         *found = false;
6459
6460         e.in.flags = flags;
6461         e.in.server = NULL;
6462         e.in.level = level;
6463         e.in.buffer = NULL;
6464         e.in.offered = 0;
6465         e.out.count = &count;
6466         e.out.info = &info;
6467         e.out.needed = &needed;
6468
6469         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6470                 "failed to enum printers");
6471
6472         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6473                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6474                 e.in.buffer = &blob;
6475                 e.in.offered = needed;
6476
6477                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6478                         "failed to enum printers");
6479         }
6480
6481         torture_assert_werr_ok(tctx, e.out.result,
6482                 "failed to enum printers");
6483
6484         for (i=0; i < count; i++) {
6485
6486                 const char *current = NULL;
6487                 const char *q;
6488
6489                 switch (level) {
6490                 case 1:
6491                         current = info[i].info1.name;
6492                         break;
6493                 }
6494
6495                 if (strequal(current, name)) {
6496                         *found = true;
6497                         break;
6498                 }
6499
6500                 q = strrchr(current, '\\');
6501                 if (q) {
6502                         if (!e.in.server) {
6503                                 torture_warning(tctx,
6504                                         "server returns printername %s incl. servername although we did not set servername", current);
6505                         }
6506                         q++;
6507                         if (strequal(q, name)) {
6508                                 *found = true;
6509                                 break;
6510                         }
6511                 }
6512         }
6513
6514         return true;
6515 }
6516
6517 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6518                                       struct dcerpc_pipe *p,
6519                                       const char *printername,
6520                                       bool ex)
6521 {
6522         WERROR result;
6523         struct spoolss_AddPrinter r;
6524         struct spoolss_AddPrinterEx rex;
6525         struct spoolss_SetPrinterInfoCtr info_ctr;
6526         struct spoolss_SetPrinterInfo1 info1;
6527         struct spoolss_DevmodeContainer devmode_ctr;
6528         struct sec_desc_buf secdesc_ctr;
6529         struct spoolss_UserLevelCtr userlevel_ctr;
6530         struct policy_handle handle;
6531         bool found = false;
6532         struct dcerpc_binding_handle *b = p->binding_handle;
6533
6534         ZERO_STRUCT(devmode_ctr);
6535         ZERO_STRUCT(secdesc_ctr);
6536         ZERO_STRUCT(userlevel_ctr);
6537         ZERO_STRUCT(info1);
6538
6539         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6540                         ex ? "Ex":"", printername);
6541
6542         /* try to add printer to wellknown printer list (level 1) */
6543
6544         userlevel_ctr.level = 1;
6545
6546         info_ctr.info.info1 = &info1;
6547         info_ctr.level = 1;
6548
6549         rex.in.server = NULL;
6550         rex.in.info_ctr = &info_ctr;
6551         rex.in.devmode_ctr = &devmode_ctr;
6552         rex.in.secdesc_ctr = &secdesc_ctr;
6553         rex.in.userlevel_ctr = &userlevel_ctr;
6554         rex.out.handle = &handle;
6555
6556         r.in.server = NULL;
6557         r.in.info_ctr = &info_ctr;
6558         r.in.devmode_ctr = &devmode_ctr;
6559         r.in.secdesc_ctr = &secdesc_ctr;
6560         r.out.handle = &handle;
6561
6562         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6563                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6564                 "failed to add printer");
6565         result = ex ? rex.out.result : r.out.result;
6566         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6567                 "unexpected result code");
6568
6569         info1.name = printername;
6570         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6571
6572         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6573                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6574                 "failed to add printer");
6575         result = ex ? rex.out.result : r.out.result;
6576         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6577                 "unexpected result code");
6578
6579         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6580            better do a real check to see the printer is really there */
6581
6582         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6583                                                         PRINTER_ENUM_NETWORK, 1,
6584                                                         printername,
6585                                                         &found),
6586                         "failed to enum printers");
6587
6588         torture_assert(tctx, found, "failed to find newly added printer");
6589
6590         info1.flags = 0;
6591
6592         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6593                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6594                 "failed to add printer");
6595         result = ex ? rex.out.result : r.out.result;
6596         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6597                 "unexpected result code");
6598
6599         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6600            better do a real check to see the printer has really been removed
6601            from the well known printer list */
6602
6603         found = false;
6604
6605         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6606                                                         PRINTER_ENUM_NETWORK, 1,
6607                                                         printername,
6608                                                         &found),
6609                         "failed to enum printers");
6610 #if 0
6611         torture_assert(tctx, !found, "printer still in well known printer list");
6612 #endif
6613         return true;
6614 }
6615
6616 static bool test_AddPrinter_normal(struct torture_context *tctx,
6617                                    struct dcerpc_pipe *p,
6618                                    struct policy_handle *handle_p,
6619                                    const char *printername,
6620                                    const char *drivername,
6621                                    const char *portname,
6622                                    struct spoolss_DeviceMode *devmode,
6623                                    bool ex)
6624 {
6625         WERROR result;
6626         struct spoolss_AddPrinter r;
6627         struct spoolss_AddPrinterEx rex;
6628         struct spoolss_SetPrinterInfoCtr info_ctr;
6629         struct spoolss_SetPrinterInfo2 info2;
6630         struct spoolss_DevmodeContainer devmode_ctr;
6631         struct sec_desc_buf secdesc_ctr;
6632         struct spoolss_UserLevelCtr userlevel_ctr;
6633         struct policy_handle handle;
6634         bool found = false;
6635         bool existing_printer_deleted = false;
6636         struct dcerpc_binding_handle *b = p->binding_handle;
6637
6638         ZERO_STRUCT(devmode_ctr);
6639         ZERO_STRUCT(secdesc_ctr);
6640         ZERO_STRUCT(userlevel_ctr);
6641
6642         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6643                         ex ? "Ex":"", printername);
6644
6645         devmode_ctr.devmode = devmode;
6646
6647         userlevel_ctr.level = 1;
6648
6649         rex.in.server = NULL;
6650         rex.in.info_ctr = &info_ctr;
6651         rex.in.devmode_ctr = &devmode_ctr;
6652         rex.in.secdesc_ctr = &secdesc_ctr;
6653         rex.in.userlevel_ctr = &userlevel_ctr;
6654         rex.out.handle = &handle;
6655
6656         r.in.server = NULL;
6657         r.in.info_ctr = &info_ctr;
6658         r.in.devmode_ctr = &devmode_ctr;
6659         r.in.secdesc_ctr = &secdesc_ctr;
6660         r.out.handle = &handle;
6661
6662  again:
6663
6664         /* try to add printer to printer list (level 2) */
6665
6666         ZERO_STRUCT(info2);
6667
6668         info_ctr.info.info2 = &info2;
6669         info_ctr.level = 2;
6670
6671         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6672                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6673                 "failed to add printer");
6674         result = ex ? rex.out.result : r.out.result;
6675         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6676                 "unexpected result code");
6677
6678         info2.printername = printername;
6679
6680         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6681                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6682                 "failed to add printer");
6683         result = ex ? rex.out.result : r.out.result;
6684
6685         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6686                 struct policy_handle printer_handle;
6687
6688                 if (existing_printer_deleted) {
6689                         torture_fail(tctx, "already deleted printer still existing?");
6690                 }
6691
6692                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6693                         "failed to open printer handle");
6694
6695                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6696                         "failed to delete printer");
6697
6698                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6699                         "failed to close server handle");
6700
6701                 existing_printer_deleted = true;
6702
6703                 goto again;
6704         }
6705
6706         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6707                 "unexpected result code");
6708
6709         info2.portname = portname;
6710
6711         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6712                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6713                 "failed to add printer");
6714         result = ex ? rex.out.result : r.out.result;
6715         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6716                 "unexpected result code");
6717
6718         info2.drivername = drivername;
6719
6720         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6721                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6722                 "failed to add printer");
6723         result = ex ? rex.out.result : r.out.result;
6724
6725         /* w2k8r2 allows to add printer w/o defining printprocessor */
6726
6727         if (!W_ERROR_IS_OK(result)) {
6728                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6729                         "unexpected result code");
6730
6731                 info2.printprocessor = "winprint";
6732
6733                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6734                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6735                         "failed to add printer");
6736                 result = ex ? rex.out.result : r.out.result;
6737                 torture_assert_werr_ok(tctx, result,
6738                         "failed to add printer");
6739         }
6740
6741         *handle_p = handle;
6742
6743         /* we are paranoid, really check if the printer is there now */
6744
6745         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6746                                                         PRINTER_ENUM_LOCAL, 1,
6747                                                         printername,
6748                                                         &found),
6749                         "failed to enum printers");
6750         torture_assert(tctx, found, "failed to find newly added printer");
6751
6752         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6753                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6754                 "failed to add printer");
6755         result = ex ? rex.out.result : r.out.result;
6756         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6757                 "unexpected result code");
6758
6759         return true;
6760 }
6761
6762 static bool test_printer_info(struct torture_context *tctx,
6763                               void *private_data)
6764 {
6765         struct torture_printer_context *t =
6766                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6767         struct dcerpc_pipe *p = t->spoolss_pipe;
6768         struct dcerpc_binding_handle *b = p->binding_handle;
6769
6770         bool ret = true;
6771
6772         if (torture_setting_bool(tctx, "samba3", false)) {
6773                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6774         }
6775
6776         if (!test_PrinterInfo(tctx, b, &t->handle)) {
6777                 ret = false;
6778         }
6779
6780         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6781                 ret = false;
6782         }
6783
6784         return ret;
6785 }
6786
6787 static bool test_EnumPrinterKey(struct torture_context *tctx,
6788                                 struct dcerpc_binding_handle *b,
6789                                 struct policy_handle *handle,
6790                                 const char *key_name,
6791                                 const char ***array)
6792 {
6793         struct spoolss_EnumPrinterKey r;
6794         uint32_t needed = 0;
6795         union spoolss_KeyNames key_buffer;
6796         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6797         uint32_t _ndr_size;
6798         int i;
6799
6800         r.in.handle = handle;
6801         r.in.key_name = key_name;
6802         r.out.key_buffer = &key_buffer;
6803         r.out.needed = &needed;
6804         r.out._ndr_size = &_ndr_size;
6805
6806         for (i=0; i < ARRAY_SIZE(offered); i++) {
6807
6808                 if (offered[i] < 0 && needed) {
6809                         if (needed <= 4) {
6810                                 continue;
6811                         }
6812                         r.in.offered = needed + offered[i];
6813                 } else {
6814                         r.in.offered = offered[i];
6815                 }
6816
6817                 ZERO_STRUCT(key_buffer);
6818
6819                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6820
6821                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6822                         "failed to call EnumPrinterKey");
6823                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6824
6825                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6826                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6827                                         _ndr_size, r.in.offered/2));
6828
6829                         r.in.offered = needed;
6830                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6831                                 "failed to call EnumPrinterKey");
6832                 }
6833
6834                 if (offered[i] > 0) {
6835                         torture_assert_werr_ok(tctx, r.out.result,
6836                                 "failed to call EnumPrinterKey");
6837                 }
6838
6839                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6840                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6841                                 _ndr_size, r.in.offered/2));
6842
6843                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6844                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6845
6846                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6847                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6848
6849                 if (key_buffer.string_array) {
6850                         uint32_t calc_needed = 0;
6851                         int s;
6852                         for (s=0; key_buffer.string_array[s]; s++) {
6853                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6854                         }
6855                         if (!key_buffer.string_array[0]) {
6856                                 calc_needed += 2;
6857                         }
6858                         calc_needed += 2;
6859
6860                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6861                                 "EnumPrinterKey unexpected size");
6862                 }
6863         }
6864
6865         if (array) {
6866                 *array = key_buffer.string_array;
6867         }
6868
6869         return true;
6870 }
6871
6872 bool test_printer_all_keys(struct torture_context *tctx,
6873                            struct dcerpc_binding_handle *b,
6874                            struct policy_handle *handle)
6875 {
6876         const char **key_array = NULL;
6877         int i;
6878
6879         torture_comment(tctx, "Testing Printer Keys\n");
6880
6881         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6882                 "failed to call test_EnumPrinterKey");
6883
6884         for (i=0; key_array && key_array[i]; i++) {
6885                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6886                         "failed to call test_EnumPrinterKey");
6887         }
6888         for (i=0; key_array && key_array[i]; i++) {
6889                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6890                         "failed to call test_EnumPrinterDataEx");
6891         }
6892
6893         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6894
6895         return true;
6896 }
6897
6898 static bool test_csetprinter(struct torture_context *tctx,
6899                              void *private_data)
6900 {
6901         struct torture_printer_context *t =
6902                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6903         struct dcerpc_pipe *p = t->spoolss_pipe;
6904
6905         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
6906         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6907         const char *portname = t->info2.portname;
6908
6909         union spoolss_PrinterInfo info;
6910         struct policy_handle new_handle, new_handle2;
6911         struct dcerpc_binding_handle *b = p->binding_handle;
6912
6913         torture_comment(tctx, "Testing c_setprinter\n");
6914
6915         torture_assert(tctx,
6916                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6917                 "failed to get level 0 printer info");
6918         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6919                 info.info0.c_setprinter);
6920
6921         /* check if c_setprinter on 1st handle increases after a printer has
6922          * been added */
6923
6924         torture_assert(tctx,
6925                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6926                 "failed to add new printer");
6927         torture_assert(tctx,
6928                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6929                 "failed to get level 0 printer info");
6930         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6931                 info.info0.c_setprinter);
6932
6933         /* check if c_setprinter on new handle increases after a printer has
6934          * been added */
6935
6936         torture_assert(tctx,
6937                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6938                 "failed to get level 0 printer info");
6939         torture_comment(tctx, "csetprinter on created handle: %d\n",
6940                 info.info0.c_setprinter);
6941
6942         /* open the new printer and check if c_setprinter increases */
6943
6944         torture_assert(tctx,
6945                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6946                 "failed to open created printer");
6947         torture_assert(tctx,
6948                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6949                 "failed to get level 0 printer info");
6950         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6951                 info.info0.c_setprinter);
6952
6953         /* cleanup */
6954
6955         torture_assert(tctx,
6956                 test_ClosePrinter(tctx, b, &new_handle2),
6957                 "failed to close printer");
6958         torture_assert(tctx,
6959                 test_DeletePrinter(tctx, b, &new_handle),
6960                 "failed to delete new printer");
6961
6962         return true;
6963 }
6964
6965 static bool compose_local_driver_directory(struct torture_context *tctx,
6966                                            const char *environment,
6967                                            const char *local_dir,
6968                                            const char **path)
6969 {
6970         char *p;
6971
6972         p = strrchr(local_dir, '/');
6973         if (!p) {
6974                 return NULL;
6975         }
6976         p++;
6977
6978         if (strequal(environment, "Windows x64")) {
6979                 if (!strequal(p, "x64")) {
6980                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6981                 }
6982         } else if (strequal(environment, "Windows NT x86")) {
6983                 if (!strequal(p, "i386")) {
6984                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6985                 }
6986         } else {
6987                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6988         }
6989
6990         return true;
6991 }
6992
6993 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6994                                                      const char *devicename)
6995 {
6996         struct spoolss_DeviceMode *r;
6997
6998         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6999         if (r == NULL) {
7000                 return NULL;
7001         }
7002
7003         r->devicename           = talloc_strdup(r, devicename);
7004         r->specversion          = DMSPEC_NT4_AND_ABOVE;
7005         r->driverversion        = 0x0600;
7006         r->size                 = 0x00dc;
7007         r->__driverextra_length = 0;
7008         r->fields               = DEVMODE_FORMNAME |
7009                                   DEVMODE_TTOPTION |
7010                                   DEVMODE_PRINTQUALITY |
7011                                   DEVMODE_DEFAULTSOURCE |
7012                                   DEVMODE_COPIES |
7013                                   DEVMODE_SCALE |
7014                                   DEVMODE_PAPERSIZE |
7015                                   DEVMODE_ORIENTATION;
7016         r->orientation          = DMORIENT_PORTRAIT;
7017         r->papersize            = DMPAPER_LETTER;
7018         r->paperlength          = 0;
7019         r->paperwidth           = 0;
7020         r->scale                = 100;
7021         r->copies               = 55;
7022         r->defaultsource        = DMBIN_FORMSOURCE;
7023         r->printquality         = DMRES_HIGH;
7024         r->color                = DMRES_MONOCHROME;
7025         r->duplex               = DMDUP_SIMPLEX;
7026         r->yresolution          = 0;
7027         r->ttoption             = DMTT_SUBDEV;
7028         r->collate              = DMCOLLATE_FALSE;
7029         r->formname             = talloc_strdup(r, "Letter");
7030
7031         return r;
7032 }
7033
7034 static bool test_architecture_buffer(struct torture_context *tctx,
7035                                      void *private_data)
7036 {
7037         struct test_spoolss_context *ctx =
7038                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7039
7040         struct spoolss_OpenPrinterEx r;
7041         struct spoolss_UserLevel1 u1;
7042         struct policy_handle handle;
7043         uint32_t architectures[] = {
7044                 PROCESSOR_ARCHITECTURE_INTEL,
7045                 PROCESSOR_ARCHITECTURE_IA64,
7046                 PROCESSOR_ARCHITECTURE_AMD64
7047         };
7048         uint32_t needed[3];
7049         int i;
7050         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7051         struct dcerpc_binding_handle *b = p->binding_handle;
7052
7053         for (i=0; i < ARRAY_SIZE(architectures); i++) {
7054
7055                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7056
7057                 u1.size = 0;
7058                 u1.client = NULL;
7059                 u1.user = NULL;
7060                 u1.build = 0;
7061                 u1.major = 3;
7062                 u1.minor = 0;
7063                 u1.processor = architectures[i];
7064
7065                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7066                 r.in.datatype           = NULL;
7067                 r.in.devmode_ctr.devmode= NULL;
7068                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
7069                 r.in.level               = 1;
7070                 r.in.userlevel.level1   = &u1;
7071                 r.out.handle            = &handle;
7072
7073                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7074                 torture_assert_werr_ok(tctx, r.out.result, "");
7075
7076                 {
7077                         struct spoolss_EnumPrinters e;
7078                         uint32_t count;
7079                         union spoolss_PrinterInfo *info;
7080
7081                         e.in.flags = PRINTER_ENUM_LOCAL;
7082                         e.in.server = NULL;
7083                         e.in.level = 2;
7084                         e.in.buffer = NULL;
7085                         e.in.offered = 0;
7086                         e.out.count = &count;
7087                         e.out.info = &info;
7088                         e.out.needed = &needed[i];
7089
7090                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7091 #if 0
7092                         torture_comment(tctx, "needed was %d\n", needed[i]);
7093 #endif
7094                 }
7095
7096                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7097         }
7098
7099         for (i=1; i < ARRAY_SIZE(architectures); i++) {
7100                 if (needed[i-1] != needed[i]) {
7101                         torture_fail(tctx,
7102                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7103                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7104                 }
7105         }
7106
7107         return true;
7108 }
7109
7110 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7111                                           void *private_data)
7112 {
7113         struct test_spoolss_context *ctx =
7114                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7115         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7116         struct dcerpc_binding_handle *b = p->binding_handle;
7117
7118         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7119 }
7120
7121 static bool test_PrintServer_Forms(struct torture_context *tctx,
7122                                    void *private_data)
7123 {
7124         struct test_spoolss_context *ctx =
7125                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7126         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7127         struct dcerpc_binding_handle *b = p->binding_handle;
7128
7129         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7130 }
7131
7132 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7133                                        void *private_data)
7134 {
7135         struct test_spoolss_context *ctx =
7136                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7137         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7138         struct dcerpc_binding_handle *b = p->binding_handle;
7139
7140         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7141 }
7142
7143 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7144 {
7145         NTSTATUS status;
7146
7147         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7148
7149         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7150
7151         torture_assert(tctx,
7152                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7153                 "failed to open printserver");
7154         torture_assert(tctx,
7155                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7156                 "failed to get environment");
7157
7158         return true;
7159 }
7160
7161 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7162 {
7163         struct test_spoolss_context *t;
7164
7165         *data = t = talloc_zero(tctx, struct test_spoolss_context);
7166
7167         return torture_rpc_spoolss_setup_common(tctx, t);
7168 }
7169
7170 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7171 {
7172         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7173
7174         return true;
7175 }
7176
7177 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7178 {
7179         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7180         bool ret;
7181
7182         ret = torture_rpc_spoolss_teardown_common(tctx, t);
7183         talloc_free(t);
7184
7185         return ret;
7186 }
7187
7188 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7189 {
7190         struct dcerpc_pipe *p;
7191         struct dcerpc_binding_handle *b;
7192         const char *server_name_slash;
7193         const char *driver_name;
7194         const char *printer_name;
7195         const char *port_name;
7196
7197         torture_assert_ntstatus_ok(tctx,
7198                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7199                 "Error connecting to server");
7200
7201         p = t->spoolss_pipe;
7202         b = p->binding_handle;
7203         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7204
7205         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
7206         t->driver.info8.driver_name             = TORTURE_DRIVER;
7207         t->driver.info8.driver_path             = "pscript5.dll";
7208         t->driver.info8.data_file               = "cups6.ppd";
7209         t->driver.info8.config_file             = "ps5ui.dll";
7210         t->driver.info8.help_file               = "pscript.hlp";
7211         t->driver.info8.default_datatype        = "RAW";
7212         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
7213         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7214         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7215         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7216         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7217         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7218         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7219         t->driver.info8.dependent_files->string[5] = "cups6.ini";
7220         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7221         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7222
7223         t->driver.local.driver_directory= "/usr/share/cups/drivers";
7224
7225         t->info2.drivername             = "Microsoft XPS Document Writer";
7226         t->info2.portname               = "LPT1:";
7227
7228         printer_name = t->info2.printername;
7229         port_name = t->info2.portname;
7230
7231         torture_assert(tctx,
7232                 fillup_printserver_info(tctx, p, &t->driver),
7233                 "failed to fillup printserver info");
7234
7235         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7236
7237         torture_assert(tctx,
7238                 compose_local_driver_directory(tctx, t->driver.remote.environment,
7239                                                t->driver.local.driver_directory,
7240                                                &t->driver.local.driver_directory),
7241                 "failed to compose local driver directory");
7242
7243         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
7244                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7245                         t->info2.drivername, t->driver.remote.environment);
7246                 t->have_driver = true;
7247                 goto try_add;
7248         }
7249
7250         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7251                 t->info2.drivername, t->driver.remote.environment);
7252         torture_comment(tctx, "trying to upload own driver\n");
7253
7254         if (!directory_exist(t->driver.local.driver_directory)) {
7255                 torture_warning(tctx, "no local driver is available!");
7256                 t->have_driver = false;
7257                 goto try_add;
7258         }
7259
7260         torture_assert(tctx,
7261                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7262                 "failed to upload printer driver");
7263
7264         torture_assert(tctx,
7265                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
7266                 "failed to add driver");
7267
7268         t->added_driver = true;
7269         t->have_driver = true;
7270
7271  try_add:
7272         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7273
7274         if (t->wellknown) {
7275                 torture_assert(tctx,
7276                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7277                         "failed to add wellknown printer");
7278         } else {
7279                 torture_assert(tctx,
7280                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7281                         "failed to add printer");
7282         }
7283
7284         return true;
7285 }
7286
7287 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7288 {
7289         struct torture_printer_context *t;
7290
7291         *data = t = talloc_zero(tctx, struct torture_printer_context);
7292
7293         t->ex                   = false;
7294         t->wellknown            = false;
7295         t->info2.printername    = TORTURE_PRINTER;
7296         t->devmode              = NULL;
7297
7298         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7299 }
7300
7301 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7302 {
7303         struct torture_printer_context *t;
7304
7305         *data = t = talloc_zero(tctx, struct torture_printer_context);
7306
7307         t->ex                   = true;
7308         t->wellknown            = false;
7309         t->info2.printername    = TORTURE_PRINTER_EX;
7310         t->devmode              = NULL;
7311
7312         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7313 }
7314
7315 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7316 {
7317         struct torture_printer_context *t;
7318
7319         *data = t = talloc_zero(tctx, struct torture_printer_context);
7320
7321         t->ex                   = false;
7322         t->wellknown            = true;
7323         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
7324         t->devmode              = NULL;
7325
7326         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7327                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7328         }
7329
7330         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7331 }
7332
7333 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7334 {
7335         struct torture_printer_context *t;
7336
7337         *data = t = talloc_zero(tctx, struct torture_printer_context);
7338
7339         t->ex                   = true;
7340         t->wellknown            = true;
7341         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7342         t->devmode              = NULL;
7343
7344         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7345                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7346         }
7347
7348         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7349 }
7350
7351 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7352 {
7353         struct torture_printer_context *t;
7354
7355         *data = t = talloc_zero(tctx, struct torture_printer_context);
7356
7357         t->ex                   = true;
7358         t->wellknown            = false;
7359         t->info2.printername    = TORTURE_PRINTER_EX;
7360         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7361
7362         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7363 }
7364
7365 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7366 {
7367         bool found = false;
7368         struct dcerpc_pipe *p = t->spoolss_pipe;
7369         struct dcerpc_binding_handle *b;
7370         const char *printer_name = t->info2.printername;
7371
7372         if (t->added_driver) {
7373                 torture_assert(tctx,
7374                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7375                         "failed to remove printer driver");
7376         }
7377
7378         if (p) {
7379                 b = p->binding_handle;
7380         }
7381
7382         if (!t->wellknown) {
7383                 torture_assert(tctx,
7384                         test_DeletePrinter(tctx, b, &t->handle),
7385                         "failed to delete printer");
7386
7387                 torture_assert(tctx,
7388                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7389                                                    printer_name, &found),
7390                         "failed to enumerate printers");
7391
7392                 torture_assert(tctx, !found, "deleted printer still there");
7393         }
7394
7395         return true;
7396 }
7397
7398 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7399 {
7400         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7401         bool ret;
7402
7403         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7404         talloc_free(t);
7405
7406         return ret;
7407 }
7408
7409 static bool test_print_test(struct torture_context *tctx,
7410                             void *private_data)
7411 {
7412         struct torture_printer_context *t =
7413                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7414         struct dcerpc_pipe *p = t->spoolss_pipe;
7415         struct dcerpc_binding_handle *b = p->binding_handle;
7416
7417         torture_assert(tctx,
7418                 test_PausePrinter(tctx, b, &t->handle),
7419                 "failed to pause printer");
7420
7421         torture_assert(tctx,
7422                 test_DoPrintTest(tctx, b, &t->handle),
7423                 "failed to do print test");
7424
7425         torture_assert(tctx,
7426                 test_ResumePrinter(tctx, b, &t->handle),
7427                 "failed to resume printer");
7428
7429         return true;
7430 }
7431
7432 static bool test_print_test_extended(struct torture_context *tctx,
7433                                      void *private_data)
7434 {
7435         struct torture_printer_context *t =
7436                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7437         struct dcerpc_pipe *p = t->spoolss_pipe;
7438         struct dcerpc_binding_handle *b = p->binding_handle;
7439         bool ret = true;
7440
7441         torture_assert(tctx,
7442                 test_PausePrinter(tctx, b, &t->handle),
7443                 "failed to pause printer");
7444
7445         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7446         if (ret == false) {
7447                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7448                 if (torture_setting_bool(tctx, "samba3", false)) {
7449                         torture_comment(tctx, "non-critical for samba3\n");
7450                         ret = true;
7451                         tctx->last_result = TORTURE_SKIP;
7452                 }
7453         }
7454
7455         torture_assert(tctx,
7456                 test_ResumePrinter(tctx, b, &t->handle),
7457                 "failed to resume printer");
7458
7459         return ret;
7460 }
7461
7462 static bool test_printer_sd(struct torture_context *tctx,
7463                             void *private_data)
7464 {
7465         struct torture_printer_context *t =
7466                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7467         struct dcerpc_pipe *p = t->spoolss_pipe;
7468         struct dcerpc_binding_handle *b = p->binding_handle;
7469
7470         torture_assert(tctx,
7471                 test_PrinterInfo_SD(tctx, b, &t->handle),
7472                 "failed to test security descriptors");
7473
7474         return true;
7475 }
7476
7477 static bool test_printer_dm(struct torture_context *tctx,
7478                             void *private_data)
7479 {
7480         struct torture_printer_context *t =
7481                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7482         struct dcerpc_pipe *p = t->spoolss_pipe;
7483
7484         torture_assert(tctx,
7485                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7486                 "failed to test devicemodes");
7487
7488         return true;
7489 }
7490
7491 static bool test_printer_info_winreg(struct torture_context *tctx,
7492                                      void *private_data)
7493 {
7494         struct torture_printer_context *t =
7495                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7496         struct dcerpc_pipe *p = t->spoolss_pipe;
7497
7498         torture_assert(tctx,
7499                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7500                 "failed to test printer info winreg");
7501
7502         return true;
7503 }
7504
7505 static bool test_printer_change_id(struct torture_context *tctx,
7506                                    void *private_data)
7507 {
7508         struct torture_printer_context *t =
7509                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7510         struct dcerpc_pipe *p = t->spoolss_pipe;
7511
7512         torture_assert(tctx,
7513                 test_ChangeID(tctx, p, &t->handle),
7514                 "failed to test change id");
7515
7516         return true;
7517 }
7518
7519 static bool test_printer_keys(struct torture_context *tctx,
7520                               void *private_data)
7521 {
7522         struct torture_printer_context *t =
7523                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7524         struct dcerpc_pipe *p = t->spoolss_pipe;
7525         struct dcerpc_binding_handle *b = p->binding_handle;
7526
7527         torture_assert(tctx,
7528                 test_printer_all_keys(tctx, b, &t->handle),
7529                 "failed to test printer keys");
7530
7531         return true;
7532 }
7533
7534 static bool test_printer_data_consistency(struct torture_context *tctx,
7535                                           void *private_data)
7536 {
7537         struct torture_printer_context *t =
7538                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7539         struct dcerpc_pipe *p = t->spoolss_pipe;
7540
7541         torture_assert(tctx,
7542                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7543                 "failed to test printer data consistency");
7544
7545         return true;
7546 }
7547
7548 static bool test_printer_data_keys(struct torture_context *tctx,
7549                                    void *private_data)
7550 {
7551         struct torture_printer_context *t =
7552                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7553         struct dcerpc_pipe *p = t->spoolss_pipe;
7554
7555         torture_assert(tctx,
7556                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7557                 "failed to test printer data keys");
7558
7559         return true;
7560 }
7561
7562 static bool test_printer_data_values(struct torture_context *tctx,
7563                                      void *private_data)
7564 {
7565         struct torture_printer_context *t =
7566                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7567         struct dcerpc_pipe *p = t->spoolss_pipe;
7568
7569         torture_assert(tctx,
7570                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7571                 "failed to test printer data values");
7572
7573         return true;
7574 }
7575
7576 static bool test_printer_data_set(struct torture_context *tctx,
7577                                   void *private_data)
7578 {
7579         struct torture_printer_context *t =
7580                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7581         struct dcerpc_pipe *p = t->spoolss_pipe;
7582
7583         torture_assert(tctx,
7584                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7585                 "failed to test printer data set");
7586
7587         return true;
7588 }
7589
7590 static bool test_printer_data_winreg(struct torture_context *tctx,
7591                                      void *private_data)
7592 {
7593         struct torture_printer_context *t =
7594                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7595         struct dcerpc_pipe *p = t->spoolss_pipe;
7596
7597         torture_assert(tctx,
7598                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7599                 "failed to test printer data winreg");
7600
7601         return true;
7602 }
7603
7604 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7605                                         void *private_data)
7606 {
7607         struct torture_printer_context *t =
7608                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7609         struct dcerpc_pipe *p = t->spoolss_pipe;
7610
7611         torture_assert(tctx,
7612                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7613                 "failed to test printer data winreg dsspooler");
7614
7615         return true;
7616 }
7617
7618 static bool test_driver_info_winreg(struct torture_context *tctx,
7619                                     void *private_data)
7620 {
7621         struct torture_printer_context *t =
7622                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7623         struct dcerpc_pipe *p = t->spoolss_pipe;
7624         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7625
7626         if (!t->have_driver) {
7627                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7628         }
7629
7630         torture_assert(tctx,
7631                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7632                 "failed to test driver info winreg");
7633
7634         return true;
7635 }
7636
7637 void torture_tcase_printer(struct torture_tcase *tcase)
7638 {
7639         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7640         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7641         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7642         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7643         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7644         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7645         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7646         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7647         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7648         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7649         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7650         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7651         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7652         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7653         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7654         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7655         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7656 }
7657
7658 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7659 {
7660         struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
7661         struct torture_tcase *tcase;
7662
7663         tcase = torture_suite_add_tcase(suite, "addprinter");
7664
7665         torture_tcase_set_fixture(tcase,
7666                                   torture_rpc_spoolss_printer_setup,
7667                                   torture_rpc_spoolss_printer_teardown);
7668
7669         torture_tcase_printer(tcase);
7670
7671         tcase = torture_suite_add_tcase(suite, "addprinterex");
7672
7673         torture_tcase_set_fixture(tcase,
7674                                   torture_rpc_spoolss_printerex_setup,
7675                                   torture_rpc_spoolss_printer_teardown);
7676
7677         torture_tcase_printer(tcase);
7678
7679         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7680
7681         torture_tcase_set_fixture(tcase,
7682                                   torture_rpc_spoolss_printerwkn_setup,
7683                                   torture_rpc_spoolss_printer_teardown);
7684
7685         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7686
7687         torture_tcase_set_fixture(tcase,
7688                                   torture_rpc_spoolss_printerexwkn_setup,
7689                                   torture_rpc_spoolss_printer_teardown);
7690
7691 #if 0
7692         /* test is not correct */
7693         tcase = torture_suite_add_tcase(suite, "addprinterdm");
7694
7695         torture_tcase_set_fixture(tcase,
7696                                   torture_rpc_spoolss_printerdm_setup,
7697                                   torture_rpc_spoolss_printer_teardown);
7698
7699         torture_tcase_printer(tcase);
7700 #endif
7701         return suite;
7702 }
7703
7704 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7705 {
7706         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7707         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7708
7709         torture_tcase_set_fixture(tcase,
7710                                   torture_rpc_spoolss_setup,
7711                                   torture_rpc_spoolss_teardown);
7712
7713         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7714         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7715         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7716         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7717         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7718         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7719         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7720         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7721         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7722         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7723         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7724         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7725         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7726         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7727         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7728         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7729         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7730         torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7731         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7732         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7733
7734         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7735
7736         return suite;
7737 }
7738
7739 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7740                                                   struct dcerpc_binding_handle *b,
7741                                                   const char *server,
7742                                                   const char *environment,
7743                                                   const char **dir_p)
7744 {
7745         struct spoolss_GetPrinterDriverDirectory r;
7746         uint32_t needed;
7747
7748         r.in.server             = server;
7749         r.in.environment        = environment;
7750         r.in.level              = 1;
7751         r.in.buffer             = NULL;
7752         r.in.offered            = 0;
7753         r.out.needed            = &needed;
7754
7755         torture_assert_ntstatus_ok(tctx,
7756                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7757                 "failed to query driver directory");
7758
7759         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7760                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7761                 r.in.buffer = &blob;
7762                 r.in.offered = needed;
7763
7764                 torture_assert_ntstatus_ok(tctx,
7765                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7766                         "failed to query driver directory");
7767         }
7768
7769         torture_assert_werr_ok(tctx, r.out.result,
7770                 "failed to query driver directory");
7771
7772         if (dir_p) {
7773                 *dir_p = r.out.info->info1.directory_name;
7774         }
7775
7776         return true;
7777 }
7778
7779 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7780 {
7781         if (info_ctr == NULL) {
7782                 return NULL;
7783         }
7784
7785         switch (info_ctr->level) {
7786         case 1:
7787                 return info_ctr->info.info1->driver_name;
7788         case 2:
7789                 return info_ctr->info.info2->driver_name;
7790         case 3:
7791                 return info_ctr->info.info3->driver_name;
7792         case 4:
7793                 return info_ctr->info.info4->driver_name;
7794         case 6:
7795                 return info_ctr->info.info6->driver_name;
7796         case 8:
7797                 return info_ctr->info.info8->driver_name;
7798         default:
7799                 return NULL;
7800         }
7801 }
7802
7803 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7804 {
7805         if (info_ctr == NULL) {
7806                 return NULL;
7807         }
7808
7809         switch (info_ctr->level) {
7810         case 2:
7811                 return info_ctr->info.info2->architecture;
7812         case 3:
7813                 return info_ctr->info.info3->architecture;
7814         case 4:
7815                 return info_ctr->info.info4->architecture;
7816         case 6:
7817                 return info_ctr->info.info6->architecture;
7818         case 8:
7819                 return info_ctr->info.info8->architecture;
7820         default:
7821                 return NULL;
7822         }
7823 }
7824
7825
7826 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7827                                       struct dcerpc_binding_handle *b,
7828                                       const char *servername,
7829                                       struct spoolss_AddDriverInfoCtr *info_ctr,
7830                                       WERROR expected_result)
7831 {
7832         struct spoolss_AddPrinterDriver r;
7833         const char *drivername = get_driver_from_info(info_ctr);
7834         const char *environment = get_environment_from_info(info_ctr);
7835
7836         r.in.servername = servername;
7837         r.in.info_ctr = info_ctr;
7838
7839         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7840                 drivername, info_ctr->level, environment);
7841
7842         torture_assert_ntstatus_ok(tctx,
7843                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7844                 "spoolss_AddPrinterDriver failed");
7845         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7846                 "spoolss_AddPrinterDriver failed with unexpected result");
7847
7848         return true;
7849
7850 }
7851
7852 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7853                                         struct dcerpc_binding_handle *b,
7854                                         const char *servername,
7855                                         struct spoolss_AddDriverInfoCtr *info_ctr,
7856                                         uint32_t flags,
7857                                         WERROR expected_result)
7858 {
7859         struct spoolss_AddPrinterDriverEx r;
7860         const char *drivername = get_driver_from_info(info_ctr);
7861         const char *environment = get_environment_from_info(info_ctr);
7862
7863         r.in.servername = servername;
7864         r.in.info_ctr = info_ctr;
7865         r.in.flags = flags;
7866
7867         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7868                 drivername, info_ctr->level, environment);
7869
7870         torture_assert_ntstatus_ok(tctx,
7871                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7872                 "AddPrinterDriverEx failed");
7873         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7874                 "AddPrinterDriverEx failed with unexpected result");
7875
7876         return true;
7877 }
7878
7879 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7880                                                struct dcerpc_binding_handle *b,
7881                                                const char *server_name,
7882                                                struct spoolss_AddDriverInfo8 *r,
7883                                                uint32_t flags,
7884                                                bool ex)
7885 {
7886         struct spoolss_AddDriverInfoCtr info_ctr;
7887         struct spoolss_AddDriverInfo1 info1;
7888
7889         ZERO_STRUCT(info1);
7890
7891         info_ctr.level = 1;
7892         info_ctr.info.info1 = &info1;
7893
7894         if (ex) {
7895                 torture_assert(tctx,
7896                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7897                         "failed to test AddPrinterDriverEx level 1");
7898         } else {
7899                 torture_assert(tctx,
7900                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7901                         "failed to test AddPrinterDriver level 1");
7902         }
7903
7904         info1.driver_name = r->driver_name;
7905
7906         if (ex) {
7907                 torture_assert(tctx,
7908                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7909                         "failed to test AddPrinterDriverEx level 1");
7910         } else {
7911                 torture_assert(tctx,
7912                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7913                         "failed to test AddPrinterDriver level 1");
7914         }
7915
7916         return true;
7917 }
7918
7919 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7920                                                struct dcerpc_binding_handle *b,
7921                                                const char *server_name,
7922                                                struct spoolss_AddDriverInfo8 *r,
7923                                                uint32_t flags,
7924                                                bool ex)
7925 {
7926         struct spoolss_AddDriverInfoCtr info_ctr;
7927         struct spoolss_AddDriverInfo2 info2;
7928
7929         ZERO_STRUCT(info2);
7930
7931         info_ctr.level = 2;
7932         info_ctr.info.info2 = &info2;
7933
7934         if (ex) {
7935                 torture_assert(tctx,
7936                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7937                         "failed to test AddPrinterDriverEx level 2");
7938         } else {
7939                 torture_assert(tctx,
7940                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7941                         "failed to test AddPrinterDriver level 2");
7942         }
7943
7944         info2.driver_name = r->driver_name;
7945
7946         if (ex) {
7947                 torture_assert(tctx,
7948                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7949                         "failed to test AddPrinterDriverEx level 2");
7950         } else {
7951                 torture_assert(tctx,
7952                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7953                         "failed to test AddPrinterDriver level 2");
7954         }
7955
7956         info2.version = r->version;
7957
7958         if (ex) {
7959                 torture_assert(tctx,
7960                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7961                         "failed to test AddPrinterDriverEx level 2");
7962         } else {
7963                 torture_assert(tctx,
7964                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7965                         "failed to test AddPrinterDriver level 2");
7966         }
7967
7968         info2.architecture = r->architecture;
7969
7970         if (ex) {
7971                 torture_assert(tctx,
7972                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7973                         "failed to test AddPrinterDriverEx level 2");
7974         } else {
7975                 torture_assert(tctx,
7976                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7977                         "failed to test AddPrinterDriver level 2");
7978         }
7979
7980         info2.driver_path = r->driver_path;
7981
7982         if (ex) {
7983                 torture_assert(tctx,
7984                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7985                         "failed to test AddPrinterDriverEx level 2");
7986         } else {
7987                 torture_assert(tctx,
7988                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7989                         "failed to test AddPrinterDriver level 2");
7990         }
7991
7992         info2.data_file = r->data_file;
7993
7994         if (ex) {
7995                 torture_assert(tctx,
7996                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7997                         "failed to test AddPrinterDriverEx level 2");
7998         } else {
7999                 torture_assert(tctx,
8000                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8001                         "failed to test AddPrinterDriver level 2");
8002         }
8003
8004         info2.config_file = r->config_file;
8005
8006         if (ex) {
8007                 torture_assert(tctx,
8008                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8009                         "failed to test AddPrinterDriverEx");
8010         }
8011
8012         if (ex) {
8013                 torture_assert(tctx,
8014                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8015                         "failed to test AddPrinterDriverEx level 2");
8016         } else {
8017                 torture_assert(tctx,
8018                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8019                         "failed to test AddPrinterDriver level 2");
8020         }
8021
8022         torture_assert(tctx,
8023                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
8024                 "failed to find added printer driver");
8025
8026         return true;
8027 }
8028
8029 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8030                                                struct dcerpc_binding_handle *b,
8031                                                const char *server_name,
8032                                                struct spoolss_AddDriverInfo8 *r,
8033                                                uint32_t flags,
8034                                                bool ex)
8035 {
8036         struct spoolss_AddDriverInfoCtr info_ctr;
8037         struct spoolss_AddDriverInfo3 info3;
8038
8039         info3.driver_name       = r->driver_name;
8040         info3.version           = r->version;
8041         info3.architecture      = r->architecture;
8042         info3.driver_path       = r->driver_path;
8043         info3.data_file         = r->data_file;
8044         info3.config_file       = r->config_file;
8045         info3.help_file         = r->help_file;
8046         info3.monitor_name      = r->monitor_name;
8047         info3.default_datatype  = r->default_datatype;
8048         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8049         info3.dependent_files   = r->dependent_files;
8050
8051         info_ctr.level = 3;
8052         info_ctr.info.info3 = &info3;
8053
8054         if (ex) {
8055                 torture_assert(tctx,
8056                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8057                         "failed to test AddPrinterDriverEx level 3");
8058         } else {
8059                 torture_assert(tctx,
8060                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8061                         "failed to test AddPrinterDriver level 3");
8062         }
8063
8064         torture_assert(tctx,
8065                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
8066                 "failed to find added printer driver");
8067
8068         return true;
8069 }
8070
8071 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8072                                                struct dcerpc_binding_handle *b,
8073                                                const char *server_name,
8074                                                struct spoolss_AddDriverInfo8 *r,
8075                                                uint32_t flags,
8076                                                bool ex)
8077 {
8078         struct spoolss_AddDriverInfoCtr info_ctr;
8079         struct spoolss_AddDriverInfo4 info4;
8080
8081         info4.version           = r->version;
8082         info4.driver_name       = r->driver_name;
8083         info4.architecture      = r->architecture;
8084         info4.driver_path       = r->driver_path;
8085         info4.data_file         = r->data_file;
8086         info4.config_file       = r->config_file;
8087         info4.help_file         = r->help_file;
8088         info4.monitor_name      = r->monitor_name;
8089         info4.default_datatype  = r->default_datatype;
8090         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8091         info4.dependent_files   = r->dependent_files;
8092         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8093         info4.previous_names = r->previous_names;
8094
8095         info_ctr.level = 4;
8096         info_ctr.info.info4 = &info4;
8097
8098         if (ex) {
8099                 torture_assert(tctx,
8100                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8101                         "failed to test AddPrinterDriverEx level 4");
8102         } else {
8103                 torture_assert(tctx,
8104                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8105                         "failed to test AddPrinterDriver level 4");
8106         }
8107
8108         torture_assert(tctx,
8109                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
8110                 "failed to find added printer driver");
8111
8112         return true;
8113 }
8114
8115 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8116                                                struct dcerpc_binding_handle *b,
8117                                                const char *server_name,
8118                                                struct spoolss_AddDriverInfo8 *r,
8119                                                uint32_t flags,
8120                                                bool ex)
8121 {
8122         struct spoolss_AddDriverInfoCtr info_ctr;
8123         struct spoolss_AddDriverInfo6 info6;
8124
8125         info6.version           = r->version;
8126         info6.driver_name       = r->driver_name;
8127         info6.architecture      = r->architecture;
8128         info6.driver_path       = r->driver_path;
8129         info6.data_file         = r->data_file;
8130         info6.config_file       = r->config_file;
8131         info6.help_file         = r->help_file;
8132         info6.monitor_name      = r->monitor_name;
8133         info6.default_datatype  = r->default_datatype;
8134         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8135         info6.dependent_files   = r->dependent_files;
8136         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8137         info6.previous_names    = r->previous_names;
8138         info6.driver_date       = r->driver_date;
8139         info6.driver_version    = r->driver_version;
8140         info6.manufacturer_name = r->manufacturer_name;
8141         info6.manufacturer_url  = r->manufacturer_url;
8142         info6.hardware_id       = r->hardware_id;
8143         info6.provider          = r->provider;
8144
8145         info_ctr.level = 6;
8146         info_ctr.info.info6 = &info6;
8147
8148         if (ex) {
8149                 torture_assert(tctx,
8150                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8151                         "failed to test AddPrinterDriverEx level 6");
8152         } else {
8153                 torture_assert(tctx,
8154                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8155                         "failed to test AddPrinterDriver level 6");
8156         }
8157
8158         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8159
8160         if (!ex) {
8161                 return true;
8162         }
8163
8164         torture_assert(tctx,
8165                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
8166                 "failed to find added printer driver");
8167
8168         return true;
8169 }
8170
8171 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8172                                                struct dcerpc_binding_handle *b,
8173                                                const char *server_name,
8174                                                struct spoolss_AddDriverInfo8 *r,
8175                                                uint32_t flags,
8176                                                bool ex)
8177 {
8178         struct spoolss_AddDriverInfoCtr info_ctr;
8179
8180         info_ctr.level = 8;
8181         info_ctr.info.info8 = r;
8182
8183         if (ex) {
8184                 torture_assert(tctx,
8185                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8186                         "failed to test AddPrinterDriverEx level 8");
8187         } else {
8188                 torture_assert(tctx,
8189                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8190                         "failed to test AddPrinterDriver level 8");
8191         }
8192
8193         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8194
8195         if (!ex) {
8196                 return true;
8197         }
8198
8199         torture_assert(tctx,
8200                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
8201                 "failed to find added printer driver");
8202
8203         return true;
8204 }
8205
8206 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8207                                          struct dcerpc_binding_handle *b,
8208                                          const char *server,
8209                                          const char *driver,
8210                                          const char *environment,
8211                                          WERROR expected_result)
8212 {
8213         struct spoolss_DeletePrinterDriver r;
8214
8215         r.in.server = server;
8216         r.in.architecture = environment;
8217         r.in.driver = driver;
8218
8219         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8220
8221         torture_assert_ntstatus_ok(tctx,
8222                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8223                 "DeletePrinterDriver failed");
8224         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8225                 "DeletePrinterDriver failed with unexpected result");
8226
8227         return true;
8228 }
8229
8230 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8231                                            struct dcerpc_binding_handle *b,
8232                                            const char *server,
8233                                            const char *driver,
8234                                            const char *environment,
8235                                            uint32_t delete_flags,
8236                                            uint32_t version,
8237                                            WERROR expected_result)
8238 {
8239         struct spoolss_DeletePrinterDriverEx r;
8240
8241         r.in.server = server;
8242         r.in.architecture = environment;
8243         r.in.driver = driver;
8244         r.in.delete_flags = delete_flags;
8245         r.in.version = version;
8246
8247         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8248
8249         torture_assert_ntstatus_ok(tctx,
8250                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8251                 "DeletePrinterDriverEx failed");
8252         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8253                 "DeletePrinterDriverEx failed with unexpected result");
8254
8255         return true;
8256 }
8257
8258 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8259                                      struct dcerpc_binding_handle *b,
8260                                      const char *server_name,
8261                                      const char *driver,
8262                                      const char *environment)
8263 {
8264         torture_assert(tctx,
8265                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8266                 "failed to delete driver");
8267
8268         torture_assert(tctx,
8269                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8270                 "failed to delete driver");
8271
8272         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8273                 torture_fail(tctx, "deleted driver still enumerated");
8274         }
8275
8276         torture_assert(tctx,
8277                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8278                 "2nd delete failed");
8279
8280         return true;
8281 }
8282
8283 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8284                                        struct dcerpc_binding_handle *b,
8285                                        const char *server_name,
8286                                        const char *driver,
8287                                        const char *environment,
8288                                        uint32_t delete_flags,
8289                                        uint32_t version)
8290 {
8291         torture_assert(tctx,
8292                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8293                 "failed to delete driver");
8294
8295         torture_assert(tctx,
8296                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8297                 "failed to delete driver");
8298
8299         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8300                 torture_fail(tctx, "deleted driver still enumerated");
8301         }
8302
8303         torture_assert(tctx,
8304                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8305                 "2nd delete failed");
8306
8307         return true;
8308 }
8309
8310 static bool test_PrinterDriver_args(struct torture_context *tctx,
8311                                     struct dcerpc_binding_handle *b,
8312                                     const char *server_name,
8313                                     uint32_t level,
8314                                     struct spoolss_AddDriverInfo8 *r,
8315                                     uint32_t add_flags,
8316                                     uint32_t delete_flags,
8317                                     uint32_t delete_version,
8318                                     bool ex)
8319 {
8320         bool ret = true;
8321
8322         switch (level) {
8323         case 1:
8324                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
8325                 break;
8326         case 2:
8327                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
8328                 break;
8329         case 3:
8330                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
8331                 break;
8332         case 4:
8333                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
8334                 break;
8335         case 6:
8336                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
8337                 break;
8338         case 8:
8339                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
8340                 break;
8341         default:
8342                 return false;
8343         }
8344
8345         if (ret == false) {
8346                 return ret;
8347         }
8348
8349         if (level == 1) {
8350                 return ret;
8351         }
8352
8353         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8354
8355         if (!ex && (level == 6 || level == 8)) {
8356                 return ret;
8357         }
8358
8359         if (ex) {
8360                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8361         } else {
8362                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8363         }
8364 }
8365
8366 static bool fillup_printserver_info(struct torture_context *tctx,
8367                                     struct dcerpc_pipe *p,
8368                                     struct torture_driver_context *d)
8369 {
8370         struct policy_handle server_handle;
8371         struct dcerpc_binding_handle *b = p->binding_handle;
8372         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8373
8374         torture_assert(tctx,
8375                 test_OpenPrinter_server(tctx, p, &server_handle),
8376                 "failed to open printserver");
8377         torture_assert(tctx,
8378                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8379                 "failed to get environment");
8380         torture_assert(tctx,
8381                 test_ClosePrinter(tctx, b, &server_handle),
8382                 "failed to close printserver");
8383
8384         torture_assert(tctx,
8385                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8386                         d->local.environment ? d->local.environment : d->remote.environment,
8387                         &d->remote.driver_directory),
8388                 "failed to get driver directory");
8389
8390         return true;
8391 }
8392
8393 static const char *driver_directory_dir(const char *driver_directory)
8394 {
8395         char *p;
8396
8397         p = strrchr(driver_directory, '\\');
8398         if (p) {
8399                 return p+1;
8400         }
8401
8402         return NULL;
8403 }
8404
8405 static const char *driver_directory_share(struct torture_context *tctx,
8406                                           const char *driver_directory)
8407 {
8408         const char *p;
8409         char *tok;
8410
8411         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8412                 driver_directory += 2;
8413         }
8414
8415         p = talloc_strdup(tctx, driver_directory);
8416
8417         torture_assert(tctx,
8418                 next_token_talloc(tctx, &p, &tok, "\\"),
8419                 "cannot explode uri");
8420         torture_assert(tctx,
8421                 next_token_talloc(tctx, &p, &tok, "\\"),
8422                 "cannot explode uri");
8423
8424         return tok;
8425 }
8426
8427 static bool upload_printer_driver_file(struct torture_context *tctx,
8428                                        struct smbcli_state *cli,
8429                                        struct torture_driver_context *d,
8430                                        const char *file_name)
8431 {
8432         XFILE *f;
8433         int fnum;
8434         uint8_t *buf;
8435         int maxwrite = 64512;
8436         off_t nread = 0;
8437         size_t start = 0;
8438         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8439         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8440         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8441
8442         if (!file_name) {
8443                 return true;
8444         }
8445
8446         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8447
8448         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8449         if (fnum == -1) {
8450                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8451         }
8452
8453         f = x_fopen(local_name, O_RDONLY, 0);
8454         if (f == NULL) {
8455                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8456         }
8457
8458         buf = talloc_array(tctx, uint8_t, maxwrite);
8459         if (!buf) {
8460                 return false;
8461         }
8462
8463         while (!x_feof(f)) {
8464                 int n = maxwrite;
8465                 int ret;
8466
8467                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8468                         if((n == 0) && x_feof(f))
8469                                 break; /* Empty local file. */
8470
8471                         torture_warning(tctx,
8472                                 "failed to read file: %s\n", strerror(errno));
8473                         break;
8474                 }
8475
8476                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8477
8478                 if (n != ret) {
8479                         torture_warning(tctx,
8480                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8481                         break;
8482                 }
8483
8484                 nread += n;
8485         }
8486
8487         x_fclose(f);
8488
8489         torture_assert_ntstatus_ok(tctx,
8490                 smbcli_close(cli->tree, fnum),
8491                 "failed to close file");
8492
8493         return true;
8494 }
8495
8496 static bool connect_printer_driver_share(struct torture_context *tctx,
8497                                          const char *server_name,
8498                                          const char *share_name,
8499                                          struct smbcli_state **cli)
8500 {
8501         struct smbcli_options smb_options;
8502         struct smbcli_session_options smb_session_options;
8503
8504         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8505                 share_name, server_name);
8506
8507         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8508         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8509
8510         torture_assert_ntstatus_ok(tctx,
8511                 smbcli_full_connection(tctx, cli, server_name,
8512                                         lpcfg_smb_ports(tctx->lp_ctx),
8513                                         share_name, NULL,
8514                                         lpcfg_socket_options(tctx->lp_ctx),
8515                                         cmdline_credentials,
8516                                         lpcfg_resolve_context(tctx->lp_ctx),
8517                                         tctx->ev,
8518                                         &smb_options,
8519                                         &smb_session_options,
8520                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8521                 "failed to open driver share");
8522
8523         return true;
8524 }
8525
8526 static bool upload_printer_driver(struct torture_context *tctx,
8527                                   const char *server_name,
8528                                   struct torture_driver_context *d)
8529 {
8530         struct smbcli_state *cli;
8531         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8532         int i;
8533
8534         torture_assert(tctx,
8535                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8536                 "failed to connect to driver share");
8537
8538         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8539                 server_name, share_name);
8540
8541         torture_assert(tctx,
8542                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8543                 "failed to upload driver_path");
8544         torture_assert(tctx,
8545                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8546                 "failed to upload data_file");
8547         torture_assert(tctx,
8548                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8549                 "failed to upload config_file");
8550         torture_assert(tctx,
8551                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8552                 "failed to upload help_file");
8553         if (d->info8.dependent_files) {
8554                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8555                         torture_assert(tctx,
8556                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8557                                 "failed to upload dependent_files");
8558                 }
8559         }
8560
8561         talloc_free(cli);
8562
8563         return true;
8564 }
8565
8566 static bool remove_printer_driver_file(struct torture_context *tctx,
8567                                        struct smbcli_state *cli,
8568                                        struct torture_driver_context *d,
8569                                        const char *file_name)
8570 {
8571         const char *remote_name;
8572         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
8573
8574         if (!file_name) {
8575                 return true;
8576         }
8577
8578         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8579
8580         torture_comment(tctx, "Removing %s\n", remote_name);
8581
8582         torture_assert_ntstatus_ok(tctx,
8583                 smbcli_unlink(cli->tree, remote_name),
8584                 "failed to unlink");
8585
8586         return true;
8587 }
8588
8589 static bool remove_printer_driver(struct torture_context *tctx,
8590                                   const char *server_name,
8591                                   struct torture_driver_context *d)
8592 {
8593         struct smbcli_state *cli;
8594         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8595         int i;
8596
8597         torture_assert(tctx,
8598                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8599                 "failed to connect to driver share");
8600
8601         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8602                 server_name, share_name);
8603
8604         torture_assert(tctx,
8605                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8606                 "failed to remove driver_path");
8607         torture_assert(tctx,
8608                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8609                 "failed to remove data_file");
8610         torture_assert(tctx,
8611                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8612                 "failed to remove config_file");
8613         torture_assert(tctx,
8614                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8615                 "failed to remove help_file");
8616         if (d->info8.dependent_files) {
8617                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8618                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8619                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8620                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8621                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8622                                 continue;
8623                         }
8624                         torture_assert(tctx,
8625                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8626                                 "failed to remove dependent_files");
8627                 }
8628         }
8629
8630         talloc_free(cli);
8631
8632         return true;
8633
8634 }
8635
8636 static bool test_add_driver_arg(struct torture_context *tctx,
8637                                 struct dcerpc_pipe *p,
8638                                 struct torture_driver_context *d)
8639 {
8640         bool ret = true;
8641         struct dcerpc_binding_handle *b = p->binding_handle;
8642         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8643         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8644         int i;
8645         struct spoolss_AddDriverInfo8 info8;
8646         uint32_t add_flags = APD_COPY_NEW_FILES;
8647         uint32_t delete_flags = 0;
8648
8649         ZERO_STRUCT(info8);
8650
8651         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8652                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8653
8654         torture_assert(tctx,
8655                 fillup_printserver_info(tctx, p, d),
8656                 "failed to fillup printserver info");
8657
8658         if (!directory_exist(d->local.driver_directory)) {
8659                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8660         }
8661
8662         torture_assert(tctx,
8663                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8664                 "failed to upload printer driver");
8665
8666         info8.version           = d->info8.version;
8667         info8.driver_name       = d->info8.driver_name;
8668         info8.architecture      = d->local.environment;
8669         info8.driver_path       = d->info8.driver_path;
8670         info8.data_file         = d->info8.data_file;
8671         info8.config_file       = d->info8.config_file;
8672
8673         for (i=0; i < ARRAY_SIZE(levels); i++) {
8674
8675                 if (torture_setting_bool(tctx, "samba3", false)) {
8676                         switch (levels[i]) {
8677                         case 2:
8678                         case 4:
8679                         case 8:
8680                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8681                                 continue;
8682                         default:
8683                                 break;
8684                         }
8685                 }
8686
8687                 torture_comment(tctx,
8688                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
8689                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8690
8691                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8692         }
8693
8694         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8695         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8696         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8697
8698         for (i=0; i < ARRAY_SIZE(levels); i++) {
8699
8700                 if (torture_setting_bool(tctx, "samba3", false)) {
8701                         switch (levels[i]) {
8702                         case 2:
8703                         case 4:
8704                         case 8:
8705                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8706                                 continue;
8707                         default:
8708                                 break;
8709                         }
8710                 }
8711
8712
8713                 torture_comment(tctx,
8714                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8715                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8716
8717                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8718         }
8719
8720         torture_assert(tctx,
8721                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8722                 "failed to remove printer driver");
8723
8724         torture_comment(tctx, "\n");
8725
8726         return ret;
8727 }
8728
8729 static bool test_add_driver_ex_64(struct torture_context *tctx,
8730                                   struct dcerpc_pipe *p,
8731                                   void *private_data)
8732 {
8733         struct torture_driver_context *d =
8734                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8735
8736         d->local.environment            = talloc_strdup(d, "Windows x64");
8737         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8738         d->info8.driver_name            = TORTURE_DRIVER_EX;
8739         d->ex                           = true;
8740
8741         return test_add_driver_arg(tctx, p, d);
8742 }
8743
8744 static bool test_add_driver_ex_32(struct torture_context *tctx,
8745                                   struct dcerpc_pipe *p,
8746                                   void *private_data)
8747 {
8748         struct torture_driver_context *d =
8749                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8750
8751         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8752         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8753         d->info8.driver_name            = TORTURE_DRIVER_EX;
8754         d->ex                           = true;
8755
8756         return test_add_driver_arg(tctx, p, d);
8757 }
8758
8759 static bool test_add_driver_64(struct torture_context *tctx,
8760                                struct dcerpc_pipe *p,
8761                                void *private_data)
8762 {
8763         struct torture_driver_context *d =
8764                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8765
8766         d->local.environment            = talloc_strdup(d, "Windows x64");
8767         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8768         d->info8.driver_name            = TORTURE_DRIVER;
8769         d->ex                           = false;
8770
8771         return test_add_driver_arg(tctx, p, d);
8772 }
8773
8774 static bool test_add_driver_32(struct torture_context *tctx,
8775                                struct dcerpc_pipe *p,
8776                                void *private_data)
8777 {
8778         struct torture_driver_context *d =
8779                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8780
8781         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8782         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8783         d->info8.driver_name            = TORTURE_DRIVER;
8784         d->ex                           = false;
8785
8786         return test_add_driver_arg(tctx, p, d);
8787 }
8788
8789 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8790 {
8791         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8792
8793         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8794                                                         "driver", &ndr_table_spoolss);
8795         struct torture_driver_context *t;
8796
8797         t = talloc_zero(mem_ctx, struct torture_driver_context);
8798
8799         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
8800         t->info8.driver_name    = NULL;
8801         t->info8.architecture   = NULL;
8802         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
8803         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
8804         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
8805
8806         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8807         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8808
8809         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8810         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8811
8812         return suite;
8813 }