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