a44b7323d41ad8f4c3d54d88ac3ce01e08a18971
[metze/samba/wip.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                                WERROR werr_expected,
3259                                uint32_t *count_p,
3260                                union spoolss_JobInfo **info_p)
3261 {
3262         NTSTATUS status;
3263         struct spoolss_EnumJobs r;
3264         uint32_t needed;
3265         uint32_t count;
3266         union spoolss_JobInfo *info;
3267
3268         r.in.handle = handle;
3269         r.in.firstjob = 0;
3270         r.in.numjobs = 0xffffffff;
3271         r.in.level = level;
3272         r.in.buffer = NULL;
3273         r.in.offered = 0;
3274         r.out.needed = &needed;
3275         r.out.count = &count;
3276         r.out.info = &info;
3277
3278         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3279
3280         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3281
3282         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3283
3284         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3285                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3286                 r.in.buffer = &blob;
3287                 r.in.offered = needed;
3288
3289                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3290
3291                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3292                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3293                                           "EnumJobs failed");
3294                 torture_assert(tctx, info, "No jobs returned");
3295
3296                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3297
3298         } else {
3299                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3300                                           "EnumJobs failed");
3301         }
3302
3303         if (count_p) {
3304                 *count_p = count;
3305         }
3306         if (info_p) {
3307                 *info_p = info;
3308         }
3309
3310         return true;
3311 }
3312
3313 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3314                                    struct dcerpc_binding_handle *b,
3315                                    struct policy_handle *handle,
3316                                    uint32_t job_id)
3317 {
3318         struct spoolss_RpcEnumJobNamedProperties r;
3319         uint32_t pcProperties = 0;
3320         struct RPC_PrintNamedProperty *ppProperties = NULL;
3321
3322         r.in.hPrinter = handle;
3323         r.in.JobId = job_id;
3324         r.out.pcProperties = &pcProperties;
3325         r.out.ppProperties = &ppProperties;
3326
3327         torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3328
3329         torture_assert_ntstatus_ok(tctx,
3330                 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3331                 "spoolss_RpcEnumJobNamedProperties failed");
3332         torture_assert_werr_ok(tctx, r.out.result,
3333                 "spoolss_RpcEnumJobNamedProperties failed");
3334
3335         return true;
3336 }
3337
3338 static bool test_JobPropertySet(struct torture_context *tctx,
3339                                 struct dcerpc_binding_handle *b,
3340                                 struct policy_handle *handle,
3341                                 uint32_t job_id,
3342                                 struct RPC_PrintNamedProperty *property)
3343 {
3344         struct spoolss_RpcSetJobNamedProperty r;
3345
3346         r.in.hPrinter = handle;
3347         r.in.JobId = job_id;
3348         r.in.pProperty = property;
3349
3350         torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3351                 job_id, property->propertyName,
3352                 property->propertyValue.ePropertyType);
3353
3354         torture_assert_ntstatus_ok(tctx,
3355                 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3356                 "spoolss_RpcSetJobNamedProperty failed");
3357         torture_assert_werr_ok(tctx, r.out.result,
3358                 "spoolss_RpcSetJobNamedProperty failed");
3359
3360         return true;
3361 }
3362
3363 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3364                                      struct dcerpc_binding_handle *b,
3365                                      struct policy_handle *handle,
3366                                      uint32_t job_id,
3367                                      const char *property_name,
3368                                      struct RPC_PrintPropertyValue *value)
3369 {
3370         struct spoolss_RpcGetJobNamedPropertyValue r;
3371
3372         r.in.hPrinter = handle;
3373         r.in.JobId = job_id;
3374         r.in.pszName = property_name;
3375         r.out.pValue = value;
3376
3377         torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3378                 job_id, property_name);
3379
3380         torture_assert_ntstatus_ok(tctx,
3381                 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3382                 "spoolss_RpcGetJobNamedPropertyValue failed");
3383         torture_assert_werr_ok(tctx, r.out.result,
3384                 "spoolss_RpcGetJobNamedPropertyValue failed");
3385
3386         return true;
3387 }
3388
3389 static bool test_JobPropertyDelete(struct torture_context *tctx,
3390                                    struct dcerpc_binding_handle *b,
3391                                    struct policy_handle *handle,
3392                                    uint32_t job_id,
3393                                    const char *property_name)
3394 {
3395         struct spoolss_RpcDeleteJobNamedProperty r;
3396
3397         r.in.hPrinter = handle;
3398         r.in.JobId = job_id;
3399         r.in.pszName = property_name;
3400
3401         torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3402                 job_id, property_name);
3403
3404         torture_assert_ntstatus_ok(tctx,
3405                 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3406                 "spoolss_RpcDeleteJobNamedProperty failed");
3407         torture_assert_werr_ok(tctx, r.out.result,
3408                 "spoolss_RpcDeleteJobNamedProperty failed");
3409
3410         return true;
3411 }
3412
3413 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3414                                          struct dcerpc_binding_handle *b,
3415                                          struct policy_handle *handle,
3416                                          const char *document_name,
3417                                          const char *datatype,
3418                                          uint32_t *job_id)
3419 {
3420         NTSTATUS status;
3421         struct spoolss_StartDocPrinter s;
3422         struct spoolss_DocumentInfoCtr info_ctr;
3423         struct spoolss_DocumentInfo1 info1;
3424         struct spoolss_StartPagePrinter sp;
3425         struct spoolss_WritePrinter w;
3426         struct spoolss_EndPagePrinter ep;
3427         struct spoolss_EndDocPrinter e;
3428         int i;
3429         uint32_t num_written;
3430
3431         torture_comment(tctx, "Testing StartDocPrinter\n");
3432
3433         s.in.handle             = handle;
3434         s.in.info_ctr           = &info_ctr;
3435         s.out.job_id            = job_id;
3436
3437         info1.document_name     = document_name;
3438         info1.output_file       = NULL;
3439         info1.datatype          = datatype;
3440
3441         info_ctr.level          = 1;
3442         info_ctr.info.info1     = &info1;
3443
3444         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3445         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3446         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3447
3448         for (i=1; i < 4; i++) {
3449                 union spoolss_JobInfo ginfo;
3450                 bool ok;
3451
3452                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3453
3454                 sp.in.handle            = handle;
3455
3456                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3457                 torture_assert_ntstatus_ok(tctx, status,
3458                                            "dcerpc_spoolss_StartPagePrinter failed");
3459                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3460
3461                 ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
3462                 if (!ok) {
3463                         torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
3464                 }
3465
3466                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3467
3468                 w.in.handle             = handle;
3469                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3470                 w.out.num_written       = &num_written;
3471
3472                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3473                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3474                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3475
3476                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3477
3478                 ep.in.handle            = handle;
3479
3480                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3481                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3482                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3483         }
3484
3485         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3486
3487         e.in.handle = handle;
3488
3489         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3490         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3491         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3492
3493         return true;
3494 }
3495
3496 static bool test_DoPrintTest_add_one_job(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, "RAW", job_id);
3503
3504         return true;
3505 }
3506
3507 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3508                                          struct dcerpc_binding_handle *b,
3509                                          struct policy_handle *handle,
3510                                          const char *document_name,
3511                                          uint32_t *job_id)
3512 {
3513         test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3514
3515         return true;
3516 }
3517
3518
3519 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3520                                         struct dcerpc_binding_handle *b,
3521                                         struct policy_handle *handle,
3522                                         uint32_t num_jobs,
3523                                         uint32_t *job_ids)
3524 {
3525         uint32_t count;
3526         union spoolss_JobInfo *info = NULL;
3527         int i;
3528
3529         torture_assert(tctx,
3530                 test_AddJob(tctx, b, handle),
3531                 "AddJob failed");
3532
3533         torture_assert(tctx,
3534                 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
3535                 "EnumJobs level 1 failed");
3536
3537         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3538
3539         for (i=0; i < num_jobs; i++) {
3540                 union spoolss_JobInfo ginfo;
3541                 const char *document_name;
3542                 const char *new_document_name = "any_other_docname";
3543                 struct spoolss_JobInfoContainer ctr;
3544                 struct spoolss_SetJobInfo1 info1;
3545
3546                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3547
3548                 torture_assert(tctx,
3549                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3550                         "failed to call test_GetJob");
3551
3552                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3553
3554                 document_name = ginfo.info1.document_name;
3555
3556                 info1.job_id            = ginfo.info1.job_id;
3557                 info1.printer_name      = ginfo.info1.printer_name;
3558                 info1.server_name       = ginfo.info1.server_name;
3559                 info1.user_name         = ginfo.info1.user_name;
3560                 info1.document_name     = new_document_name;
3561                 info1.data_type         = ginfo.info1.data_type;
3562                 info1.text_status       = ginfo.info1.text_status;
3563                 info1.status            = ginfo.info1.status;
3564                 info1.priority          = ginfo.info1.priority;
3565                 info1.position          = ginfo.info1.position;
3566                 info1.total_pages       = ginfo.info1.total_pages;
3567                 info1.pages_printed     = ginfo.info1.pages_printed;
3568                 info1.submitted         = ginfo.info1.submitted;
3569
3570                 ctr.level = 1;
3571                 ctr.info.info1 = &info1;
3572
3573                 torture_assert(tctx,
3574                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3575                         "failed to call test_SetJob level 1");
3576
3577                 torture_assert(tctx,
3578                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3579                         "failed to call test_GetJob");
3580
3581                 if (strequal(ginfo.info1.document_name, document_name)) {
3582                         torture_warning(tctx,
3583                                         "document_name did *NOT* change from '%s' to '%s'\n",
3584                                         document_name, new_document_name);
3585                 }
3586         }
3587
3588         for (i=0; i < num_jobs; i++) {
3589                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3590                         torture_warning(tctx, "failed to pause printjob\n");
3591                 }
3592                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3593                         torture_warning(tctx, "failed to resume printjob\n");
3594                 }
3595         }
3596
3597         return true;
3598 }
3599
3600 static bool test_DoPrintTest(struct torture_context *tctx,
3601                              struct dcerpc_binding_handle *b,
3602                              struct policy_handle *handle)
3603 {
3604         bool ret = true;
3605         uint32_t num_jobs = 8;
3606         uint32_t *job_ids;
3607         int i;
3608
3609         torture_comment(tctx, "Testing real print operations\n");
3610
3611         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3612
3613         for (i=0; i < num_jobs; i++) {
3614                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3615         }
3616
3617         for (i=0; i < num_jobs; i++) {
3618                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3619         }
3620
3621         for (i=0; i < num_jobs; i++) {
3622                 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3623         }
3624
3625         for (i=0; i < num_jobs; i++) {
3626                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3627         }
3628
3629         if (ret == true) {
3630                 torture_comment(tctx, "real print operations test succeeded\n\n");
3631         }
3632
3633         return ret;
3634 }
3635
3636 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3637                                       struct dcerpc_binding_handle *b,
3638                                       struct policy_handle *handle)
3639 {
3640         bool ret = true;
3641         uint32_t num_jobs = 8;
3642         uint32_t *job_ids;
3643         int i;
3644         torture_comment(tctx, "Testing real print operations (extended)\n");
3645
3646         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3647
3648         for (i=0; i < num_jobs; i++) {
3649                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3650         }
3651
3652         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3653
3654         for (i=0; i < num_jobs; i++) {
3655                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3656         }
3657
3658         if (ret == true) {
3659                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3660         }
3661
3662         return ret;
3663 }
3664
3665 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3666                                           struct RPC_PrintPropertyValue *got,
3667                                           struct RPC_PrintNamedProperty *exp)
3668 {
3669         torture_assert_int_equal(tctx,
3670                                  got->ePropertyType,
3671                                  exp->propertyValue.ePropertyType,
3672                                  "ePropertyType");
3673
3674         switch (exp->propertyValue.ePropertyType) {
3675         case kRpcPropertyTypeString:
3676                 torture_assert_str_equal(tctx,
3677                                          got->value.propertyString,
3678                                          exp->propertyValue.value.propertyString,
3679                                          "propertyString");
3680                 break;
3681         case kRpcPropertyTypeInt32:
3682                 torture_assert_int_equal(tctx,
3683                                          got->value.propertyInt32,
3684                                          exp->propertyValue.value.propertyInt32,
3685                                          "propertyInt32");
3686                 break;
3687         case kRpcPropertyTypeInt64:
3688                 torture_assert_u64_equal(tctx,
3689                                          got->value.propertyInt64,
3690                                          exp->propertyValue.value.propertyInt64,
3691                                          "propertyInt64");
3692                 break;
3693         case kRpcPropertyTypeByte:
3694                 torture_assert_int_equal(tctx,
3695                                          got->value.propertyByte,
3696                                          exp->propertyValue.value.propertyByte,
3697                                          "propertyByte");
3698                 break;
3699         case kRpcPropertyTypeBuffer:
3700                 torture_assert_int_equal(tctx,
3701                                          got->value.propertyBlob.cbBuf,
3702                                          exp->propertyValue.value.propertyBlob.cbBuf,
3703                                          "propertyBlob.cbBuf");
3704                 torture_assert_mem_equal(tctx,
3705                                          got->value.propertyBlob.pBuf,
3706                                          exp->propertyValue.value.propertyBlob.pBuf,
3707                                          exp->propertyValue.value.propertyBlob.cbBuf,
3708                                          "propertyBlob.pBuf");
3709
3710                 break;
3711
3712         }
3713
3714         return true;
3715 }
3716
3717 static bool test_JobPrintProperties(struct torture_context *tctx,
3718                                     struct dcerpc_binding_handle *b,
3719                                     struct policy_handle *handle,
3720                                     uint32_t job_id)
3721 {
3722         struct RPC_PrintNamedProperty in;
3723         struct RPC_PrintPropertyValue out;
3724         int i;
3725         DATA_BLOB blob = data_blob_string_const("blob");
3726         struct {
3727                 const char *property_name;
3728                 enum RPC_EPrintPropertyType type;
3729                 union RPC_PrintPropertyValueUnion value;
3730                 WERROR expected_result;
3731         } tests[] = {
3732                 {
3733                         .property_name                  = "torture_property_string",
3734                         .type                           = kRpcPropertyTypeString,
3735                         .value.propertyString           = "torture_property_value_string",
3736                 },{
3737                         .property_name                  = "torture_property_int32",
3738                         .type                           = kRpcPropertyTypeInt32,
3739                         .value.propertyInt32            = 42,
3740                 },{
3741                         .property_name                  = "torture_property_int64",
3742                         .type                           = kRpcPropertyTypeInt64,
3743                         .value.propertyInt64            = 0xaffe,
3744                 },{
3745                         .property_name                  = "torture_property_byte",
3746                         .type                           = kRpcPropertyTypeByte,
3747                         .value.propertyByte             = 0xab,
3748                 },{
3749                         .property_name                  = "torture_property_buffer",
3750                         .type                           = kRpcPropertyTypeBuffer,
3751                         .value.propertyBlob.cbBuf       = blob.length,
3752                         .value.propertyBlob.pBuf        = blob.data,
3753                 }
3754         };
3755
3756         torture_assert(tctx,
3757                 test_JobPropertiesEnum(tctx, b, handle, job_id),
3758                 "failed to enum properties");
3759
3760         for (i=0; i <ARRAY_SIZE(tests); i++) {
3761
3762                 in.propertyName                 = tests[i].property_name;
3763                 in.propertyValue.ePropertyType  = tests[i].type;
3764                 in.propertyValue.value          = tests[i].value;
3765
3766                 torture_assert(tctx,
3767                         test_JobPropertySet(tctx, b, handle, job_id, &in),
3768                         "failed to set property");
3769
3770                 torture_assert(tctx,
3771                         test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3772                         "failed to get property");
3773
3774                 torture_assert(tctx,
3775                         test_JobPrintProperties_equal(tctx, &out, &in),
3776                         "property unequal");
3777
3778                 torture_assert(tctx,
3779                         test_JobPropertiesEnum(tctx, b, handle, job_id),
3780                         "failed to enum properties");
3781
3782                 torture_assert(tctx,
3783                         test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3784                         "failed to delete job property");
3785         }
3786
3787         torture_assert(tctx,
3788                 test_JobPropertiesEnum(tctx, b, handle, job_id),
3789                 "failed to enum properties");
3790
3791         return true;
3792 }
3793
3794 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3795                                         struct dcerpc_binding_handle *b,
3796                                         struct policy_handle *handle)
3797 {
3798         uint32_t num_jobs = 8;
3799         uint32_t *job_ids;
3800         int i;
3801         torture_comment(tctx, "Testing real print operations (properties)\n");
3802
3803         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3804
3805         for (i=0; i < num_jobs; i++) {
3806                 torture_assert(tctx,
3807                         test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3808                         "failed to create print job");
3809         }
3810
3811         for (i=0; i < num_jobs; i++) {
3812                 torture_assert(tctx,
3813                         test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3814                         "failed to test job properties");
3815         }
3816
3817
3818         for (i=0; i < num_jobs; i++) {
3819                 torture_assert(tctx,
3820                         test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3821                         "failed to delete printjob");
3822         }
3823
3824         torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3825
3826         return true;
3827 }
3828
3829 static bool test_PausePrinter(struct torture_context *tctx,
3830                               struct dcerpc_binding_handle *b,
3831                               struct policy_handle *handle)
3832 {
3833         NTSTATUS status;
3834         struct spoolss_SetPrinter r;
3835         struct spoolss_SetPrinterInfoCtr info_ctr;
3836         struct spoolss_DevmodeContainer devmode_ctr;
3837         struct sec_desc_buf secdesc_ctr;
3838
3839         info_ctr.level = 0;
3840         info_ctr.info.info0 = NULL;
3841
3842         ZERO_STRUCT(devmode_ctr);
3843         ZERO_STRUCT(secdesc_ctr);
3844
3845         r.in.handle             = handle;
3846         r.in.info_ctr           = &info_ctr;
3847         r.in.devmode_ctr        = &devmode_ctr;
3848         r.in.secdesc_ctr        = &secdesc_ctr;
3849         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3850
3851         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3852
3853         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3854
3855         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3856
3857         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3858
3859         return true;
3860 }
3861
3862 static bool test_ResumePrinter(struct torture_context *tctx,
3863                                struct dcerpc_binding_handle *b,
3864                                struct policy_handle *handle)
3865 {
3866         NTSTATUS status;
3867         struct spoolss_SetPrinter r;
3868         struct spoolss_SetPrinterInfoCtr info_ctr;
3869         struct spoolss_DevmodeContainer devmode_ctr;
3870         struct sec_desc_buf secdesc_ctr;
3871
3872         info_ctr.level = 0;
3873         info_ctr.info.info0 = NULL;
3874
3875         ZERO_STRUCT(devmode_ctr);
3876         ZERO_STRUCT(secdesc_ctr);
3877
3878         r.in.handle             = handle;
3879         r.in.info_ctr           = &info_ctr;
3880         r.in.devmode_ctr        = &devmode_ctr;
3881         r.in.secdesc_ctr        = &secdesc_ctr;
3882         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3883
3884         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3885
3886         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3887
3888         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3889
3890         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3891
3892         return true;
3893 }
3894
3895 static bool test_printer_purge(struct torture_context *tctx,
3896                                struct dcerpc_binding_handle *b,
3897                                struct policy_handle *handle)
3898 {
3899         NTSTATUS status;
3900         struct spoolss_SetPrinter r;
3901         struct spoolss_SetPrinterInfoCtr info_ctr;
3902         struct spoolss_DevmodeContainer devmode_ctr;
3903         struct sec_desc_buf secdesc_ctr;
3904
3905         info_ctr.level = 0;
3906         info_ctr.info.info0 = NULL;
3907
3908         ZERO_STRUCT(devmode_ctr);
3909         ZERO_STRUCT(secdesc_ctr);
3910
3911         r.in.handle             = handle;
3912         r.in.info_ctr           = &info_ctr;
3913         r.in.devmode_ctr        = &devmode_ctr;
3914         r.in.secdesc_ctr        = &secdesc_ctr;
3915         r.in.command            = SPOOLSS_PRINTER_CONTROL_PURGE;
3916
3917         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3918
3919         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3920         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3921         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3922
3923         return true;
3924 }
3925
3926 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3927                                           struct dcerpc_binding_handle *b,
3928                                           struct policy_handle *handle,
3929                                           const char *value_name,
3930                                           enum winreg_Type *expected_type,
3931                                           enum winreg_Type *type_p,
3932                                           uint8_t **data_p,
3933                                           uint32_t *needed_p)
3934 {
3935         NTSTATUS status;
3936         struct spoolss_GetPrinterData r;
3937         uint32_t needed;
3938         enum winreg_Type type;
3939         union spoolss_PrinterData data;
3940
3941         r.in.handle = handle;
3942         r.in.value_name = value_name;
3943         r.in.offered = 0;
3944         r.out.needed = &needed;
3945         r.out.type = &type;
3946         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3947
3948         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3949
3950         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3951         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3952
3953         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3954                 if (expected_type) {
3955                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3956                 }
3957                 r.in.offered = needed;
3958                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3959                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3960                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3961         }
3962
3963         torture_assert_werr_ok(tctx, r.out.result,
3964                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3965
3966         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3967
3968         if (type_p) {
3969                 *type_p = type;
3970         }
3971
3972         if (data_p) {
3973                 *data_p = r.out.data;
3974         }
3975
3976         if (needed_p) {
3977                 *needed_p = needed;
3978         }
3979
3980         return true;
3981 }
3982
3983 static bool test_GetPrinterData(struct torture_context *tctx,
3984                                 struct dcerpc_binding_handle *b,
3985                                 struct policy_handle *handle,
3986                                 const char *value_name,
3987                                 enum winreg_Type *type_p,
3988                                 uint8_t **data_p,
3989                                 uint32_t *needed_p)
3990 {
3991         return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3992                                              NULL, type_p, data_p, needed_p);
3993 }
3994
3995 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3996                                             struct dcerpc_pipe *p,
3997                                             struct policy_handle *handle,
3998                                             const char *key_name,
3999                                             const char *value_name,
4000                                             enum winreg_Type *expected_type,
4001                                             enum winreg_Type *type_p,
4002                                             uint8_t **data_p,
4003                                             uint32_t *needed_p)
4004 {
4005         NTSTATUS status;
4006         struct spoolss_GetPrinterDataEx r;
4007         enum winreg_Type type;
4008         uint32_t needed;
4009         union spoolss_PrinterData data;
4010         struct dcerpc_binding_handle *b = p->binding_handle;
4011
4012         r.in.handle = handle;
4013         r.in.key_name = key_name;
4014         r.in.value_name = value_name;
4015         r.in.offered = 0;
4016         r.out.type = &type;
4017         r.out.needed = &needed;
4018         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4019
4020         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
4021                 r.in.key_name, r.in.value_name);
4022
4023         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4024         if (!NT_STATUS_IS_OK(status)) {
4025                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
4026                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
4027                 }
4028                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4029         }
4030
4031         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4032                 if (expected_type) {
4033                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
4034                 }
4035                 r.in.offered = needed;
4036                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4037                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4038                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4039         }
4040
4041         torture_assert_werr_ok(tctx, r.out.result,
4042                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
4043
4044         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
4045
4046         if (type_p) {
4047                 *type_p = type;
4048         }
4049
4050         if (data_p) {
4051                 *data_p = r.out.data;
4052         }
4053
4054         if (needed_p) {
4055                 *needed_p = needed;
4056         }
4057
4058         return true;
4059 }
4060
4061 static bool test_GetPrinterDataEx(struct torture_context *tctx,
4062                                   struct dcerpc_pipe *p,
4063                                   struct policy_handle *handle,
4064                                   const char *key_name,
4065                                   const char *value_name,
4066                                   enum winreg_Type *type_p,
4067                                   uint8_t **data_p,
4068                                   uint32_t *needed_p)
4069 {
4070         return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
4071                                                NULL, type_p, data_p, needed_p);
4072 }
4073
4074 static bool test_get_environment(struct torture_context *tctx,
4075                                  struct dcerpc_binding_handle *b,
4076                                  struct policy_handle *handle,
4077                                  const char **architecture)
4078 {
4079         DATA_BLOB blob;
4080         enum winreg_Type type;
4081         uint8_t *data;
4082         uint32_t needed;
4083
4084         torture_assert(tctx,
4085                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4086                 "failed to get Architecture");
4087
4088         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4089
4090         blob = data_blob_const(data, needed);
4091         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4092
4093         return true;
4094 }
4095
4096 static bool test_GetPrinterData_list(struct torture_context *tctx,
4097                                      void *private_data)
4098 {
4099         struct test_spoolss_context *ctx =
4100                 talloc_get_type_abort(private_data, struct test_spoolss_context);
4101         struct dcerpc_pipe *p = ctx->spoolss_pipe;
4102         struct dcerpc_binding_handle *b = p->binding_handle;
4103         const char *list[] = {
4104                 "W3SvcInstalled",
4105                 "BeepEnabled",
4106                 "EventLog",
4107                 /* "NetPopup", not on w2k8 */
4108                 /* "NetPopupToComputer", not on w2k8 */
4109                 "MajorVersion",
4110                 "MinorVersion",
4111                 "DefaultSpoolDirectory",
4112                 "Architecture",
4113                 "DsPresent",
4114                 "OSVersion",
4115                 /* "OSVersionEx", not on s3 */
4116                 "DNSMachineName"
4117         };
4118         int i;
4119
4120         for (i=0; i < ARRAY_SIZE(list); i++) {
4121                 enum winreg_Type type = REG_NONE;
4122                 enum winreg_Type type_ex1 = REG_NONE;
4123                 enum winreg_Type type_ex2 = REG_NONE;
4124                 uint8_t *data;
4125                 uint8_t *data_ex1 = NULL;
4126                 uint8_t *data_ex2 = NULL;
4127                 uint32_t needed;
4128                 uint32_t needed_ex1 = 0;
4129                 uint32_t needed_ex2 = 0;
4130
4131                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4132                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4133                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex1, &data_ex1, &needed_ex1),
4134                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4135                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "", list[i], &type_ex2, &data_ex2, &needed_ex2),
4136                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4137                 torture_assert_int_equal(tctx, type, type_ex1, "type mismatch");
4138                 torture_assert_int_equal(tctx, type, type_ex2, "type mismatch");
4139                 torture_assert_int_equal(tctx, needed, needed_ex1, "needed mismatch");
4140                 torture_assert_int_equal(tctx, needed, needed_ex2, "needed mismatch");
4141                 torture_assert_mem_equal(tctx, data, data_ex1, needed, "data mismatch");
4142                 torture_assert_mem_equal(tctx, data, data_ex2, needed, "data mismatch");
4143         }
4144
4145         return true;
4146 }
4147
4148 static bool test_EnumPrinterData(struct torture_context *tctx,
4149                                  struct dcerpc_pipe *p,
4150                                  struct policy_handle *handle,
4151                                  uint32_t enum_index,
4152                                  uint32_t value_offered,
4153                                  uint32_t data_offered,
4154                                  enum winreg_Type *type_p,
4155                                  uint32_t *value_needed_p,
4156                                  uint32_t *data_needed_p,
4157                                  const char **value_name_p,
4158                                  uint8_t **data_p,
4159                                  WERROR *result_p)
4160 {
4161         struct spoolss_EnumPrinterData r;
4162         uint32_t data_needed;
4163         uint32_t value_needed;
4164         enum winreg_Type type;
4165         struct dcerpc_binding_handle *b = p->binding_handle;
4166
4167         r.in.handle = handle;
4168         r.in.enum_index = enum_index;
4169         r.in.value_offered = value_offered;
4170         r.in.data_offered = data_offered;
4171         r.out.data_needed = &data_needed;
4172         r.out.value_needed = &value_needed;
4173         r.out.type = &type;
4174         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4175         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4176
4177         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4178
4179         torture_assert_ntstatus_ok(tctx,
4180                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4181                 "EnumPrinterData failed");
4182
4183         if (type_p) {
4184                 *type_p = type;
4185         }
4186         if (value_needed_p) {
4187                 *value_needed_p = value_needed;
4188         }
4189         if (data_needed_p) {
4190                 *data_needed_p = data_needed;
4191         }
4192         if (value_name_p) {
4193                 *value_name_p = r.out.value_name;
4194         }
4195         if (data_p) {
4196                 *data_p = r.out.data;
4197         }
4198         if (result_p) {
4199                 *result_p = r.out.result;
4200         }
4201
4202         return true;
4203 }
4204
4205
4206 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4207                                      struct dcerpc_pipe *p,
4208                                      struct policy_handle *handle)
4209 {
4210         uint32_t enum_index = 0;
4211         enum winreg_Type type;
4212         uint32_t value_needed;
4213         uint32_t data_needed;
4214         uint8_t *data;
4215         const char *value_name;
4216         WERROR result;
4217
4218         torture_comment(tctx, "Testing EnumPrinterData\n");
4219
4220         do {
4221                 torture_assert(tctx,
4222                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4223                                              &type, &value_needed, &data_needed,
4224                                              &value_name, &data, &result),
4225                         "EnumPrinterData failed");
4226
4227                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4228                         break;
4229                 }
4230
4231                 torture_assert(tctx,
4232                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4233                                              &type, &value_needed, &data_needed,
4234                                              &value_name, &data, &result),
4235                         "EnumPrinterData failed");
4236
4237                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4238                         break;
4239                 }
4240
4241                 enum_index++;
4242
4243         } while (W_ERROR_IS_OK(result));
4244
4245         torture_comment(tctx, "EnumPrinterData test succeeded\n");
4246
4247         return true;
4248 }
4249
4250 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4251                                    struct dcerpc_binding_handle *b,
4252                                    struct policy_handle *handle,
4253                                    const char *key_name,
4254                                    uint32_t *count_p,
4255                                    struct spoolss_PrinterEnumValues **info_p)
4256 {
4257         struct spoolss_EnumPrinterDataEx r;
4258         struct spoolss_PrinterEnumValues *info;
4259         uint32_t needed;
4260         uint32_t count;
4261
4262         r.in.handle = handle;
4263         r.in.key_name = key_name;
4264         r.in.offered = 0;
4265         r.out.needed = &needed;
4266         r.out.count = &count;
4267         r.out.info = &info;
4268
4269         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4270
4271         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4272                 "EnumPrinterDataEx failed");
4273         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4274                 r.in.offered = needed;
4275                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4276                         "EnumPrinterDataEx failed");
4277         }
4278
4279         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4280
4281         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4282
4283         if (count_p) {
4284                 *count_p = count;
4285         }
4286         if (info_p) {
4287                 *info_p = info;
4288         }
4289
4290         return true;
4291 }
4292
4293 static bool test_SetPrinterData(struct torture_context *tctx,
4294                                 struct dcerpc_binding_handle *b,
4295                                 struct policy_handle *handle,
4296                                 const char *value_name,
4297                                 enum winreg_Type type,
4298                                 uint8_t *data,
4299                                 uint32_t offered);
4300 static bool test_DeletePrinterData(struct torture_context *tctx,
4301                                    struct dcerpc_binding_handle *b,
4302                                    struct policy_handle *handle,
4303                                    const char *value_name);
4304
4305 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4306                                              struct dcerpc_pipe *p,
4307                                              struct policy_handle *handle)
4308 {
4309         uint32_t count;
4310         struct spoolss_PrinterEnumValues *info;
4311         int i;
4312         uint32_t value_needed, data_needed;
4313         uint32_t value_offered, data_offered;
4314         WERROR result;
4315         struct dcerpc_binding_handle *b = p->binding_handle;
4316
4317         enum winreg_Type type;
4318         DATA_BLOB blob;
4319
4320         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4321
4322         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4323         type = REG_SZ;
4324
4325         torture_assert(tctx,
4326                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4327                 "SetPrinterData failed");
4328
4329         blob = data_blob_string_const("torture_data2");
4330
4331         torture_assert(tctx,
4332                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4333                 "SetPrinterData failed");
4334
4335         blob = data_blob_talloc(tctx, NULL, 4);
4336         SIVAL(blob.data, 0, 0x11223344);
4337
4338         torture_assert(tctx,
4339                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4340                 "SetPrinterData failed");
4341
4342         torture_assert(tctx,
4343                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4344                 "failed to call EnumPrinterDataEx");
4345
4346         /* get the max sizes for value and data */
4347
4348         torture_assert(tctx,
4349                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4350                                      NULL, &value_needed, &data_needed,
4351                                      NULL, NULL, &result),
4352                 "EnumPrinterData failed");
4353         torture_assert_werr_ok(tctx, result, "unexpected result");
4354
4355         /* check if the reply from the EnumPrinterData really matches max values */
4356
4357         for (i=0; i < count; i++) {
4358                 if (info[i].value_name_len > value_needed) {
4359                         torture_fail(tctx,
4360                                 talloc_asprintf(tctx,
4361                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4362                                 info[i].value_name_len, value_needed));
4363                 }
4364                 if (info[i].data_length > data_needed) {
4365                         torture_fail(tctx,
4366                                 talloc_asprintf(tctx,
4367                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4368                                 info[i].data_length, data_needed));
4369                 }
4370         }
4371
4372         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4373          * sort or not sort the replies by value name, we should be able to do
4374          * the following entry comparison */
4375
4376         data_offered = data_needed;
4377         value_offered = value_needed;
4378
4379         for (i=0; i < count; i++) {
4380
4381                 const char *value_name;
4382                 uint8_t *data;
4383
4384                 torture_assert(tctx,
4385                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4386                                              &type, &value_needed, &data_needed,
4387                                              &value_name, &data, &result),
4388                         "EnumPrinterData failed");
4389
4390                 if (i -1 == count) {
4391                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4392                                 "unexpected result");
4393                         break;
4394                 } else {
4395                         torture_assert_werr_ok(tctx, result, "unexpected result");
4396                 }
4397
4398                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4399                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4400                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4401                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4402                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4403         }
4404
4405         torture_assert(tctx,
4406                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4407                 "DeletePrinterData failed");
4408         torture_assert(tctx,
4409                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4410                 "DeletePrinterData failed");
4411         torture_assert(tctx,
4412                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4413                 "DeletePrinterData failed");
4414
4415         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4416
4417         return true;
4418 }
4419
4420 static bool test_DeletePrinterData(struct torture_context *tctx,
4421                                    struct dcerpc_binding_handle *b,
4422                                    struct policy_handle *handle,
4423                                    const char *value_name)
4424 {
4425         NTSTATUS status;
4426         struct spoolss_DeletePrinterData r;
4427
4428         r.in.handle = handle;
4429         r.in.value_name = value_name;
4430
4431         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4432                 r.in.value_name);
4433
4434         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4435
4436         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4437         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4438
4439         return true;
4440 }
4441
4442 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4443                                      struct dcerpc_binding_handle *b,
4444                                      struct policy_handle *handle,
4445                                      const char *key_name,
4446                                      const char *value_name)
4447 {
4448         struct spoolss_DeletePrinterDataEx r;
4449
4450         r.in.handle = handle;
4451         r.in.key_name = key_name;
4452         r.in.value_name = value_name;
4453
4454         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4455                 r.in.key_name, r.in.value_name);
4456
4457         torture_assert_ntstatus_ok(tctx,
4458                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4459                 "DeletePrinterDataEx failed");
4460         torture_assert_werr_ok(tctx, r.out.result,
4461                 "DeletePrinterDataEx failed");
4462
4463         return true;
4464 }
4465
4466 static bool test_DeletePrinterKey(struct torture_context *tctx,
4467                                   struct dcerpc_binding_handle *b,
4468                                   struct policy_handle *handle,
4469                                   const char *key_name)
4470 {
4471         struct spoolss_DeletePrinterKey r;
4472
4473         r.in.handle = handle;
4474         r.in.key_name = key_name;
4475
4476         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4477
4478         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4479                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4480                 return true;
4481         }
4482
4483         torture_assert_ntstatus_ok(tctx,
4484                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4485                 "DeletePrinterKey failed");
4486         torture_assert_werr_ok(tctx, r.out.result,
4487                 "DeletePrinterKey failed");
4488
4489         return true;
4490 }
4491
4492 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4493                                  struct dcerpc_binding_handle *b,
4494                                  struct policy_handle *handle)
4495 {
4496         struct winreg_OpenHKLM r;
4497
4498         r.in.system_name = NULL;
4499         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4500         r.out.handle = handle;
4501
4502         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4503
4504         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4505         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4506
4507         return true;
4508 }
4509
4510 static void init_winreg_String(struct winreg_String *name, const char *s)
4511 {
4512         name->name = s;
4513         if (s) {
4514                 name->name_len = 2 * (strlen_m(s) + 1);
4515                 name->name_size = name->name_len;
4516         } else {
4517                 name->name_len = 0;
4518                 name->name_size = 0;
4519         }
4520 }
4521
4522 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4523                                      struct dcerpc_binding_handle *b,
4524                                      struct policy_handle *hive_handle,
4525                                      const char *keyname,
4526                                      uint32_t options,
4527                                      struct policy_handle *key_handle)
4528 {
4529         struct winreg_OpenKey r;
4530
4531         r.in.parent_handle = hive_handle;
4532         init_winreg_String(&r.in.keyname, keyname);
4533         r.in.options = options;
4534         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4535         r.out.handle = key_handle;
4536
4537         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4538
4539         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4540         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4541
4542         return true;
4543 }
4544
4545 static bool test_winreg_OpenKey(struct torture_context *tctx,
4546                                 struct dcerpc_binding_handle *b,
4547                                 struct policy_handle *hive_handle,
4548                                 const char *keyname,
4549                                 struct policy_handle *key_handle)
4550 {
4551         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4552                                         REG_OPTION_NON_VOLATILE, key_handle);
4553 }
4554
4555 static bool test_winreg_CloseKey(struct torture_context *tctx,
4556                                  struct dcerpc_binding_handle *b,
4557                                  struct policy_handle *handle)
4558 {
4559         struct winreg_CloseKey r;
4560
4561         r.in.handle = handle;
4562         r.out.handle = handle;
4563
4564         torture_comment(tctx, "Testing winreg_CloseKey\n");
4565
4566         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4567         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4568
4569         return true;
4570 }
4571
4572 bool test_winreg_QueryValue(struct torture_context *tctx,
4573                             struct dcerpc_binding_handle *b,
4574                             struct policy_handle *handle,
4575                             const char *value_name,
4576                             enum winreg_Type *type_p,
4577                             uint32_t *data_size_p,
4578                             uint32_t *data_length_p,
4579                             uint8_t **data_p)
4580 {
4581         struct winreg_QueryValue r;
4582         enum winreg_Type type = REG_NONE;
4583         uint32_t data_size = 0;
4584         uint32_t data_length = 0;
4585         struct winreg_String valuename;
4586         uint8_t *data = NULL;
4587
4588         init_winreg_String(&valuename, value_name);
4589
4590         data = talloc_zero_array(tctx, uint8_t, 0);
4591
4592         r.in.handle = handle;
4593         r.in.value_name = &valuename;
4594         r.in.type = &type;
4595         r.in.data_size = &data_size;
4596         r.in.data_length = &data_length;
4597         r.in.data = data;
4598         r.out.type = &type;
4599         r.out.data = data;
4600         r.out.data_size = &data_size;
4601         r.out.data_length = &data_length;
4602
4603         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4604
4605         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4606         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4607                 *r.in.data_size = *r.out.data_size;
4608                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4609                 r.in.data = data;
4610                 r.out.data = data;
4611                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4612         }
4613         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4614
4615         if (type_p) {
4616                 *type_p = *r.out.type;
4617         }
4618         if (data_size_p) {
4619                 *data_size_p = *r.out.data_size;
4620         }
4621         if (data_length_p) {
4622                 *data_length_p = *r.out.data_length;
4623         }
4624         if (data_p) {
4625                 *data_p = r.out.data;
4626         }
4627
4628         return true;
4629 }
4630
4631 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4632                                           struct dcerpc_binding_handle *b,
4633                                           struct policy_handle *handle,
4634                                           const char *printer_name,
4635                                           const char *key_name,
4636                                           const char *value_name,
4637                                           enum winreg_Type *w_type,
4638                                           uint32_t *w_size,
4639                                           uint32_t *w_length,
4640                                           uint8_t **w_data)
4641 {
4642         const char *printer_key;
4643         struct policy_handle key_handle;
4644
4645         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4646                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4647
4648         torture_assert(tctx,
4649                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4650
4651         torture_assert(tctx,
4652                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4653
4654         torture_assert(tctx,
4655                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4656
4657         return true;
4658 }
4659
4660 static bool test_GetForm_winreg(struct torture_context *tctx,
4661                                 struct dcerpc_binding_handle *b,
4662                                 struct policy_handle *handle,
4663                                 const char *key_name,
4664                                 const char *form_name,
4665                                 enum winreg_Type *w_type,
4666                                 uint32_t *w_size,
4667                                 uint32_t *w_length,
4668                                 uint8_t **w_data)
4669 {
4670         struct policy_handle key_handle;
4671
4672         torture_assert(tctx,
4673                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4674
4675         torture_assert(tctx,
4676                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4677
4678         torture_assert(tctx,
4679                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4680
4681         return true;
4682 }
4683
4684 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4685                                       struct dcerpc_binding_handle *b,
4686                                       struct policy_handle *handle,
4687                                       const char *symlink_keyname,
4688                                       const char *symlink_destination)
4689 {
4690         /* check if the first key is a symlink to the second key */
4691
4692         enum winreg_Type w_type;
4693         uint32_t w_size;
4694         uint32_t w_length;
4695         uint8_t *w_data;
4696         struct policy_handle key_handle;
4697         DATA_BLOB blob;
4698         const char *str;
4699
4700         if (torture_setting_bool(tctx, "samba3", false)) {
4701                 torture_skip(tctx, "skip winreg symlink test against samba");
4702         }
4703
4704         torture_assert(tctx,
4705                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4706                         "failed to open key link");
4707
4708         torture_assert(tctx,
4709                 test_winreg_QueryValue(tctx, b, &key_handle,
4710                                        "SymbolicLinkValue",
4711                                        &w_type, &w_size, &w_length, &w_data),
4712                 "failed to query for 'SymbolicLinkValue' attribute");
4713
4714         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4715
4716         blob = data_blob(w_data, w_size);
4717         str = reg_val_data_string(tctx, REG_SZ, blob);
4718
4719         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4720
4721         torture_assert(tctx,
4722                 test_winreg_CloseKey(tctx, b, &key_handle),
4723                 "failed to close key link");
4724
4725         return true;
4726 }
4727
4728 static const char *strip_unc(const char *unc)
4729 {
4730         char *name;
4731
4732         if (!unc) {
4733                 return NULL;
4734         }
4735
4736         if (unc[0] == '\\' && unc[1] == '\\') {
4737                 unc +=2;
4738         }
4739
4740         name = strchr(unc, '\\');
4741         if (name) {
4742                 return name+1;
4743         }
4744
4745         return unc;
4746 }
4747
4748 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4749                                        struct dcerpc_binding_handle *b,
4750                                        struct policy_handle *handle,
4751                                        const char *printer_name,
4752                                        struct dcerpc_binding_handle *winreg_handle,
4753                                        struct policy_handle *hive_handle)
4754 {
4755         union spoolss_PrinterInfo info;
4756         const char *keys[] = {
4757                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4758                 TOP_LEVEL_PRINT_PRINTERS_KEY
4759         };
4760         int i;
4761         const char *printername, *sharename;
4762
4763         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4764
4765         torture_assert(tctx,
4766                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4767                 "failed to get printer info level 2");
4768
4769         printername = strip_unc(info.info2.printername);
4770         sharename = strip_unc(info.info2.sharename);
4771
4772 #define test_sz(wname, iname) \
4773 do {\
4774         DATA_BLOB blob;\
4775         const char *str;\
4776         enum winreg_Type w_type;\
4777         uint32_t w_size;\
4778         uint32_t w_length;\
4779         uint8_t *w_data;\
4780         torture_assert(tctx,\
4781                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4782                                        &w_type, &w_size, &w_length, &w_data),\
4783                 "failed to query winreg");\
4784         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4785         blob = data_blob(w_data, w_size);\
4786         str = reg_val_data_string(tctx, REG_SZ, blob);\
4787         if (w_size == 2 && iname == NULL) {\
4788                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4789         } else {\
4790                 torture_assert_str_equal(tctx, str, iname,\
4791                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4792         }\
4793 } while(0);
4794
4795 #define test_dword(wname, iname) \
4796 do {\
4797         uint32_t value;\
4798         enum winreg_Type w_type;\
4799         uint32_t w_size;\
4800         uint32_t w_length;\
4801         uint8_t *w_data;\
4802         torture_assert(tctx,\
4803                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4804                                        &w_type, &w_size, &w_length, &w_data),\
4805                 "failed to query winreg");\
4806         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4807         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4808         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4809         value = IVAL(w_data, 0);\
4810         torture_assert_int_equal(tctx, value, iname,\
4811                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4812 } while(0);
4813
4814 #define test_binary(wname, iname) \
4815 do {\
4816         enum winreg_Type w_type;\
4817         uint32_t w_size;\
4818         uint32_t w_length;\
4819         uint8_t *w_data;\
4820         torture_assert(tctx,\
4821                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4822                                        &w_type, &w_size, &w_length, &w_data),\
4823                 "failed to query winreg");\
4824         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4825         torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4826         torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4827                 "binary unequal");\
4828 } while(0);
4829
4830
4831 #define test_dm(wname, iname) \
4832 do {\
4833         DATA_BLOB blob;\
4834         struct spoolss_DeviceMode dm;\
4835         enum ndr_err_code ndr_err;\
4836         enum winreg_Type w_type;\
4837         uint32_t w_size;\
4838         uint32_t w_length;\
4839         uint8_t *w_data;\
4840         torture_assert(tctx,\
4841                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4842                                        &w_type, &w_size, &w_length, &w_data),\
4843                 "failed to query winreg");\
4844         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4845         blob = data_blob(w_data, w_size);\
4846         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4847                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4848         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4849         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4850                 "dm unequal");\
4851 } while(0);
4852
4853 #define test_sd(wname, iname) \
4854 do {\
4855         DATA_BLOB blob;\
4856         struct security_descriptor sd;\
4857         enum ndr_err_code ndr_err;\
4858         enum winreg_Type w_type;\
4859         uint32_t w_size;\
4860         uint32_t w_length;\
4861         uint8_t *w_data;\
4862         torture_assert(tctx,\
4863                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4864                                        &w_type, &w_size, &w_length, &w_data),\
4865                 "failed to query winreg");\
4866         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4867         blob = data_blob(w_data, w_size);\
4868         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4869                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4870         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4871         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4872                 "sd unequal");\
4873 } while(0);
4874
4875 #define test_multi_sz(wname, iname) \
4876 do {\
4877         DATA_BLOB blob;\
4878         const char **array;\
4879         enum winreg_Type w_type;\
4880         uint32_t w_size;\
4881         uint32_t w_length;\
4882         uint8_t *w_data;\
4883         int i;\
4884         torture_assert(tctx,\
4885                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4886                                        &w_type, &w_size, &w_length, &w_data),\
4887                 "failed to query winreg");\
4888         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4889         blob = data_blob(w_data, w_size);\
4890         torture_assert(tctx, \
4891                 pull_reg_multi_sz(tctx, &blob, &array),\
4892                 "failed to pull multi sz");\
4893         for (i=0; array[i] != NULL; i++) {\
4894                 torture_assert_str_equal(tctx, array[i], iname[i],\
4895                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4896         }\
4897 } while(0);
4898
4899         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4900                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4901                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4902         {
4903                 torture_warning(tctx, "failed to check for winreg symlink");
4904         }
4905
4906         for (i=0; i < ARRAY_SIZE(keys); i++) {
4907
4908                 const char *printer_key;
4909                 struct policy_handle key_handle;
4910
4911                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4912                         keys[i], printer_name);
4913
4914                 torture_assert(tctx,
4915                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4916
4917                 test_sz("Name", printername);
4918                 test_sz("Share Name", sharename);
4919                 test_sz("Port", info.info2.portname);
4920                 test_sz("Printer Driver", info.info2.drivername);
4921                 test_sz("Description", info.info2.comment);
4922                 test_sz("Location", info.info2.location);
4923                 test_sz("Separator File", info.info2.sepfile);
4924                 test_sz("Print Processor", info.info2.printprocessor);
4925                 test_sz("Datatype", info.info2.datatype);
4926                 test_sz("Parameters", info.info2.parameters);
4927                 /* winreg: 0, spoolss not */
4928 /*              test_dword("Attributes", info.info2.attributes); */
4929                 test_dword("Priority", info.info2.priority);
4930                 test_dword("Default Priority", info.info2.defaultpriority);
4931                 /* winreg: 60, spoolss: 0 */
4932 /*              test_dword("StartTime", info.info2.starttime); */
4933 /*              test_dword("UntilTime", info.info2.untiltime); */
4934                 /* winreg != spoolss */
4935 /*              test_dword("Status", info.info2.status); */
4936                 test_dm("Default DevMode", info.info2.devmode);
4937                 test_sd("Security", info.info2.secdesc);
4938
4939                 torture_assert(tctx,
4940                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4941         }
4942
4943 #undef test_dm
4944 #undef test_sd
4945
4946         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4947
4948         return true;
4949 }
4950
4951 static bool test_PrintProcessors(struct torture_context *tctx,
4952                                  struct dcerpc_binding_handle *b,
4953                                  const char *environment,
4954                                  struct dcerpc_binding_handle *winreg_handle,
4955                                  struct policy_handle *hive_handle)
4956 {
4957         union spoolss_PrintProcessorInfo *info;
4958         uint32_t count;
4959         int i;
4960
4961         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4962
4963         torture_assert(tctx,
4964                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4965                 "failed to enum print processors level 1");
4966
4967         for (i=0; i < count; i++) {
4968
4969                 const char *processor_key;
4970                 struct policy_handle key_handle;
4971
4972                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4973                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4974                                                 environment,
4975                                                 info[i].info1.print_processor_name);
4976
4977                 torture_assert(tctx,
4978                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4979
4980                 /* nothing to check in there so far */
4981
4982                 torture_assert(tctx,
4983                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4984         }
4985
4986         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4987
4988         return true;
4989 }
4990
4991 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4992                                          struct dcerpc_binding_handle *b,
4993                                          struct policy_handle *handle,
4994                                          const char *driver_name,
4995                                          const char *architecture,
4996                                          uint32_t level,
4997                                          uint32_t client_major_version,
4998                                          uint32_t client_minor_version,
4999                                          union spoolss_DriverInfo *info_p,
5000                                          WERROR *result);
5001
5002 static const char *strip_path(const char *path)
5003 {
5004         char *p;
5005
5006         if (path == NULL) {
5007                 return NULL;
5008         }
5009
5010         p = strrchr(path, '\\');
5011         if (p) {
5012                 return p+1;
5013         }
5014
5015         return path;
5016 }
5017
5018 static const char **strip_paths(const char **path_array)
5019 {
5020         int i;
5021
5022         if (path_array == NULL) {
5023                 return NULL;
5024         }
5025
5026         for (i=0; path_array[i] != NULL; i++) {
5027                 path_array[i] = strip_path(path_array[i]);
5028         }
5029
5030         return path_array;
5031 }
5032
5033 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
5034 {
5035         time_t t;
5036         struct tm *tm;
5037
5038         if (nt == 0) {
5039                 return talloc_strdup(mem_ctx, "01/01/1601");
5040         }
5041
5042         t = nt_time_to_unix(nt);
5043         tm = localtime(&t);
5044
5045         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
5046                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
5047 }
5048
5049 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
5050 {
5051         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
5052                 (unsigned)((v >> 48) & 0xFFFF),
5053                 (unsigned)((v >> 32) & 0xFFFF),
5054                 (unsigned)((v >> 16) & 0xFFFF),
5055                 (unsigned)(v & 0xFFFF));
5056 }
5057
5058 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
5059                                       struct dcerpc_binding_handle *b,
5060                                       struct policy_handle *handle,
5061                                       const char *printer_name,
5062                                       const char *driver_name,
5063                                       const char *environment,
5064                                       enum spoolss_DriverOSVersion version,
5065                                       struct dcerpc_binding_handle *winreg_handle,
5066                                       struct policy_handle *hive_handle,
5067                                       const char *server_name_slash)
5068 {
5069         WERROR result = WERR_OK;
5070         union spoolss_DriverInfo info;
5071         const char *driver_key;
5072         struct policy_handle key_handle;
5073
5074         const char *driver_path;
5075         const char *data_file;
5076         const char *config_file;
5077         const char *help_file;
5078         const char **dependent_files;
5079
5080         const char *driver_date;
5081         const char *inbox_driver_date;
5082
5083         const char *driver_version;
5084         const char *inbox_driver_version;
5085
5086         ZERO_STRUCT(key_handle);
5087
5088         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
5089
5090         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5091                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5092                                      environment,
5093                                      version,
5094                                      driver_name);
5095
5096         torture_assert(tctx,
5097                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5098                 "failed to open driver key");
5099
5100         if (torture_setting_bool(tctx, "samba3", false) ||
5101             torture_setting_bool(tctx, "w2k3", false)) {
5102                 goto try_level6;
5103         }
5104
5105         if (handle) {
5106                 torture_assert(tctx,
5107                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5108                         "failed to get driver info level 8");
5109         } else {
5110                 torture_assert(tctx,
5111                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5112                         "failed to get driver info level 8");
5113         }
5114
5115         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5116                 goto try_level6;
5117         }
5118
5119         driver_path     = strip_path(info.info8.driver_path);
5120         data_file       = strip_path(info.info8.data_file);
5121         config_file     = strip_path(info.info8.config_file);
5122         help_file       = strip_path(info.info8.help_file);
5123         dependent_files = strip_paths(info.info8.dependent_files);
5124
5125         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
5126         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5127
5128         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
5129         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5130
5131         test_sz("Configuration File",           config_file);
5132         test_sz("Data File",                    data_file);
5133         test_sz("Datatype",                     info.info8.default_datatype);
5134         test_sz("Driver",                       driver_path);
5135         test_sz("DriverDate",                   driver_date);
5136         test_sz("DriverVersion",                driver_version);
5137         test_sz("HardwareID",                   info.info8.hardware_id);
5138         test_sz("Help File",                    help_file);
5139         test_sz("InfPath",                      info.info8.inf_path);
5140         test_sz("Manufacturer",                 info.info8.manufacturer_name);
5141         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
5142         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
5143         test_sz("Monitor",                      info.info8.monitor_name);
5144         test_sz("OEM URL",                      info.info8.manufacturer_url);
5145         test_sz("Print Processor",              info.info8.print_processor);
5146         test_sz("Provider",                     info.info8.provider);
5147         test_sz("VendorSetup",                  info.info8.vendor_setup);
5148         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
5149         test_multi_sz("Dependent Files",        dependent_files);
5150         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
5151         test_multi_sz("Previous Names",         info.info8.previous_names);
5152 /*      test_dword("Attributes",                ?); */
5153         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
5154         test_dword("Version",                   info.info8.version);
5155 /*      test_dword("TempDir",                   ?); */
5156
5157  try_level6:
5158
5159         if (handle) {
5160                 torture_assert(tctx,
5161                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5162                         "failed to get driver info level 6");
5163         } else {
5164                 torture_assert(tctx,
5165                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5166                         "failed to get driver info level 6");
5167         }
5168
5169         driver_path     = strip_path(info.info6.driver_path);
5170         data_file       = strip_path(info.info6.data_file);
5171         config_file     = strip_path(info.info6.config_file);
5172         help_file       = strip_path(info.info6.help_file);
5173         dependent_files = strip_paths(info.info6.dependent_files);
5174
5175         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
5176
5177         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
5178
5179         test_sz("Configuration File",           config_file);
5180         test_sz("Data File",                    data_file);
5181         test_sz("Datatype",                     info.info6.default_datatype);
5182         test_sz("Driver",                       driver_path);
5183         if (torture_setting_bool(tctx, "w2k3", false)) {
5184                 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5185                 push_nttime(blob.data, 0, info.info6.driver_date);
5186                 test_binary("DriverDate",       blob);
5187                 SBVAL(blob.data, 0, info.info6.driver_version);
5188                 test_binary("DriverVersion",    blob);
5189         } else {
5190                 test_sz("DriverDate",           driver_date);
5191                 test_sz("DriverVersion",        driver_version);
5192         }
5193         test_sz("HardwareID",                   info.info6.hardware_id);
5194         test_sz("Help File",                    help_file);
5195         test_sz("Manufacturer",                 info.info6.manufacturer_name);
5196         test_sz("Monitor",                      info.info6.monitor_name);
5197         test_sz("OEM URL",                      info.info6.manufacturer_url);
5198         test_sz("Provider",                     info.info6.provider);
5199         test_multi_sz("Dependent Files",        dependent_files);
5200         test_multi_sz("Previous Names",         info.info6.previous_names);
5201 /*      test_dword("Attributes",                ?); */
5202         test_dword("Version",                   info.info6.version);
5203 /*      test_dword("TempDir",                   ?); */
5204
5205         if (handle) {
5206                 torture_assert(tctx,
5207                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5208                         "failed to get driver info level 3");
5209         } else {
5210                 torture_assert(tctx,
5211                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5212                         "failed to get driver info level 3");
5213         }
5214
5215         driver_path     = strip_path(info.info3.driver_path);
5216         data_file       = strip_path(info.info3.data_file);
5217         config_file     = strip_path(info.info3.config_file);
5218         help_file       = strip_path(info.info3.help_file);
5219         dependent_files = strip_paths(info.info3.dependent_files);
5220
5221         test_sz("Configuration File",           config_file);
5222         test_sz("Data File",                    data_file);
5223         test_sz("Datatype",                     info.info3.default_datatype);
5224         test_sz("Driver",                       driver_path);
5225         test_sz("Help File",                    help_file);
5226         test_sz("Monitor",                      info.info3.monitor_name);
5227         test_multi_sz("Dependent Files",        dependent_files);
5228 /*      test_dword("Attributes",                ?); */
5229         test_dword("Version",                   info.info3.version);
5230 /*      test_dword("TempDir",                   ?); */
5231
5232
5233         torture_assert(tctx,
5234                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5235
5236         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5237
5238         return true;
5239 }
5240
5241 #undef test_sz
5242 #undef test_dword
5243
5244 static bool test_SetPrinterData(struct torture_context *tctx,
5245                                 struct dcerpc_binding_handle *b,
5246                                 struct policy_handle *handle,
5247                                 const char *value_name,
5248                                 enum winreg_Type type,
5249                                 uint8_t *data,
5250                                 uint32_t offered)
5251 {
5252         struct spoolss_SetPrinterData r;
5253
5254         r.in.handle = handle;
5255         r.in.value_name = value_name;
5256         r.in.type = type;
5257         r.in.data = data;
5258         r.in.offered = offered;
5259
5260         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5261                 r.in.value_name);
5262
5263         torture_assert_ntstatus_ok(tctx,
5264                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5265                 "SetPrinterData failed");
5266         torture_assert_werr_ok(tctx, r.out.result,
5267                 "SetPrinterData failed");
5268
5269         return true;
5270 }
5271
5272 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5273                                        struct dcerpc_binding_handle *b,
5274                                        struct policy_handle *handle,
5275                                        const char *printer_name,
5276                                        struct dcerpc_binding_handle *winreg_handle,
5277                                        struct policy_handle *hive_handle)
5278 {
5279         const char *values[] = {
5280                 "spootyfoot",
5281                 "spooty\\foot",
5282 #if 0
5283         /* FIXME: not working with s3 atm. */
5284                 "spooty,foot",
5285                 "spooty,fo,ot",
5286 #endif
5287                 "spooty foot",
5288 #if 0
5289         /* FIXME: not working with s3 atm. */
5290                 "spooty\\fo,ot",
5291                 "spooty,fo\\ot"
5292 #endif
5293         };
5294         int i;
5295
5296         for (i=0; i < ARRAY_SIZE(values); i++) {
5297
5298                 enum winreg_Type type, expected_type = REG_SZ;
5299                 DATA_BLOB blob;
5300                 uint8_t *data;
5301                 uint32_t needed;
5302
5303                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5304                 type = REG_SZ;
5305
5306                 torture_assert(tctx,
5307                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5308                         "SetPrinterData failed");
5309
5310                 torture_assert(tctx,
5311                         test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5312                         "GetPrinterData failed");
5313
5314                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5315                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5316                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5317
5318                 if (winreg_handle && hive_handle) {
5319
5320                         enum winreg_Type w_type;
5321                         uint32_t w_size;
5322                         uint32_t w_length;
5323                         uint8_t *w_data;
5324
5325                         torture_assert(tctx,
5326                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5327                                         printer_name, "PrinterDriverData", values[i],
5328                                         &w_type, &w_size, &w_length, &w_data), "");
5329
5330                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5331                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5332                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5333                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5334                 }
5335
5336                 torture_assert(tctx,
5337                         test_DeletePrinterData(tctx, b, handle, values[i]),
5338                         "DeletePrinterData failed");
5339         }
5340
5341         return true;
5342 }
5343
5344
5345 static bool test_EnumPrinterKey(struct torture_context *tctx,
5346                                 struct dcerpc_binding_handle *b,
5347                                 struct policy_handle *handle,
5348                                 const char *key_name,
5349                                 const char ***array);
5350
5351 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5352                                   struct dcerpc_binding_handle *b,
5353                                   struct policy_handle *handle,
5354                                   const char *key_name,
5355                                   const char *value_name,
5356                                   enum winreg_Type type,
5357                                   uint8_t *data,
5358                                   uint32_t offered)
5359 {
5360         NTSTATUS status;
5361         struct spoolss_SetPrinterDataEx r;
5362
5363         r.in.handle = handle;
5364         r.in.key_name = key_name;
5365         r.in.value_name = value_name;
5366         r.in.type = type;
5367         r.in.data = data;
5368         r.in.offered = offered;
5369
5370         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5371                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5372
5373         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5374
5375         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5376         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5377
5378         return true;
5379 }
5380
5381 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5382                                        struct dcerpc_pipe *p,
5383                                        struct policy_handle *handle)
5384 {
5385         struct dcerpc_binding_handle *b = p->binding_handle;
5386         const char *value_name = "dog";
5387         const char *keys[] = {
5388                 "torturedataex",
5389                 "torture data ex",
5390                 "torturedataex_with_subkey\\subkey",
5391                 "torturedataex_with_subkey\\subkey:0",
5392                 "torturedataex_with_subkey\\subkey:1",
5393                 "torturedataex_with_subkey\\subkey\\subsubkey",
5394                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5395                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5396                 "torture,data",
5397                 "torture,data,ex",
5398                 "torture,data\\ex",
5399                 "torture\\data,ex",
5400                 "torture/data",
5401                 "torture/data ex",
5402                 "torture/data ex/sub",
5403                 "torture//data",
5404                 "torture//data ex",
5405                 "torture//data ex/sub",
5406                 "torture//data ex//sub",
5407         };
5408         int i;
5409
5410         for (i=0; i < ARRAY_SIZE(keys); i++) {
5411
5412                 char *c;
5413                 const char *key;
5414                 enum winreg_Type type;
5415                 DATA_BLOB blob_in, blob_out;
5416                 const char **subkeys;
5417                 uint32_t ecount;
5418                 struct spoolss_PrinterEnumValues *einfo;
5419                 uint32_t needed;
5420
5421                 blob_in = data_blob_talloc(tctx, NULL, 42);
5422
5423                 generate_random_buffer(blob_in.data, blob_in.length);
5424
5425                 torture_assert(tctx,
5426                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5427                         "failed to call SetPrinterDataEx");
5428
5429                 torture_assert(tctx,
5430                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5431                         "failed to call GetPrinterDataEx");
5432
5433                 blob_out.length = needed;
5434                 torture_assert(tctx,
5435                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5436                         "failed to call EnumPrinterDataEx");
5437
5438                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5439                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5440                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5441
5442                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5443                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5444                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5445                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5446                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5447                 if (einfo[0].data_length > 0) {
5448                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5449                 }
5450
5451                 key = talloc_strdup(tctx, keys[i]);
5452
5453                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5454                         return false;
5455                 }
5456
5457                 c = strchr(key, '\\');
5458                 if (c) {
5459                         int k;
5460
5461                         /* we have subkeys */
5462
5463                         *c = 0;
5464
5465                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5466                                 return false;
5467                         }
5468
5469                         for (k=0; subkeys && subkeys[k]; k++) {
5470
5471                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5472
5473                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5474                                         return false;
5475                                 }
5476                         }
5477
5478                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5479                                 return false;
5480                         }
5481
5482                 } else {
5483                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5484                                 return false;
5485                         }
5486                 }
5487         }
5488
5489         return true;
5490 }
5491
5492 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5493                                          struct dcerpc_pipe *p,
5494                                          struct policy_handle *handle)
5495 {
5496         struct dcerpc_binding_handle *b = p->binding_handle;
5497         const char *key = "torturedataex";
5498         const char *values[] = {
5499                 "torture_value",
5500                 "torture value",
5501                 "torture,value",
5502                 "torture/value",
5503                 "torture\\value",
5504                 "torture\\\\value"
5505         };
5506         int i;
5507
5508         for (i=0; i < ARRAY_SIZE(values); i++) {
5509
5510                 enum winreg_Type type;
5511                 DATA_BLOB blob_in, blob_out;
5512                 uint32_t ecount;
5513                 struct spoolss_PrinterEnumValues *einfo;
5514                 uint32_t needed;
5515
5516                 if (torture_setting_bool(tctx, "samba3", false)) {
5517                         char *q;
5518                         q = strrchr(values[i], ',');
5519                         if (q) {
5520                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5521                                                 values[i]);
5522                                 continue;
5523                         }
5524                 }
5525
5526                 blob_in = data_blob_talloc(tctx, NULL, 42);
5527
5528                 generate_random_buffer(blob_in.data, blob_in.length);
5529
5530                 torture_assert(tctx,
5531                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5532                         "failed to call SetPrinterDataEx");
5533
5534                 torture_assert(tctx,
5535                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5536                         "failed to call GetPrinterDataEx");
5537
5538                 blob_out.length = needed;
5539                 torture_assert(tctx,
5540                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5541                         "failed to call EnumPrinterDataEx");
5542
5543                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5544                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5545                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5546
5547                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5548                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5549                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5550                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5551                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5552                 if (einfo[0].data_length > 0) {
5553                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5554                 }
5555
5556                 torture_assert(tctx,
5557                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5558                         "failed to call DeletePrinterDataEx");
5559         }
5560
5561         return true;
5562 }
5563
5564
5565 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5566                                          struct dcerpc_pipe *p,
5567                                          struct policy_handle *handle,
5568                                          const char *printername,
5569                                          struct dcerpc_binding_handle *winreg_handle,
5570                                          struct policy_handle *hive_handle)
5571 {
5572         struct dcerpc_binding_handle *b = p->binding_handle;
5573         const char *value_name = "dog";
5574         const char *key_name = "torturedataex";
5575         enum winreg_Type types[] = {
5576                 REG_SZ,
5577                 REG_MULTI_SZ,
5578                 REG_DWORD,
5579                 REG_BINARY
5580         };
5581         const char *str = "abcdefghi";
5582         int t, s;
5583
5584         for (t=0; t < ARRAY_SIZE(types); t++) {
5585         for (s=0; s < strlen(str); s++) {
5586
5587                 enum winreg_Type type;
5588                 const char *string = talloc_strndup(tctx, str, s);
5589                 const char *array[2];
5590                 DATA_BLOB blob = data_blob_string_const(string);
5591                 DATA_BLOB data;
5592                 uint8_t *data_out;
5593                 uint32_t needed, offered = 0;
5594                 uint32_t ecount;
5595                 struct spoolss_PrinterEnumValues *einfo;
5596
5597                 array[0] = talloc_strdup(tctx, string);
5598                 array[1] = NULL;
5599
5600                 if (types[t] == REG_DWORD) {
5601                         s = 0xffff;
5602                 }
5603
5604                 switch (types[t]) {
5605                 case REG_BINARY:
5606                         data = blob;
5607                         offered = blob.length;
5608                         break;
5609                 case REG_DWORD:
5610                         data = data_blob_talloc(tctx, NULL, 4);
5611                         SIVAL(data.data, 0, 0x12345678);
5612                         offered = 4;
5613                         break;
5614                 case REG_SZ:
5615                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5616                         type = REG_SZ;
5617                         offered = data.length;
5618                         /*strlen_m_term(data.string)*2;*/
5619                         break;
5620                 case REG_MULTI_SZ:
5621                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5622                         type = REG_MULTI_SZ;
5623                         offered = data.length;
5624                         break;
5625                 default:
5626                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5627                 }
5628
5629                 torture_assert(tctx,
5630                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5631                         "failed to call SetPrinterDataEx");
5632
5633                 torture_assert(tctx,
5634                         test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5635                         "failed to call GetPrinterDataEx");
5636
5637                 torture_assert(tctx,
5638                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5639                         "failed to call EnumPrinterDataEx");
5640
5641                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5642                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5643                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5644
5645                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5646                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5647                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5648                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5649                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5650                 if (einfo[0].data_length > 0) {
5651                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5652                 }
5653
5654                 if (winreg_handle && hive_handle) {
5655                         enum winreg_Type w_type;
5656                         uint32_t w_size;
5657                         uint32_t w_length;
5658                         uint8_t *w_data;
5659
5660                         torture_assert(tctx,
5661                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5662                                         printername, key_name, value_name,
5663                                         &w_type, &w_size, &w_length, &w_data), "");
5664
5665                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5666                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5667                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5668                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5669                 }
5670
5671                 torture_assert(tctx,
5672                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5673                         "failed to call DeletePrinterDataEx");
5674         }
5675         }
5676
5677         return true;
5678 }
5679
5680 static bool test_PrinterData_winreg(struct torture_context *tctx,
5681                                     struct dcerpc_pipe *p,
5682                                     struct policy_handle *handle,
5683                                     const char *printer_name)
5684 {
5685         struct dcerpc_binding_handle *b = p->binding_handle;
5686         struct dcerpc_pipe *p2;
5687         bool ret = true;
5688         struct policy_handle hive_handle;
5689         struct dcerpc_binding_handle *b2;
5690
5691         torture_assert_ntstatus_ok(tctx,
5692                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5693                 "could not open winreg pipe");
5694         b2 = p2->binding_handle;
5695
5696         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5697
5698         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5699         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5700
5701         test_winreg_CloseKey(tctx, b2, &hive_handle);
5702
5703         talloc_free(p2);
5704
5705         return ret;
5706 }
5707
5708 static bool test_Forms_winreg(struct torture_context *tctx,
5709                               struct dcerpc_binding_handle *b,
5710                               struct policy_handle *handle,
5711                               bool print_server,
5712                               const char *printer_name)
5713 {
5714         struct dcerpc_pipe *p2;
5715         bool ret = true;
5716         struct policy_handle hive_handle;
5717         struct dcerpc_binding_handle *b2;
5718
5719         torture_assert_ntstatus_ok(tctx,
5720                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5721                 "could not open winreg pipe");
5722         b2 = p2->binding_handle;
5723
5724         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5725
5726         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5727
5728         test_winreg_CloseKey(tctx, b2, &hive_handle);
5729
5730         talloc_free(p2);
5731
5732         return ret;
5733 }
5734
5735 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5736                                     struct dcerpc_pipe *p,
5737                                     struct policy_handle *handle,
5738                                     const char *printer_name)
5739 {
5740         struct dcerpc_binding_handle *b = p->binding_handle;
5741         struct dcerpc_pipe *p2;
5742         bool ret = true;
5743         struct policy_handle hive_handle;
5744         struct dcerpc_binding_handle *b2;
5745
5746         torture_assert_ntstatus_ok(tctx,
5747                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5748                 "could not open winreg pipe");
5749         b2 = p2->binding_handle;
5750
5751         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5752
5753         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5754
5755         test_winreg_CloseKey(tctx, b2, &hive_handle);
5756
5757         talloc_free(p2);
5758
5759         return ret;
5760 }
5761
5762 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5763                                    struct dcerpc_pipe *p,
5764                                    struct policy_handle *handle,
5765                                    const char *printer_name,
5766                                    const char *driver_name,
5767                                    const char *environment,
5768                                    enum spoolss_DriverOSVersion version)
5769 {
5770         struct dcerpc_binding_handle *b = p->binding_handle;
5771         struct dcerpc_pipe *p2;
5772         bool ret = true;
5773         struct policy_handle hive_handle;
5774         struct dcerpc_binding_handle *b2;
5775
5776         torture_assert_ntstatus_ok(tctx,
5777                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5778                 "could not open winreg pipe");
5779         b2 = p2->binding_handle;
5780
5781         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5782
5783         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5784
5785         test_winreg_CloseKey(tctx, b2, &hive_handle);
5786
5787         talloc_free(p2);
5788
5789         return ret;
5790 }
5791
5792 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5793                                         struct dcerpc_binding_handle *b,
5794                                         const char *environment)
5795 {
5796         struct dcerpc_pipe *p2;
5797         bool ret = true;
5798         struct policy_handle hive_handle;
5799         struct dcerpc_binding_handle *b2;
5800
5801         torture_assert_ntstatus_ok(tctx,
5802                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5803                 "could not open winreg pipe");
5804         b2 = p2->binding_handle;
5805
5806         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5807
5808         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5809
5810         test_winreg_CloseKey(tctx, b2, &hive_handle);
5811
5812         talloc_free(p2);
5813
5814         return ret;
5815 }
5816
5817 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5818                                        struct dcerpc_pipe *p,
5819                                        struct policy_handle *handle,
5820                                        const char *printer_name)
5821 {
5822         struct spoolss_SetPrinterInfoCtr info_ctr;
5823         struct spoolss_DevmodeContainer devmode_ctr;
5824         struct sec_desc_buf secdesc_ctr;
5825         union spoolss_SetPrinterInfo sinfo;
5826         union spoolss_PrinterInfo info;
5827         struct dcerpc_binding_handle *b = p->binding_handle;
5828         const char *pname;
5829
5830         ZERO_STRUCT(info_ctr);
5831         ZERO_STRUCT(devmode_ctr);
5832         ZERO_STRUCT(secdesc_ctr);
5833
5834         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5835
5836         torture_assert(tctx,
5837                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5838                 "failed to query Printer level 2");
5839
5840         torture_assert(tctx,
5841                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5842                 "failed to convert");
5843
5844         info_ctr.level = 2;
5845         info_ctr.info = sinfo;
5846
5847 #define TEST_SZ(wname, iname) \
5848 do {\
5849         enum winreg_Type type;\
5850         uint8_t *data;\
5851         uint32_t needed;\
5852         DATA_BLOB blob;\
5853         const char *str;\
5854         torture_assert(tctx,\
5855                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5856                 "failed to query");\
5857         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5858         blob = data_blob_const(data, needed);\
5859         torture_assert(tctx,\
5860                 pull_reg_sz(tctx, &blob, &str),\
5861                 "failed to pull REG_SZ");\
5862         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5863 } while(0);
5864
5865
5866 #define TEST_SET_SZ(wname, iname, val) \
5867 do {\
5868         enum winreg_Type type;\
5869         uint8_t *data;\
5870         uint32_t needed;\
5871         DATA_BLOB blob;\
5872         const char *str;\
5873         sinfo.info2->iname = val;\
5874         torture_assert(tctx,\
5875                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5876                 "failed to call SetPrinter");\
5877         torture_assert(tctx,\
5878                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5879                 "failed to query");\
5880         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5881         blob = data_blob_const(data, needed);\
5882         torture_assert(tctx,\
5883                 pull_reg_sz(tctx, &blob, &str),\
5884                 "failed to pull REG_SZ");\
5885         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5886 } while(0);
5887
5888 #define TEST_SET_DWORD(wname, iname, val) \
5889 do {\
5890         enum winreg_Type type;\
5891         uint8_t *data;\
5892         uint32_t needed;\
5893         uint32_t value;\
5894         sinfo.info2->iname = val;\
5895         torture_assert(tctx,\
5896                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5897                 "failed to call SetPrinter");\
5898         torture_assert(tctx,\
5899                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5900                 "failed to query");\
5901         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5902         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5903         value = IVAL(data, 0); \
5904         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5905 } while(0);
5906
5907         TEST_SET_SZ("description", comment, "newval");
5908         TEST_SET_SZ("location", location, "newval");
5909         TEST_SET_SZ("driverName", drivername, "newval");
5910 /*      TEST_SET_DWORD("priority", priority, 25); */
5911
5912         torture_assert(tctx,
5913                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5914                 "failed to query Printer level 2");
5915
5916         TEST_SZ("description", info.info2.comment);
5917         TEST_SZ("driverName", info.info2.drivername);
5918         TEST_SZ("location", info.info2.location);
5919
5920         pname = strrchr(info.info2.printername, '\\');
5921         if (pname == NULL) {
5922                 pname = info.info2.printername;
5923         } else {
5924                 pname++;
5925         }
5926         TEST_SZ("printerName", pname);
5927         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5928         /* TEST_SZ("printShareName", info.info2.sharename); */
5929
5930         /* FIXME gd: complete the list */
5931
5932 #undef TEST_SZ
5933 #undef TEST_SET_SZ
5934 #undef TEST_DWORD
5935
5936         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5937
5938         return true;
5939 }
5940
5941 static bool test_print_processors_winreg(struct torture_context *tctx,
5942                                          void *private_data)
5943 {
5944         struct test_spoolss_context *ctx =
5945                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5946         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5947         struct dcerpc_binding_handle *b = p->binding_handle;
5948
5949         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5950 }
5951
5952 static bool test_AddPrintProcessor(struct torture_context *tctx,
5953                                    struct dcerpc_binding_handle *b,
5954                                    const char *environment,
5955                                    const char *path_name,
5956                                    const char *print_processor_name,
5957                                    WERROR expected_error)
5958 {
5959         struct spoolss_AddPrintProcessor r;
5960
5961         r.in.server = NULL;
5962         r.in.architecture = environment;
5963         r.in.path_name = path_name;
5964         r.in.print_processor_name = print_processor_name;
5965
5966         torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5967                 print_processor_name);
5968
5969         torture_assert_ntstatus_ok(tctx,
5970                 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5971                 "spoolss_AddPrintProcessor failed");
5972         torture_assert_werr_equal(tctx, r.out.result, expected_error,
5973                 "spoolss_AddPrintProcessor failed");
5974
5975         return true;
5976 }
5977
5978 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5979                                       struct dcerpc_binding_handle *b,
5980                                       const char *environment,
5981                                       const char *print_processor_name,
5982                                       WERROR expected_error)
5983 {
5984         struct spoolss_DeletePrintProcessor r;
5985
5986         r.in.server = NULL;
5987         r.in.architecture = environment;
5988         r.in.print_processor_name = print_processor_name;
5989
5990         torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5991                 print_processor_name);
5992
5993         torture_assert_ntstatus_ok(tctx,
5994                 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5995                 "spoolss_DeletePrintProcessor failed");
5996         torture_assert_werr_equal(tctx, r.out.result, expected_error,
5997                 "spoolss_DeletePrintProcessor failed");
5998
5999         return true;
6000 }
6001
6002 static bool test_add_print_processor(struct torture_context *tctx,
6003                                      void *private_data)
6004 {
6005         struct test_spoolss_context *ctx =
6006                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6007         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6008         struct dcerpc_binding_handle *b = p->binding_handle;
6009         int i;
6010
6011         struct {
6012                 const char *environment;
6013                 const char *path_name;
6014                 const char *print_processor_name;
6015                 WERROR expected_add_result;
6016                 WERROR expected_del_result;
6017         } tests[] = {
6018                 {
6019                         .environment            = ctx->environment,
6020                         .path_name              = "",
6021                         .print_processor_name   = "winprint",
6022                         .expected_add_result    = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
6023                         .expected_del_result    = WERR_CAN_NOT_COMPLETE
6024                 },{
6025                         .environment            = ctx->environment,
6026                         .path_name              = "",
6027                         .print_processor_name   = "unknown",
6028                         .expected_add_result    = WERR_MOD_NOT_FOUND,
6029                         .expected_del_result    = WERR_UNKNOWN_PRINTPROCESSOR
6030                 }
6031         };
6032
6033         for (i=0; i < ARRAY_SIZE(tests); i++) {
6034                 torture_assert(tctx,
6035                         test_AddPrintProcessor(tctx, b,
6036                                                tests[i].environment,
6037                                                tests[i].path_name,
6038                                                tests[i].print_processor_name,
6039                                                tests[i].expected_add_result),
6040                         "add print processor failed");
6041                 torture_assert(tctx,
6042                         test_DeletePrintProcessor(tctx, b,
6043                                                   tests[i].environment,
6044                                                   tests[i].print_processor_name,
6045                                                   tests[i].expected_del_result),
6046                         "delete print processor failed");
6047         }
6048
6049         return true;
6050 }
6051
6052 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
6053                                          struct dcerpc_binding_handle *b,
6054                                          struct policy_handle *handle,
6055                                          uint32_t *change_id)
6056 {
6057         enum winreg_Type type;
6058         uint8_t *data;
6059         uint32_t needed;
6060
6061         torture_assert(tctx,
6062                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
6063                 "failed to call GetPrinterData");
6064
6065         torture_assert(tctx, type == REG_DWORD, "unexpected type");
6066         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6067
6068         *change_id = IVAL(data, 0);
6069
6070         return true;
6071 }
6072
6073 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
6074                                            struct dcerpc_pipe *p,
6075                                            struct policy_handle *handle,
6076                                            uint32_t *change_id)
6077 {
6078         enum winreg_Type type = REG_NONE;
6079         uint8_t *data = NULL;
6080         uint32_t needed = 0;
6081
6082         torture_assert(tctx,
6083                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
6084                 "failed to call GetPrinterData");
6085
6086         torture_assert(tctx, type == REG_DWORD, "unexpected type");
6087         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6088
6089         *change_id = IVAL(data, 0);
6090
6091         return true;
6092 }
6093
6094 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6095                                          struct dcerpc_binding_handle *b,
6096                                          struct policy_handle *handle,
6097                                          uint32_t *change_id)
6098 {
6099         union spoolss_PrinterInfo info;
6100
6101         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6102                 "failed to query Printer level 0");
6103
6104         *change_id = info.info0.change_id;
6105
6106         return true;
6107 }
6108
6109 static bool test_ChangeID(struct torture_context *tctx,
6110                           struct dcerpc_pipe *p,
6111                           struct policy_handle *handle)
6112 {
6113         uint32_t change_id, change_id_ex, change_id_info;
6114         uint32_t change_id2, change_id_ex2, change_id_info2;
6115         union spoolss_PrinterInfo info;
6116         const char *comment;
6117         struct dcerpc_binding_handle *b = p->binding_handle;
6118
6119         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6120
6121         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6122                 "failed to query for ChangeID");
6123         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6124                 "failed to query for ChangeID");
6125         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6126                 "failed to query for ChangeID");
6127
6128         torture_assert_int_equal(tctx, change_id, change_id_ex,
6129                 "change_ids should all be equal");
6130         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6131                 "change_ids should all be equal");
6132
6133
6134         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6135
6136         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6137                 "failed to query for ChangeID");
6138         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6139                 "failed to query Printer level 2");
6140         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6141                 "failed to query for ChangeID");
6142         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6143                 "failed to query for ChangeID");
6144         torture_assert_int_equal(tctx, change_id, change_id_ex,
6145                 "change_id should not have changed");
6146         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6147                 "change_id should not have changed");
6148
6149
6150         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6151
6152         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6153                 "failed to query for ChangeID");
6154         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6155                 "failed to query for ChangeID");
6156         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6157                 "failed to query for ChangeID");
6158         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6159                 "failed to query Printer level 2");
6160         comment = talloc_strdup(tctx, info.info2.comment);
6161
6162         {
6163                 struct spoolss_SetPrinterInfoCtr info_ctr;
6164                 struct spoolss_DevmodeContainer devmode_ctr;
6165                 struct sec_desc_buf secdesc_ctr;
6166                 union spoolss_SetPrinterInfo sinfo;
6167
6168                 ZERO_STRUCT(info_ctr);
6169                 ZERO_STRUCT(devmode_ctr);
6170                 ZERO_STRUCT(secdesc_ctr);
6171
6172
6173                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6174                 sinfo.info2->comment    = "torture_comment";
6175
6176                 info_ctr.level = 2;
6177                 info_ctr.info = sinfo;
6178
6179                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6180                         "failed to call SetPrinter");
6181
6182                 sinfo.info2->comment    = comment;
6183
6184                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6185                         "failed to call SetPrinter");
6186
6187         }
6188
6189         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6190                 "failed to query for ChangeID");
6191         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6192                 "failed to query for ChangeID");
6193         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6194                 "failed to query for ChangeID");
6195
6196         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6197                 "change_ids should all be equal");
6198         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6199                 "change_ids should all be equal");
6200
6201         torture_assert(tctx, (change_id < change_id2),
6202                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6203                 change_id2, change_id));
6204         torture_assert(tctx, (change_id_ex < change_id_ex2),
6205                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6206                 change_id_ex2, change_id_ex));
6207         torture_assert(tctx, (change_id_info < change_id_info2),
6208                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6209                 change_id_info2, change_id_info));
6210
6211         torture_comment(tctx, "ChangeID tests succeeded\n\n");
6212
6213         return true;
6214 }
6215
6216 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6217                                        struct dcerpc_pipe *p,
6218                                        struct policy_handle *handle)
6219 {
6220         NTSTATUS status;
6221         struct cli_credentials *anon_creds;
6222         const struct dcerpc_binding *binding2;
6223         struct dcerpc_pipe *p2;
6224         struct spoolss_ClosePrinter cp;
6225
6226         /* only makes sense on SMB */
6227         if (p->conn->transport.transport != NCACN_NP) {
6228                 return true;
6229         }
6230
6231         torture_comment(tctx, "Testing close on secondary pipe\n");
6232
6233         anon_creds = cli_credentials_init_anon(tctx);
6234         torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
6235
6236         binding2 = p->binding;
6237         status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_spoolss,
6238                                                   anon_creds, tctx->lp_ctx,
6239                                                   tctx, &p2);
6240         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6241
6242         cp.in.handle = handle;
6243         cp.out.handle = handle;
6244
6245         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6246         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6247                         "ERROR: Allowed close on secondary connection");
6248
6249         talloc_free(p2);
6250
6251         return true;
6252 }
6253
6254 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6255                                      struct dcerpc_binding_handle *b, const char *name)
6256 {
6257         NTSTATUS status;
6258         struct spoolss_OpenPrinter op;
6259         struct spoolss_OpenPrinterEx opEx;
6260         struct policy_handle handle;
6261         bool ret = true;
6262
6263         op.in.printername       = name;
6264         op.in.datatype          = NULL;
6265         op.in.devmode_ctr.devmode= NULL;
6266         op.in.access_mask       = 0;
6267         op.out.handle           = &handle;
6268
6269         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6270
6271         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6272         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6273         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6274                 "unexpected result");
6275
6276         if (W_ERROR_IS_OK(op.out.result)) {
6277                 ret &=test_ClosePrinter(tctx, b, &handle);
6278         }
6279
6280         opEx.in.printername             = name;
6281         opEx.in.datatype                = NULL;
6282         opEx.in.devmode_ctr.devmode     = NULL;
6283         opEx.in.access_mask             = 0;
6284         opEx.in.userlevel_ctr.level             = 1;
6285         opEx.in.userlevel_ctr.user_info.level1 = NULL;
6286         opEx.out.handle                 = &handle;
6287
6288         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6289
6290         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6291         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6292         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6293                 "unexpected result");
6294
6295         if (W_ERROR_IS_OK(opEx.out.result)) {
6296                 ret &=test_ClosePrinter(tctx, b, &handle);
6297         }
6298
6299         return ret;
6300 }
6301
6302 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6303                                           void *private_data)
6304 {
6305         struct test_spoolss_context *ctx =
6306                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6307
6308         const char *badnames[] = {
6309                 "__INVALID_PRINTER__",
6310                 "\\\\__INVALID_HOST__",
6311                 "",
6312                 "\\\\\\",
6313                 "\\\\\\__INVALID_PRINTER__"
6314         };
6315         const char *badname;
6316         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6317         const char *server_name = dcerpc_server_name(p);
6318         struct dcerpc_binding_handle *b = p->binding_handle;
6319         int i;
6320
6321         for (i=0; i < ARRAY_SIZE(badnames); i++) {
6322                 torture_assert(tctx,
6323                         test_OpenPrinter_badname(tctx, b, badnames[i]),
6324                         "");
6325         }
6326
6327         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6328         torture_assert(tctx,
6329                 test_OpenPrinter_badname(tctx, b, badname),
6330                 "");
6331
6332         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6333         torture_assert(tctx,
6334                 test_OpenPrinter_badname(tctx, b, badname),
6335                 "");
6336
6337         return true;
6338 }
6339
6340 static bool test_OpenPrinter(struct torture_context *tctx,
6341                              struct dcerpc_pipe *p,
6342                              const char *name,
6343                              const char *environment,
6344                              bool open_only)
6345 {
6346         NTSTATUS status;
6347         struct spoolss_OpenPrinter r;
6348         struct policy_handle handle;
6349         bool ret = true;
6350         struct dcerpc_binding_handle *b = p->binding_handle;
6351
6352         r.in.printername        = name;
6353         r.in.datatype           = NULL;
6354         r.in.devmode_ctr.devmode= NULL;
6355         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6356         r.out.handle            = &handle;
6357
6358         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6359
6360         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6361
6362         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6363
6364         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6365
6366         if (open_only) {
6367                 goto close_printer;
6368         }
6369
6370         if (!test_GetPrinter(tctx, b, &handle, environment)) {
6371                 ret = false;
6372         }
6373
6374         if (!torture_setting_bool(tctx, "samba3", false)) {
6375                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6376                         ret = false;
6377                 }
6378         }
6379
6380  close_printer:
6381         if (!test_ClosePrinter(tctx, b, &handle)) {
6382                 ret = false;
6383         }
6384
6385         return ret;
6386 }
6387
6388 static bool test_OpenPrinterEx(struct torture_context *tctx,
6389                                struct dcerpc_binding_handle *b,
6390                                const char *printername,
6391                                const char *datatype,
6392                                struct spoolss_DeviceMode *devmode,
6393                                uint32_t access_mask,
6394                                struct spoolss_UserLevelCtr *userlevel_ctr,
6395                                struct policy_handle *handle,
6396                                WERROR expected_result)
6397 {
6398         struct spoolss_OpenPrinterEx r;
6399
6400         r.in.printername        = printername;
6401         r.in.datatype           = datatype;
6402         r.in.devmode_ctr.devmode= devmode;
6403         r.in.access_mask        = access_mask;
6404         r.in.userlevel_ctr      = *userlevel_ctr;
6405         r.out.handle            = handle;
6406
6407         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6408
6409         torture_assert_ntstatus_ok(tctx,
6410                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6411                 "OpenPrinterEx failed");
6412
6413         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6414                 "OpenPrinterEx failed");
6415
6416         return true;
6417 }
6418
6419 static bool call_OpenPrinterEx(struct torture_context *tctx,
6420                                struct dcerpc_pipe *p,
6421                                const char *name,
6422                                struct spoolss_DeviceMode *devmode,
6423                                struct policy_handle *handle)
6424 {
6425         struct spoolss_UserLevelCtr userlevel_ctr;
6426         struct spoolss_UserLevel1 userlevel1;
6427         struct dcerpc_binding_handle *b = p->binding_handle;
6428
6429         userlevel1.size = 1234;
6430         userlevel1.client = "hello";
6431         userlevel1.user = "spottyfoot!";
6432         userlevel1.build = 1;
6433         userlevel1.major = 2;
6434         userlevel1.minor = 3;
6435         userlevel1.processor = 4;
6436
6437         userlevel_ctr.level = 1;
6438         userlevel_ctr.user_info.level1 = &userlevel1;
6439
6440         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6441                                   SEC_FLAG_MAXIMUM_ALLOWED,
6442                                   &userlevel_ctr,
6443                                   handle,
6444                                   WERR_OK);
6445 }
6446
6447 static bool test_printer_rename(struct torture_context *tctx,
6448                                 void *private_data)
6449 {
6450         struct torture_printer_context *t =
6451                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6452         struct dcerpc_pipe *p = t->spoolss_pipe;
6453
6454         bool ret = true;
6455         union spoolss_PrinterInfo info;
6456         union spoolss_SetPrinterInfo sinfo;
6457         struct spoolss_SetPrinterInfoCtr info_ctr;
6458         struct spoolss_DevmodeContainer devmode_ctr;
6459         struct sec_desc_buf secdesc_ctr;
6460         const char *printer_name;
6461         const char *printer_name_orig;
6462         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6463         struct policy_handle new_handle;
6464         const char *q;
6465         struct dcerpc_binding_handle *b = p->binding_handle;
6466
6467         ZERO_STRUCT(devmode_ctr);
6468         ZERO_STRUCT(secdesc_ctr);
6469
6470         torture_comment(tctx, "Testing Printer rename operations\n");
6471
6472         torture_assert(tctx,
6473                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6474                 "failed to call GetPrinter level 2");
6475
6476         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6477
6478         q = strrchr(info.info2.printername, '\\');
6479         if (q) {
6480                 torture_warning(tctx,
6481                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6482         }
6483
6484         torture_assert(tctx,
6485                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6486
6487         sinfo.info2->printername = printer_name_new;
6488
6489         info_ctr.level = 2;
6490         info_ctr.info = sinfo;
6491
6492         torture_assert(tctx,
6493                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6494                 "failed to call SetPrinter level 2");
6495
6496         torture_assert(tctx,
6497                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6498                 "failed to call GetPrinter level 2");
6499
6500         printer_name = talloc_strdup(tctx, info.info2.printername);
6501
6502         q = strrchr(info.info2.printername, '\\');
6503         if (q) {
6504                 torture_warning(tctx,
6505                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6506                 q++;
6507                 printer_name = q;
6508         }
6509
6510         torture_assert_str_equal(tctx, printer_name, printer_name_new,
6511                 "new printer name was not set");
6512
6513         /* samba currently cannot fully rename printers */
6514         if (!torture_setting_bool(tctx, "samba3", false)) {
6515                 torture_assert(tctx,
6516                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
6517                         "still can open printer with oldname after rename");
6518         } else {
6519                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6520         }
6521
6522         torture_assert(tctx,
6523                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6524                 "failed to open printer with new name");
6525
6526         torture_assert(tctx,
6527                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6528                 "failed to call GetPrinter level 2");
6529
6530         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6531                 "new printer name was not set");
6532
6533         torture_assert(tctx,
6534                 test_ClosePrinter(tctx, b, &new_handle),
6535                 "failed to close printer");
6536
6537         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6538
6539         return ret;
6540 }
6541
6542 static bool test_openprinter(struct torture_context *tctx,
6543                              struct dcerpc_binding_handle *b,
6544                              const char *real_printername)
6545 {
6546         struct spoolss_UserLevelCtr userlevel_ctr;
6547         struct policy_handle handle;
6548         struct spoolss_UserLevel1 userlevel1;
6549         const char *printername = NULL;
6550         int i;
6551
6552         struct {
6553                 const char *suffix;
6554                 WERROR expected_result;
6555         } tests[] = {
6556                 {
6557                         .suffix                 = "rubbish",
6558                         .expected_result        = WERR_INVALID_PRINTER_NAME
6559                 },{
6560                         .suffix                 = ", LocalOnl",
6561                         .expected_result        = WERR_INVALID_PRINTER_NAME
6562                 },{
6563                         .suffix                 = ", localOnly",
6564                         .expected_result        = WERR_INVALID_PRINTER_NAME
6565                 },{
6566                         .suffix                 = ", localonl",
6567                         .expected_result        = WERR_INVALID_PRINTER_NAME
6568                 },{
6569                         .suffix                 = ",LocalOnl",
6570                         .expected_result        = WERR_INVALID_PRINTER_NAME
6571                 },{
6572                         .suffix                 = ",localOnl2",
6573                         .expected_result        = WERR_INVALID_PRINTER_NAME
6574                 },{
6575                         .suffix                 = ", DrvConver2t",
6576                         .expected_result        = WERR_INVALID_PRINTER_NAME
6577                 },{
6578                         .suffix                 = ", drvconvert",
6579                         .expected_result        = WERR_INVALID_PRINTER_NAME
6580                 },{
6581                         .suffix                 = ",drvconvert",
6582                         .expected_result        = WERR_INVALID_PRINTER_NAME
6583                 },{
6584                         .suffix                 = ", DrvConvert",
6585                         .expected_result        = WERR_OK
6586                 },{
6587                         .suffix                 = " , DrvConvert",
6588                         .expected_result        = WERR_INVALID_PRINTER_NAME
6589                 },{
6590                         .suffix                 = ",DrvConvert",
6591                         .expected_result        = WERR_OK
6592                 },{
6593                         .suffix                 = ", DrvConvertsadfasdf",
6594                         .expected_result        = WERR_OK
6595                 },{
6596                         .suffix                 = ",DrvConvertasdfasd",
6597                         .expected_result        = WERR_OK
6598                 },{
6599                         .suffix                 = ", LocalOnly",
6600                         .expected_result        = WERR_OK
6601                 },{
6602                         .suffix                 = " , LocalOnly",
6603                         .expected_result        = WERR_INVALID_PRINTER_NAME
6604                 },{
6605                         .suffix                 = ",LocalOnly",
6606                         .expected_result        = WERR_OK
6607                 },{
6608                         .suffix                 = ", LocalOnlysagi4gjfkd",
6609                         .expected_result        = WERR_OK
6610                 },{
6611                         .suffix                 = ",LocalOnlysagi4gjfkd",
6612                         .expected_result        = WERR_OK
6613                 }
6614         };
6615
6616         userlevel1.size = 1234;
6617         userlevel1.client = "hello";
6618         userlevel1.user = "spottyfoot!";
6619         userlevel1.build = 1;
6620         userlevel1.major = 2;
6621         userlevel1.minor = 3;
6622         userlevel1.processor = 4;
6623
6624         userlevel_ctr.level = 1;
6625         userlevel_ctr.user_info.level1 = &userlevel1;
6626
6627         torture_comment(tctx, "Testing openprinterex printername pattern\n");
6628
6629         torture_assert(tctx,
6630                 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6631                                    &userlevel_ctr, &handle,
6632                                    WERR_OK),
6633                 "OpenPrinterEx failed");
6634         test_ClosePrinter(tctx, b, &handle);
6635
6636         for (i=0; i < ARRAY_SIZE(tests); i++) {
6637
6638                 printername = talloc_asprintf(tctx, "%s%s",
6639                                               real_printername,
6640                                               tests[i].suffix);
6641
6642                 torture_assert(tctx,
6643                         test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6644                                            &userlevel_ctr, &handle,
6645                                            tests[i].expected_result),
6646                         "OpenPrinterEx failed");
6647                 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6648                         test_ClosePrinter(tctx, b, &handle);
6649                 }
6650         }
6651
6652         return true;
6653 }
6654
6655
6656 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6657                                                 struct dcerpc_pipe *p,
6658                                                 const char *name,
6659                                                 const char *environment)
6660 {
6661         struct policy_handle handle;
6662         bool ret = true;
6663         struct dcerpc_binding_handle *b = p->binding_handle;
6664
6665         if (!test_openprinter(tctx, b, name)) {
6666                 return false;
6667         }
6668
6669         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6670                 return false;
6671         }
6672
6673         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6674                 ret = false;
6675         }
6676
6677         if (!test_GetPrinter(tctx, b, &handle, environment)) {
6678                 ret = false;
6679         }
6680
6681         if (!test_EnumForms_all(tctx, b, &handle, false)) {
6682                 ret = false;
6683         }
6684
6685         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6686                 ret = false;
6687         }
6688
6689         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6690                 ret = false;
6691         }
6692
6693         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6694                 ret = false;
6695         }
6696
6697         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6698                 ret = false;
6699         }
6700
6701         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6702                 ret = false;
6703         }
6704
6705         if (!test_printer_all_keys(tctx, b, &handle)) {
6706                 ret = false;
6707         }
6708
6709         if (!test_PausePrinter(tctx, b, &handle)) {
6710                 ret = false;
6711         }
6712
6713         if (!test_DoPrintTest(tctx, b, &handle)) {
6714                 ret = false;
6715         }
6716
6717         if (!test_ResumePrinter(tctx, b, &handle)) {
6718                 ret = false;
6719         }
6720
6721         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6722                 ret = false;
6723         }
6724
6725         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6726                 ret = false;
6727         }
6728
6729         if (!torture_setting_bool(tctx, "samba3", false)) {
6730                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6731                         ret = false;
6732                 }
6733         }
6734
6735         if (!test_ClosePrinter(tctx, b, &handle)) {
6736                 ret = false;
6737         }
6738
6739         return ret;
6740 }
6741
6742 static bool test_EnumPrinters_old(struct torture_context *tctx,
6743                                   void *private_data)
6744 {
6745         struct test_spoolss_context *ctx =
6746                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6747         struct spoolss_EnumPrinters r;
6748         NTSTATUS status;
6749         uint16_t levels[] = {1, 2, 4, 5};
6750         int i;
6751         bool ret = true;
6752         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6753         struct dcerpc_binding_handle *b = p->binding_handle;
6754
6755         for (i=0;i<ARRAY_SIZE(levels);i++) {
6756                 union spoolss_PrinterInfo *info;
6757                 int j;
6758                 uint32_t needed;
6759                 uint32_t count;
6760
6761                 r.in.flags      = PRINTER_ENUM_LOCAL;
6762                 r.in.server     = "";
6763                 r.in.level      = levels[i];
6764                 r.in.buffer     = NULL;
6765                 r.in.offered    = 0;
6766                 r.out.needed    = &needed;
6767                 r.out.count     = &count;
6768                 r.out.info      = &info;
6769
6770                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6771
6772                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6773                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6774
6775                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6776                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6777                         r.in.buffer = &blob;
6778                         r.in.offered = needed;
6779                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6780                 }
6781
6782                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6783
6784                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6785
6786                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6787
6788                 if (!info) {
6789                         torture_comment(tctx, "No printers returned\n");
6790                         return true;
6791                 }
6792
6793                 for (j=0;j<count;j++) {
6794                         if (r.in.level == 1) {
6795                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
6796                                 char *slash, *name, *full_name;
6797                                 name = unc;
6798                                 if (unc[0] == '\\' && unc[1] == '\\') {
6799                                         unc +=2;
6800                                 }
6801                                 slash = strchr(unc, '\\');
6802                                 if (slash) {
6803                                         slash++;
6804                                         name = slash;
6805                                 }
6806                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6807                                                             dcerpc_server_name(p), name);
6808                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6809                                         ret = false;
6810                                 }
6811                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6812                                         ret = false;
6813                                 }
6814                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6815                                         ret = false;
6816                                 }
6817                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6818                                         ret = false;
6819                                 }
6820                         }
6821                 }
6822         }
6823
6824         return ret;
6825 }
6826
6827 static bool test_EnumPrinters_level(struct torture_context *tctx,
6828                                     struct dcerpc_binding_handle *b,
6829                                     uint32_t flags,
6830                                     const char *servername,
6831                                     uint32_t level,
6832                                     uint32_t *count_p,
6833                                     union spoolss_PrinterInfo **info_p)
6834 {
6835         struct spoolss_EnumPrinters r;
6836         union spoolss_PrinterInfo *info;
6837         uint32_t needed;
6838         uint32_t count;
6839
6840         r.in.flags      = flags;
6841         r.in.server     = servername;
6842         r.in.level      = level;
6843         r.in.buffer     = NULL;
6844         r.in.offered    = 0;
6845         r.out.needed    = &needed;
6846         r.out.count     = &count;
6847         r.out.info      = &info;
6848
6849         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6850                 r.in.server, r.in.level);
6851
6852         torture_assert_ntstatus_ok(tctx,
6853                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6854                 "EnumPrinters failed");
6855         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6856                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6857                 r.in.buffer = &blob;
6858                 r.in.offered = needed;
6859                 torture_assert_ntstatus_ok(tctx,
6860                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6861                         "EnumPrinters failed");
6862         }
6863
6864         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6865
6866         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6867
6868         if (count_p) {
6869                 *count_p = count;
6870         }
6871         if (info_p) {
6872                 *info_p = info;
6873         }
6874
6875         return true;
6876 }
6877
6878 static const char *get_short_printername(struct torture_context *tctx,
6879                                          const char *name)
6880 {
6881         const char *short_name;
6882
6883         if (name[0] == '\\' && name[1] == '\\') {
6884                 name += 2;
6885                 short_name = strchr(name, '\\');
6886                 if (short_name) {
6887                         return talloc_strdup(tctx, short_name+1);
6888                 }
6889         }
6890
6891         return name;
6892 }
6893
6894 static const char *get_full_printername(struct torture_context *tctx,
6895                                         const char *name)
6896 {
6897         const char *full_name = talloc_strdup(tctx, name);
6898         char *p;
6899
6900         if (name && name[0] == '\\' && name[1] == '\\') {
6901                 name += 2;
6902                 p = strchr(name, '\\');
6903                 if (p) {
6904                         return full_name;
6905                 }
6906         }
6907
6908         return NULL;
6909 }
6910
6911 static bool test_OnePrinter_servername(struct torture_context *tctx,
6912                                        struct dcerpc_pipe *p,
6913                                        struct dcerpc_binding_handle *b,
6914                                        const char *servername,
6915                                        const char *printername)
6916 {
6917         union spoolss_PrinterInfo info;
6918         const char *short_name = get_short_printername(tctx, printername);
6919         const char *full_name = get_full_printername(tctx, printername);
6920
6921         if (short_name) {
6922                 struct policy_handle handle;
6923                 torture_assert(tctx,
6924                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6925                         "failed to open printer");
6926
6927                 torture_assert(tctx,
6928                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6929                         "failed to get printer info");
6930
6931                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6932                         "unexpected servername");
6933                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6934                         "unexpected printername");
6935
6936                 if (info.info2.devmode) {
6937                         const char *expected_devicename;
6938                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6939                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6940                                 "unexpected devicemode devicename");
6941                 }
6942
6943                 torture_assert(tctx,
6944                         test_ClosePrinter(tctx, b, &handle),
6945                         "failed to close printer");
6946         }
6947
6948         if (full_name) {
6949                 struct policy_handle handle;
6950
6951                 torture_assert(tctx,
6952                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6953                         "failed to open printer");
6954
6955                 torture_assert(tctx,
6956                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6957                         "failed to get printer info");
6958
6959                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6960                         "unexpected servername");
6961                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6962                         "unexpected printername");
6963
6964                 if (info.info2.devmode) {
6965                         const char *expected_devicename;
6966                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6967                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6968                                 "unexpected devicemode devicename");
6969                 }
6970
6971                 torture_assert(tctx,
6972                         test_ClosePrinter(tctx, b, &handle),
6973                         "failed to close printer");
6974         }
6975
6976         return true;
6977 }
6978
6979 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6980                                          void *private_data)
6981 {
6982         struct test_spoolss_context *ctx =
6983                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6984         int i;
6985         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6986         struct dcerpc_binding_handle *b = p->binding_handle;
6987         uint32_t count;
6988         union spoolss_PrinterInfo *info;
6989         const char *servername;
6990         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6991
6992         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6993
6994         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6995
6996         torture_assert(tctx,
6997                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6998                 "failed to enumerate printers");
6999
7000         for (i=0; i < count; i++) {
7001
7002                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
7003                         "unexpected servername");
7004
7005                 torture_assert(tctx,
7006                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7007                         "failed to check printer");
7008         }
7009
7010         servername = "";
7011
7012         torture_assert(tctx,
7013                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
7014                 "failed to enumerate printers");
7015
7016         for (i=0; i < count; i++) {
7017
7018                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
7019                         "unexpected servername");
7020
7021                 torture_assert(tctx,
7022                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7023                         "failed to check printer");
7024         }
7025
7026
7027         return true;
7028 }
7029
7030 #if 0
7031 static bool test_GetPrinterDriver(struct torture_context *tctx,
7032                                   struct dcerpc_binding_handle *b,
7033                                   struct policy_handle *handle,
7034                                   const char *driver_name)
7035 {
7036         struct spoolss_GetPrinterDriver r;
7037         uint32_t needed;
7038
7039         r.in.handle = handle;
7040         r.in.architecture = "W32X86";
7041         r.in.level = 1;
7042         r.in.buffer = NULL;
7043         r.in.offered = 0;
7044         r.out.needed = &needed;
7045
7046         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
7047
7048         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7049                 "failed to call GetPrinterDriver");
7050         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7051                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7052                 r.in.buffer = &blob;
7053                 r.in.offered = needed;
7054                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7055                         "failed to call GetPrinterDriver");
7056         }
7057
7058         torture_assert_werr_ok(tctx, r.out.result,
7059                 "failed to call GetPrinterDriver");
7060
7061         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7062
7063         return true;
7064 }
7065 #endif
7066
7067 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
7068                                          struct dcerpc_binding_handle *b,
7069                                          struct policy_handle *handle,
7070                                          const char *driver_name,
7071                                          const char *architecture,
7072                                          uint32_t level,
7073                                          uint32_t client_major_version,
7074                                          uint32_t client_minor_version,
7075                                          union spoolss_DriverInfo *info_p,
7076                                          WERROR *result_p)
7077
7078 {
7079         struct spoolss_GetPrinterDriver2 r;
7080         uint32_t needed;
7081         uint32_t server_major_version;
7082         uint32_t server_minor_version;
7083
7084         r.in.handle = handle;
7085         r.in.architecture = architecture;
7086         r.in.client_major_version = client_major_version;
7087         r.in.client_minor_version = client_minor_version;
7088         r.in.buffer = NULL;
7089         r.in.offered = 0;
7090         r.in.level = level;
7091         r.out.needed = &needed;
7092         r.out.server_major_version = &server_major_version;
7093         r.out.server_minor_version = &server_minor_version;
7094
7095         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7096                 driver_name, r.in.level);
7097
7098         torture_assert_ntstatus_ok(tctx,
7099                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7100                 "failed to call GetPrinterDriver2");
7101         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7102                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7103                 r.in.buffer = &blob;
7104                 r.in.offered = needed;
7105                 torture_assert_ntstatus_ok(tctx,
7106                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7107                         "failed to call GetPrinterDriver2");
7108         }
7109
7110         if (result_p) {
7111                 *result_p = r.out.result;
7112         }
7113
7114         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7115                 switch (r.in.level) {
7116                 case 101:
7117                 case 8:
7118                         torture_comment(tctx,
7119                                 "level %d not implemented, not considering as an error\n",
7120                                 r.in.level);
7121                         return true;
7122                 default:
7123                         break;
7124                 }
7125         }
7126
7127         torture_assert_werr_ok(tctx, r.out.result,
7128                 "failed to call GetPrinterDriver2");
7129
7130         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7131
7132         if (info_p) {
7133                 *info_p = *r.out.info;
7134         }
7135
7136         return true;
7137 }
7138
7139 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7140                                    struct dcerpc_binding_handle *b,
7141                                    struct policy_handle *handle,
7142                                    const char *driver_name,
7143                                    const char *architecture)
7144 {
7145         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7146         int i;
7147
7148
7149         for (i=0;i<ARRAY_SIZE(levels);i++) {
7150
7151                 torture_assert(tctx,
7152                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7153                         "");
7154         }
7155
7156         return true;
7157 }
7158
7159 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7160                                         void *private_data)
7161 {
7162         struct test_spoolss_context *ctx =
7163                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7164         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7165         int i;
7166         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7167         struct dcerpc_binding_handle *b = p->binding_handle;
7168         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7169
7170         for (i=0;i<ARRAY_SIZE(levels);i++) {
7171
7172                 uint32_t count;
7173                 union spoolss_DriverInfo *info;
7174
7175                 torture_assert(tctx,
7176                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7177                         "failed to enumerate drivers");
7178
7179                 if (!info) {
7180                         torture_comment(tctx, "No printer drivers returned\n");
7181                         break;
7182                 }
7183         }
7184
7185         return true;
7186 }
7187
7188 static bool test_DeletePrinter(struct torture_context *tctx,
7189                                struct dcerpc_binding_handle *b,
7190                                struct policy_handle *handle)
7191 {
7192         struct spoolss_DeletePrinter r;
7193
7194         torture_comment(tctx, "Testing DeletePrinter\n");
7195
7196         r.in.handle = handle;
7197
7198         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7199                 "failed to delete printer");
7200         torture_assert_werr_ok(tctx, r.out.result,
7201                 "failed to delete printer");
7202
7203         return true;
7204 }
7205
7206 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7207                                        struct dcerpc_binding_handle *b,
7208                                        uint32_t flags,
7209                                        uint32_t level,
7210                                        const char *name,
7211                                        bool *found)
7212 {
7213         struct spoolss_EnumPrinters e;
7214         uint32_t count;
7215         union spoolss_PrinterInfo *info;
7216         uint32_t needed;
7217         int i;
7218
7219         *found = false;
7220
7221         e.in.flags = flags;
7222         e.in.server = NULL;
7223         e.in.level = level;
7224         e.in.buffer = NULL;
7225         e.in.offered = 0;
7226         e.out.count = &count;
7227         e.out.info = &info;
7228         e.out.needed = &needed;
7229
7230         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7231                 "failed to enum printers");
7232
7233         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7234                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7235                 e.in.buffer = &blob;
7236                 e.in.offered = needed;
7237
7238                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7239                         "failed to enum printers");
7240         }
7241
7242         torture_assert_werr_ok(tctx, e.out.result,
7243                 "failed to enum printers");
7244
7245         for (i=0; i < count; i++) {
7246
7247                 const char *current = NULL;
7248                 const char *q;
7249
7250                 switch (level) {
7251                 case 1:
7252                         current = info[i].info1.name;
7253                         break;
7254                 }
7255
7256                 if (strequal(current, name)) {
7257                         *found = true;
7258                         break;
7259                 }
7260
7261                 q = strrchr(current, '\\');
7262                 if (q) {
7263                         if (!e.in.server) {
7264                                 torture_warning(tctx,
7265                                         "server returns printername %s incl. servername although we did not set servername", current);
7266                         }
7267                         q++;
7268                         if (strequal(q, name)) {
7269                                 *found = true;
7270                                 break;
7271                         }
7272                 }
7273         }
7274
7275         return true;
7276 }
7277
7278 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7279                                       struct dcerpc_pipe *p,
7280                                       const char *printername,
7281                                       bool ex)
7282 {
7283         WERROR result;
7284         struct spoolss_AddPrinter r;
7285         struct spoolss_AddPrinterEx rex;
7286         struct spoolss_SetPrinterInfoCtr info_ctr;
7287         struct spoolss_SetPrinterInfo1 info1;
7288         struct spoolss_DevmodeContainer devmode_ctr;
7289         struct sec_desc_buf secdesc_ctr;
7290         struct spoolss_UserLevelCtr userlevel_ctr;
7291         struct policy_handle handle;
7292         bool found = false;
7293         struct dcerpc_binding_handle *b = p->binding_handle;
7294
7295         ZERO_STRUCT(devmode_ctr);
7296         ZERO_STRUCT(secdesc_ctr);
7297         ZERO_STRUCT(userlevel_ctr);
7298         ZERO_STRUCT(info1);
7299
7300         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7301                         ex ? "Ex":"", printername);
7302
7303         /* try to add printer to wellknown printer list (level 1) */
7304
7305         userlevel_ctr.level = 1;
7306
7307         info_ctr.info.info1 = &info1;
7308         info_ctr.level = 1;
7309
7310         rex.in.server = NULL;
7311         rex.in.info_ctr = &info_ctr;
7312         rex.in.devmode_ctr = &devmode_ctr;
7313         rex.in.secdesc_ctr = &secdesc_ctr;
7314         rex.in.userlevel_ctr = &userlevel_ctr;
7315         rex.out.handle = &handle;
7316
7317         r.in.server = NULL;
7318         r.in.info_ctr = &info_ctr;
7319         r.in.devmode_ctr = &devmode_ctr;
7320         r.in.secdesc_ctr = &secdesc_ctr;
7321         r.out.handle = &handle;
7322
7323         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7324                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7325                 "failed to add printer");
7326         result = ex ? rex.out.result : r.out.result;
7327         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7328                 "unexpected result code");
7329
7330         info1.name = printername;
7331         info1.flags = PRINTER_ATTRIBUTE_SHARED;
7332
7333         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7334                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7335                 "failed to add printer");
7336         result = ex ? rex.out.result : r.out.result;
7337         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7338                 "unexpected result code");
7339
7340         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7341            better do a real check to see the printer is really there */
7342
7343         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7344                                                         PRINTER_ENUM_NETWORK, 1,
7345                                                         printername,
7346                                                         &found),
7347                         "failed to enum printers");
7348
7349         torture_assert(tctx, found, "failed to find newly added printer");
7350
7351         info1.flags = 0;
7352
7353         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7354                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7355                 "failed to add printer");
7356         result = ex ? rex.out.result : r.out.result;
7357         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7358                 "unexpected result code");
7359
7360         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7361            better do a real check to see the printer has really been removed
7362            from the well known printer list */
7363
7364         found = false;
7365
7366         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7367                                                         PRINTER_ENUM_NETWORK, 1,
7368                                                         printername,
7369                                                         &found),
7370                         "failed to enum printers");
7371 #if 0
7372         torture_assert(tctx, !found, "printer still in well known printer list");
7373 #endif
7374         return true;
7375 }
7376
7377 static bool test_AddPrinter_normal(struct torture_context *tctx,
7378                                    struct dcerpc_pipe *p,
7379                                    struct policy_handle *handle_p,
7380                                    const char *printername,
7381                                    const char *drivername,
7382                                    const char *portname,
7383                                    struct spoolss_DeviceMode *devmode,
7384                                    bool ex)
7385 {
7386         WERROR result;
7387         struct spoolss_AddPrinter r;
7388         struct spoolss_AddPrinterEx rex;
7389         struct spoolss_SetPrinterInfoCtr info_ctr;
7390         struct spoolss_SetPrinterInfo2 info2;
7391         struct spoolss_DevmodeContainer devmode_ctr;
7392         struct sec_desc_buf secdesc_ctr;
7393         struct spoolss_UserLevelCtr userlevel_ctr;
7394         struct policy_handle handle;
7395         bool found = false;
7396         bool existing_printer_deleted = false;
7397         struct dcerpc_binding_handle *b = p->binding_handle;
7398
7399         ZERO_STRUCT(devmode_ctr);
7400         ZERO_STRUCT(secdesc_ctr);
7401         ZERO_STRUCT(userlevel_ctr);
7402
7403         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7404                         ex ? "Ex":"", printername);
7405
7406         devmode_ctr.devmode = devmode;
7407
7408         userlevel_ctr.level = 1;
7409
7410         rex.in.server = NULL;
7411         rex.in.info_ctr = &info_ctr;
7412         rex.in.devmode_ctr = &devmode_ctr;
7413         rex.in.secdesc_ctr = &secdesc_ctr;
7414         rex.in.userlevel_ctr = &userlevel_ctr;
7415         rex.out.handle = &handle;
7416
7417         r.in.server = NULL;
7418         r.in.info_ctr = &info_ctr;
7419         r.in.devmode_ctr = &devmode_ctr;
7420         r.in.secdesc_ctr = &secdesc_ctr;
7421         r.out.handle = &handle;
7422
7423  again:
7424
7425         /* try to add printer to printer list (level 2) */
7426
7427         ZERO_STRUCT(info2);
7428
7429         info_ctr.info.info2 = &info2;
7430         info_ctr.level = 2;
7431
7432         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7433                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7434                 "failed to add printer");
7435         result = ex ? rex.out.result : r.out.result;
7436         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7437                 "unexpected result code");
7438
7439         info2.printername = printername;
7440
7441         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7442                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7443                 "failed to add printer");
7444         result = ex ? rex.out.result : r.out.result;
7445
7446         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7447                 struct policy_handle printer_handle;
7448
7449                 if (existing_printer_deleted) {
7450                         torture_fail(tctx, "already deleted printer still existing?");
7451                 }
7452
7453                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7454                         "failed to open printer handle");
7455
7456                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7457                         "failed to delete printer");
7458
7459                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7460                         "failed to close server handle");
7461
7462                 existing_printer_deleted = true;
7463
7464                 goto again;
7465         }
7466
7467         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7468                 "unexpected result code");
7469
7470         info2.portname = portname;
7471
7472         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7473                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7474                 "failed to add printer");
7475         result = ex ? rex.out.result : r.out.result;
7476         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7477                 "unexpected result code");
7478
7479         info2.drivername = drivername;
7480
7481         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7482                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7483                 "failed to add printer");
7484         result = ex ? rex.out.result : r.out.result;
7485
7486         /* w2k8r2 allows one to add printer w/o defining printprocessor */
7487
7488         if (!W_ERROR_IS_OK(result)) {
7489                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7490                         "unexpected result code");
7491
7492                 info2.printprocessor = "winprint";
7493
7494                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7495                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7496                         "failed to add printer");
7497                 result = ex ? rex.out.result : r.out.result;
7498                 torture_assert_werr_ok(tctx, result,
7499                         "failed to add printer");
7500         }
7501
7502         *handle_p = handle;
7503
7504         /* we are paranoid, really check if the printer is there now */
7505
7506         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7507                                                         PRINTER_ENUM_LOCAL, 1,
7508                                                         printername,
7509                                                         &found),
7510                         "failed to enum printers");
7511         torture_assert(tctx, found, "failed to find newly added printer");
7512
7513         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7514                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7515                 "failed to add printer");
7516         result = ex ? rex.out.result : r.out.result;
7517         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7518                 "unexpected result code");
7519
7520         return true;
7521 }
7522
7523 static bool test_printer_info(struct torture_context *tctx,
7524                               void *private_data)
7525 {
7526         struct torture_printer_context *t =
7527                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7528         struct dcerpc_pipe *p = t->spoolss_pipe;
7529         struct dcerpc_binding_handle *b = p->binding_handle;
7530
7531         bool ret = true;
7532
7533         if (torture_setting_bool(tctx, "samba3", false)) {
7534                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7535         }
7536
7537         if (!test_PrinterInfo(tctx, b, &t->handle)) {
7538                 ret = false;
7539         }
7540
7541         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7542                 ret = false;
7543         }
7544
7545         return ret;
7546 }
7547
7548 static bool test_EnumPrinterKey(struct torture_context *tctx,
7549                                 struct dcerpc_binding_handle *b,
7550                                 struct policy_handle *handle,
7551                                 const char *key_name,
7552                                 const char ***array)
7553 {
7554         struct spoolss_EnumPrinterKey r;
7555         uint32_t needed = 0;
7556         union spoolss_KeyNames key_buffer;
7557         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7558         uint32_t _ndr_size;
7559         int i;
7560
7561         r.in.handle = handle;
7562         r.in.key_name = key_name;
7563         r.out.key_buffer = &key_buffer;
7564         r.out.needed = &needed;
7565         r.out._ndr_size = &_ndr_size;
7566
7567         for (i=0; i < ARRAY_SIZE(offered); i++) {
7568
7569                 if (offered[i] < 0 && needed) {
7570                         if (needed <= 4) {
7571                                 continue;
7572                         }
7573                         r.in.offered = needed + offered[i];
7574                 } else {
7575                         r.in.offered = offered[i];
7576                 }
7577
7578                 ZERO_STRUCT(key_buffer);
7579
7580                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7581
7582                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7583                         "failed to call EnumPrinterKey");
7584                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7585
7586                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
7587                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7588                                         _ndr_size, r.in.offered/2));
7589
7590                         r.in.offered = needed;
7591                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7592                                 "failed to call EnumPrinterKey");
7593                 }
7594
7595                 if (offered[i] > 0) {
7596                         torture_assert_werr_ok(tctx, r.out.result,
7597                                 "failed to call EnumPrinterKey");
7598                 }
7599
7600                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7601                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7602                                 _ndr_size, r.in.offered/2));
7603
7604                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7605                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7606
7607                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7608                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7609
7610                 if (key_buffer.string_array) {
7611                         uint32_t calc_needed = 0;
7612                         int s;
7613                         for (s=0; key_buffer.string_array[s]; s++) {
7614                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7615                         }
7616                         if (!key_buffer.string_array[0]) {
7617                                 calc_needed += 2;
7618                         }
7619                         calc_needed += 2;
7620
7621                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7622                                 "EnumPrinterKey unexpected size");
7623                 }
7624         }
7625
7626         if (array) {
7627                 *array = key_buffer.string_array;
7628         }
7629
7630         return true;
7631 }
7632
7633 bool test_printer_all_keys(struct torture_context *tctx,
7634                            struct dcerpc_binding_handle *b,
7635                            struct policy_handle *handle)
7636 {
7637         const char **key_array = NULL;
7638         int i;
7639
7640         torture_comment(tctx, "Testing Printer Keys\n");
7641
7642         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7643                 "failed to call test_EnumPrinterKey");
7644
7645         for (i=0; key_array && key_array[i]; i++) {
7646                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7647                         "failed to call test_EnumPrinterKey");
7648         }
7649         for (i=0; key_array && key_array[i]; i++) {
7650                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7651                         "failed to call test_EnumPrinterDataEx");
7652         }
7653
7654         torture_comment(tctx, "Printer Keys test succeeded\n\n");
7655
7656         return true;
7657 }
7658
7659 static bool test_openprinter_wrap(struct torture_context *tctx,
7660                                   void *private_data)
7661 {
7662         struct torture_printer_context *t =
7663                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7664         struct dcerpc_pipe *p = t->spoolss_pipe;
7665         struct dcerpc_binding_handle *b = p->binding_handle;
7666         const char *printername = t->info2.printername;
7667
7668         return test_openprinter(tctx, b, printername);
7669 }
7670
7671 static bool test_csetprinter(struct torture_context *tctx,
7672                              void *private_data)
7673 {
7674         struct torture_printer_context *t =
7675                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7676         struct dcerpc_pipe *p = t->spoolss_pipe;
7677
7678         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7679         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7680         const char *portname = t->info2.portname;
7681
7682         union spoolss_PrinterInfo info;
7683         struct policy_handle new_handle, new_handle2;
7684         struct dcerpc_binding_handle *b = p->binding_handle;
7685
7686         torture_comment(tctx, "Testing c_setprinter\n");
7687
7688         torture_assert(tctx,
7689                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7690                 "failed to get level 0 printer info");
7691         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7692                 info.info0.c_setprinter);
7693
7694         /* check if c_setprinter on 1st handle increases after a printer has
7695          * been added */
7696
7697         torture_assert(tctx,
7698                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7699                 "failed to add new printer");
7700         torture_assert(tctx,
7701                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7702                 "failed to get level 0 printer info");
7703         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7704                 info.info0.c_setprinter);
7705
7706         /* check if c_setprinter on new handle increases after a printer has
7707          * been added */
7708
7709         torture_assert(tctx,
7710                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7711                 "failed to get level 0 printer info");
7712         torture_comment(tctx, "csetprinter on created handle: %d\n",
7713                 info.info0.c_setprinter);
7714
7715         /* open the new printer and check if c_setprinter increases */
7716
7717         torture_assert(tctx,
7718                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7719                 "failed to open created printer");
7720         torture_assert(tctx,
7721                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7722                 "failed to get level 0 printer info");
7723         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7724                 info.info0.c_setprinter);
7725
7726         /* cleanup */
7727
7728         torture_assert(tctx,
7729                 test_ClosePrinter(tctx, b, &new_handle2),
7730                 "failed to close printer");
7731         torture_assert(tctx,
7732                 test_DeletePrinter(tctx, b, &new_handle),
7733                 "failed to delete new printer");
7734
7735         return true;
7736 }
7737
7738 static bool compose_local_driver_directory(struct torture_context *tctx,
7739                                            const char *environment,
7740                                            const char *local_dir,
7741                                            const char **path)
7742 {
7743         char *p;
7744
7745         p = strrchr(local_dir, '/');
7746         if (!p) {
7747                 return NULL;
7748         }
7749         p++;
7750
7751         if (strequal(environment, "Windows x64")) {
7752                 if (!strequal(p, "x64")) {
7753                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7754                 }
7755         } else if (strequal(environment, "Windows NT x86")) {
7756                 if (!strequal(p, "i386")) {
7757                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7758                 }
7759         } else {
7760                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7761         }
7762
7763         return true;
7764 }
7765
7766 #if 0
7767 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7768                                                      const char *devicename)
7769 {
7770         struct spoolss_DeviceMode *r;
7771
7772         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7773         if (r == NULL) {
7774                 return NULL;
7775         }
7776
7777         r->devicename           = talloc_strdup(r, devicename);
7778         r->specversion          = DMSPEC_NT4_AND_ABOVE;
7779         r->driverversion        = 0x0600;
7780         r->size                 = 0x00dc;
7781         r->__driverextra_length = 0;
7782         r->fields               = DEVMODE_FORMNAME |
7783                                   DEVMODE_TTOPTION |
7784                                   DEVMODE_PRINTQUALITY |
7785                                   DEVMODE_DEFAULTSOURCE |
7786                                   DEVMODE_COPIES |
7787                                   DEVMODE_SCALE |
7788                                   DEVMODE_PAPERSIZE |
7789                                   DEVMODE_ORIENTATION;
7790         r->orientation          = DMORIENT_PORTRAIT;
7791         r->papersize            = DMPAPER_LETTER;
7792         r->paperlength          = 0;
7793         r->paperwidth           = 0;
7794         r->scale                = 100;
7795         r->copies               = 55;
7796         r->defaultsource        = DMBIN_FORMSOURCE;
7797         r->printquality         = DMRES_HIGH;
7798         r->color                = DMRES_MONOCHROME;
7799         r->duplex               = DMDUP_SIMPLEX;
7800         r->yresolution          = 0;
7801         r->ttoption             = DMTT_SUBDEV;
7802         r->collate              = DMCOLLATE_FALSE;
7803         r->formname             = talloc_strdup(r, "Letter");
7804
7805         return r;
7806 }
7807 #endif
7808
7809 static bool test_architecture_buffer(struct torture_context *tctx,
7810                                      void *private_data)
7811 {
7812         struct test_spoolss_context *ctx =
7813                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7814
7815         struct spoolss_OpenPrinterEx r;
7816         struct spoolss_UserLevel1 u1;
7817         struct policy_handle handle;
7818         uint32_t architectures[] = {
7819                 PROCESSOR_ARCHITECTURE_INTEL,
7820                 PROCESSOR_ARCHITECTURE_IA64,
7821                 PROCESSOR_ARCHITECTURE_AMD64
7822         };
7823         uint32_t needed[3];
7824         int i;
7825         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7826         struct dcerpc_binding_handle *b = p->binding_handle;
7827
7828         for (i=0; i < ARRAY_SIZE(architectures); i++) {
7829
7830                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7831
7832                 u1.size = 0;
7833                 u1.client = NULL;
7834                 u1.user = NULL;
7835                 u1.build = 0;
7836                 u1.major = 3;
7837                 u1.minor = 0;
7838                 u1.processor = architectures[i];
7839
7840                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7841                 r.in.datatype           = NULL;
7842                 r.in.devmode_ctr.devmode= NULL;
7843                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
7844                 r.in.userlevel_ctr.level = 1;
7845                 r.in.userlevel_ctr.user_info.level1 = &u1;
7846                 r.out.handle            = &handle;
7847
7848                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7849                 torture_assert_werr_ok(tctx, r.out.result, "");
7850
7851                 {
7852                         struct spoolss_EnumPrinters e;
7853                         uint32_t count;
7854                         union spoolss_PrinterInfo *info;
7855
7856                         e.in.flags = PRINTER_ENUM_LOCAL;
7857                         e.in.server = NULL;
7858                         e.in.level = 2;
7859                         e.in.buffer = NULL;
7860                         e.in.offered = 0;
7861                         e.out.count = &count;
7862                         e.out.info = &info;
7863                         e.out.needed = &needed[i];
7864
7865                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7866 #if 0
7867                         torture_comment(tctx, "needed was %d\n", needed[i]);
7868 #endif
7869                 }
7870
7871                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7872         }
7873
7874         for (i=1; i < ARRAY_SIZE(architectures); i++) {
7875                 if (needed[i-1] != needed[i]) {
7876                         torture_fail(tctx,
7877                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7878                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7879                 }
7880         }
7881
7882         return true;
7883 }
7884
7885 static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
7886                                                     struct dcerpc_pipe *p,
7887                                                     const char *architecture,
7888                                                     const char *guid_str,
7889                                                     const char **package_id)
7890 {
7891         struct spoolss_GetCorePrinterDrivers r;
7892         struct spoolss_CorePrinterDriver core_printer_drivers;
7893         DATA_BLOB blob;
7894         const char **s;
7895         struct dcerpc_binding_handle *b = p->binding_handle;
7896         struct GUID guid;
7897
7898         s = talloc_zero_array(tctx, const char *, 2);
7899
7900         r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7901         r.in.architecture = "foobar";
7902         r.in.core_driver_size = 0;
7903         r.in.core_driver_dependencies = "";
7904         r.in.core_printer_driver_count = 0;
7905         r.out.core_printer_drivers = &core_printer_drivers;
7906
7907         torture_assert_ntstatus_ok(tctx,
7908                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
7909                 "spoolss_GetCorePrinterDrivers failed");
7910         torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
7911                 "spoolss_GetCorePrinterDrivers failed");
7912
7913         guid = GUID_random();
7914         s[0] = GUID_string2(tctx, &guid);
7915
7916         torture_assert(tctx,
7917                 push_reg_multi_sz(tctx, &blob, s),
7918                 "push_reg_multi_sz failed");
7919
7920         r.in.core_driver_size = blob.length;
7921         r.in.core_driver_dependencies = s[0];
7922         r.in.core_printer_driver_count = 1;
7923         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
7924
7925         torture_assert_ntstatus_ok(tctx,
7926                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
7927                 "spoolss_GetCorePrinterDrivers failed");
7928         torture_assert_werr_equal(tctx,
7929                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
7930                 "spoolss_GetCorePrinterDrivers failed");
7931
7932         r.in.architecture = architecture;
7933
7934         torture_assert_ntstatus_ok(tctx,
7935                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
7936                 "spoolss_GetCorePrinterDrivers failed");
7937         torture_assert_werr_equal(tctx,
7938                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
7939                 "spoolss_GetCorePrinterDrivers failed");
7940
7941         s[0] = talloc_strdup(s, guid_str);
7942
7943         torture_assert(tctx,
7944                 push_reg_multi_sz(tctx, &blob, s),
7945                 "push_reg_multi_sz failed");
7946
7947         r.in.core_driver_size = blob.length;
7948         r.in.core_driver_dependencies = s[0];
7949         r.in.core_printer_driver_count = 1;
7950         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
7951
7952         torture_assert_ntstatus_ok(tctx,
7953                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
7954                 "spoolss_GetCorePrinterDrivers failed");
7955         torture_assert_hresult_ok(tctx, r.out.result,
7956                 "spoolss_GetCorePrinterDrivers failed");
7957
7958         if (package_id) {
7959                 *package_id = r.out.core_printer_drivers[0].szPackageID;
7960         }
7961
7962         return true;
7963 }
7964
7965 static bool test_get_core_printer_drivers(struct torture_context *tctx,
7966                                           void *private_data)
7967 {
7968         struct test_spoolss_context *ctx =
7969                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7970
7971         const char *architectures[] = {
7972                 SPOOLSS_ARCHITECTURE_NT_X86,
7973                 SPOOLSS_ARCHITECTURE_x64
7974         };
7975         int i;
7976         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7977
7978         for (i=0; i < ARRAY_SIZE(architectures); i++) {
7979
7980                 torture_comment(tctx, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
7981                         architectures[i],
7982                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
7983
7984                 torture_assert(tctx,
7985                         test_get_core_printer_drivers_arch_guid(tctx, p,
7986                                 architectures[i],
7987                                 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
7988                                 NULL),
7989                         "");
7990         }
7991
7992         return true;
7993 }
7994
7995 static bool test_get_printer_driver_package_path(struct torture_context *tctx,
7996                                                  void *private_data)
7997 {
7998         struct test_spoolss_context *ctx =
7999                 talloc_get_type_abort(private_data, struct test_spoolss_context);
8000
8001         const char *architectures[] = {
8002                 SPOOLSS_ARCHITECTURE_NT_X86,
8003                 SPOOLSS_ARCHITECTURE_x64
8004         };
8005         int i;
8006         struct dcerpc_pipe *p = ctx->spoolss_pipe;
8007         struct dcerpc_binding_handle *b = p->binding_handle;
8008
8009         for (i=0; i < ARRAY_SIZE(architectures); i++) {
8010                 struct spoolss_GetPrinterDriverPackagePath r;
8011                 uint32_t required = 0;
8012                 const char *package_id = NULL;
8013
8014                 test_get_core_printer_drivers_arch_guid(tctx, p,
8015                         architectures[i],
8016                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
8017                         &package_id),
8018
8019                 torture_comment(tctx, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
8020                         architectures[i], package_id);
8021
8022                 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8023                 r.in.architecture = "foobar";
8024                 r.in.language = NULL;
8025                 r.in.package_id = "";
8026                 r.in.driver_package_cab_size = 0;
8027                 r.in.driver_package_cab = NULL;
8028
8029                 r.out.required = &required;
8030                 r.out.driver_package_cab = NULL;
8031
8032                 torture_assert_ntstatus_ok(tctx,
8033                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8034                         "spoolss_GetPrinterDriverPackagePath failed");
8035                 torture_assert_werr_equal(tctx,
8036                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
8037                         "spoolss_GetPrinterDriverPackagePath failed");
8038
8039                 r.in.architecture = architectures[i];
8040
8041                 torture_assert_ntstatus_ok(tctx,
8042                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8043                         "spoolss_GetPrinterDriverPackagePath failed");
8044                 torture_assert_werr_equal(tctx,
8045                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
8046                         "spoolss_GetPrinterDriverPackagePath failed");
8047
8048                 r.in.package_id = package_id;
8049
8050                 torture_assert_ntstatus_ok(tctx,
8051                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8052                         "spoolss_GetPrinterDriverPackagePath failed");
8053                 torture_assert_hresult_ok(tctx, r.out.result,
8054                         "spoolss_GetPrinterDriverPackagePath failed");
8055
8056                 r.in.driver_package_cab_size = required;
8057                 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
8058                 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
8059
8060                 torture_assert_ntstatus_ok(tctx,
8061                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8062                         "spoolss_GetPrinterDriverPackagePath failed");
8063                 torture_assert_hresult_ok(tctx, r.out.result,
8064                         "spoolss_GetPrinterDriverPackagePath failed");
8065
8066         }
8067
8068         return true;
8069 }
8070
8071 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
8072                                           void *private_data)
8073 {
8074         struct test_spoolss_context *ctx =
8075                 talloc_get_type_abort(private_data, struct test_spoolss_context);
8076         struct dcerpc_pipe *p = ctx->spoolss_pipe;
8077         struct dcerpc_binding_handle *b = p->binding_handle;
8078
8079         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
8080 }
8081
8082 static bool test_PrintServer_Forms(struct torture_context *tctx,
8083                                    void *private_data)
8084 {
8085         struct test_spoolss_context *ctx =
8086                 talloc_get_type_abort(private_data, struct test_spoolss_context);
8087         struct dcerpc_pipe *p = ctx->spoolss_pipe;
8088         struct dcerpc_binding_handle *b = p->binding_handle;
8089
8090         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
8091 }
8092
8093 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
8094                                        void *private_data)
8095 {
8096         struct test_spoolss_context *ctx =
8097                 talloc_get_type_abort(private_data, struct test_spoolss_context);
8098         struct dcerpc_pipe *p = ctx->spoolss_pipe;
8099         struct dcerpc_binding_handle *b = p->binding_handle;
8100
8101         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
8102 }
8103
8104 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
8105 {
8106         NTSTATUS status;
8107
8108         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
8109
8110         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
8111
8112         torture_assert(tctx,
8113                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
8114                 "failed to open printserver");
8115         torture_assert(tctx,
8116                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
8117                 "failed to get environment");
8118
8119         return true;
8120 }
8121
8122 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
8123 {
8124         struct test_spoolss_context *t;
8125
8126         *data = t = talloc_zero(tctx, struct test_spoolss_context);
8127
8128         return torture_rpc_spoolss_setup_common(tctx, t);
8129 }
8130
8131 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
8132 {
8133         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
8134
8135         return true;
8136 }
8137
8138 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
8139 {
8140         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
8141         bool ret;
8142
8143         ret = torture_rpc_spoolss_teardown_common(tctx, t);
8144         talloc_free(t);
8145
8146         return ret;
8147 }
8148
8149 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
8150 {
8151         struct dcerpc_pipe *p;
8152         struct dcerpc_binding_handle *b;
8153         const char *server_name_slash;
8154         const char *driver_name;
8155         const char *printer_name;
8156         const char *port_name;
8157
8158         torture_assert_ntstatus_ok(tctx,
8159                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
8160                 "Error connecting to server");
8161
8162         p = t->spoolss_pipe;
8163         b = p->binding_handle;
8164         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8165
8166         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
8167         t->driver.info8.driver_name             = TORTURE_DRIVER;
8168         t->driver.info8.driver_path             = "pscript5.dll";
8169         t->driver.info8.data_file               = "cups6.ppd";
8170         t->driver.info8.config_file             = "ps5ui.dll";
8171         t->driver.info8.help_file               = "pscript.hlp";
8172         t->driver.info8.default_datatype        = "RAW";
8173         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
8174         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
8175         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
8176         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
8177         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
8178         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
8179         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
8180         t->driver.info8.dependent_files->string[5] = "cups6.ini";
8181         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
8182         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
8183
8184         t->driver.local.driver_directory= "/usr/share/cups/drivers";
8185
8186         t->info2.portname               = "LPT1:";
8187
8188         printer_name = t->info2.printername;
8189         port_name = t->info2.portname;
8190
8191         torture_assert(tctx,
8192                 fillup_printserver_info(tctx, p, &t->driver),
8193                 "failed to fillup printserver info");
8194
8195         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
8196
8197         torture_assert(tctx,
8198                 compose_local_driver_directory(tctx, t->driver.remote.environment,
8199                                                t->driver.local.driver_directory,
8200                                                &t->driver.local.driver_directory),
8201                 "failed to compose local driver directory");
8202
8203         t->info2.drivername             = "Microsoft XPS Document Writer";
8204
8205         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8206                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
8207                         t->info2.drivername, t->driver.remote.environment);
8208                 t->have_driver = true;
8209                 goto try_add;
8210         }
8211
8212         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8213                 t->info2.drivername, t->driver.remote.environment);
8214
8215         t->info2.drivername             = "Microsoft XPS Document Writer v4";
8216
8217         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8218                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8219                         t->info2.drivername, t->driver.remote.environment);
8220                 t->have_driver = true;
8221                 goto try_add;
8222         }
8223
8224         torture_comment(tctx, "trying to upload own driver\n");
8225
8226         if (!directory_exist(t->driver.local.driver_directory)) {
8227                 torture_warning(tctx, "no local driver is available!");
8228                 t->have_driver = false;
8229                 goto try_add;
8230         }
8231
8232         torture_assert(tctx,
8233                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
8234                 "failed to upload printer driver");
8235
8236         torture_assert(tctx,
8237                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
8238                 "failed to add driver");
8239
8240         t->added_driver = true;
8241         t->have_driver = true;
8242
8243  try_add:
8244         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8245
8246         if (t->wellknown) {
8247                 torture_assert(tctx,
8248                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
8249                         "failed to add wellknown printer");
8250         } else {
8251                 torture_assert(tctx,
8252                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
8253                         "failed to add printer");
8254         }
8255
8256         return true;
8257 }
8258
8259 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
8260 {
8261         struct torture_printer_context *t;
8262
8263         *data = t = talloc_zero(tctx, struct torture_printer_context);
8264
8265         t->ex                   = false;
8266         t->wellknown            = false;
8267         t->info2.printername    = TORTURE_PRINTER;
8268         t->devmode              = NULL;
8269
8270         return torture_rpc_spoolss_printer_setup_common(tctx, t);
8271 }
8272
8273 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
8274 {
8275         struct torture_printer_context *t;
8276
8277         *data = t = talloc_zero(tctx, struct torture_printer_context);
8278
8279         t->ex                   = true;
8280         t->wellknown            = false;
8281         t->info2.printername    = TORTURE_PRINTER_EX;
8282         t->devmode              = NULL;
8283
8284         return torture_rpc_spoolss_printer_setup_common(tctx, t);
8285 }
8286
8287 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8288 {
8289         struct torture_printer_context *t;
8290
8291         *data = t = talloc_zero(tctx, struct torture_printer_context);
8292
8293         t->ex                   = false;
8294         t->wellknown            = true;
8295         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
8296         t->devmode              = NULL;
8297
8298         /* FIXME */
8299         if (t->wellknown) {
8300                 torture_skip(tctx, "skipping AddPrinter level 1");
8301         }
8302
8303         return torture_rpc_spoolss_printer_setup_common(tctx, t);
8304 }
8305
8306 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8307 {
8308         struct torture_printer_context *t;
8309
8310         *data = t = talloc_zero(tctx, struct torture_printer_context);
8311
8312         t->ex                   = true;
8313         t->wellknown            = true;
8314         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
8315         t->devmode              = NULL;
8316
8317         /* FIXME */
8318         if (t->wellknown) {
8319                 torture_skip(tctx, "skipping AddPrinterEx level 1");
8320         }
8321
8322         return torture_rpc_spoolss_printer_setup_common(tctx, t);
8323 }
8324
8325 #if 0
8326 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8327 {
8328         struct torture_printer_context *t;
8329
8330         *data = t = talloc_zero(tctx, struct torture_printer_context);
8331
8332         t->ex                   = true;
8333         t->wellknown            = false;
8334         t->info2.printername    = TORTURE_PRINTER_EX;
8335         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
8336
8337         return torture_rpc_spoolss_printer_setup_common(tctx, t);
8338 }
8339 #endif
8340
8341 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8342 {
8343         bool found = false;
8344         struct dcerpc_pipe *p = t->spoolss_pipe;
8345         struct dcerpc_binding_handle *b;
8346         const char *printer_name = t->info2.printername;
8347
8348         if (t->added_driver) {
8349                 torture_assert(tctx,
8350                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8351                         "failed to remove printer driver");
8352         }
8353
8354         if (p && !t->wellknown) {
8355                 b = p->binding_handle;
8356
8357                 torture_assert(tctx,
8358                         test_DeletePrinter(tctx, b, &t->handle),
8359                         "failed to delete printer");
8360
8361                 torture_assert(tctx,
8362                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8363                                                    printer_name, &found),
8364                         "failed to enumerate printers");
8365
8366                 torture_assert(tctx, !found, "deleted printer still there");
8367         }
8368
8369         return true;
8370 }
8371
8372 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8373 {
8374         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8375         bool ret;
8376
8377         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8378         talloc_free(t);
8379
8380         return ret;
8381 }
8382
8383 static bool test_print_test(struct torture_context *tctx,
8384                             void *private_data)
8385 {
8386         struct torture_printer_context *t =
8387                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8388         struct dcerpc_pipe *p = t->spoolss_pipe;
8389         struct dcerpc_binding_handle *b = p->binding_handle;
8390
8391         torture_assert(tctx,
8392                 test_PausePrinter(tctx, b, &t->handle),
8393                 "failed to pause printer");
8394
8395         torture_assert(tctx,
8396                 test_DoPrintTest(tctx, b, &t->handle),
8397                 "failed to do print test");
8398
8399         torture_assert(tctx,
8400                 test_ResumePrinter(tctx, b, &t->handle),
8401                 "failed to resume printer");
8402
8403         return true;
8404 }
8405
8406 static bool test_print_test_extended(struct torture_context *tctx,
8407                                      void *private_data)
8408 {
8409         struct torture_printer_context *t =
8410                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8411         struct dcerpc_pipe *p = t->spoolss_pipe;
8412         struct dcerpc_binding_handle *b = p->binding_handle;
8413         bool ret = true;
8414
8415         torture_assert(tctx,
8416                 test_PausePrinter(tctx, b, &t->handle),
8417                 "failed to pause printer");
8418
8419         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8420         if (ret == false) {
8421                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8422                 if (torture_setting_bool(tctx, "samba3", false)) {
8423                         torture_comment(tctx, "non-critical for samba3\n");
8424                         ret = true;
8425                         tctx->last_result = TORTURE_SKIP;
8426                 }
8427         }
8428
8429         torture_assert(tctx,
8430                 test_ResumePrinter(tctx, b, &t->handle),
8431                 "failed to resume printer");
8432
8433         return ret;
8434 }
8435
8436 static bool test_print_test_properties(struct torture_context *tctx,
8437                                        void *private_data)
8438 {
8439         struct torture_printer_context *t =
8440                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8441         struct dcerpc_pipe *p = t->spoolss_pipe;
8442         struct dcerpc_binding_handle *b = p->binding_handle;
8443
8444         if (torture_setting_bool(tctx, "samba3", false)) {
8445                 torture_skip(tctx, "skip printer job property tests against samba");
8446         }
8447
8448         torture_assert(tctx,
8449                 test_PausePrinter(tctx, b, &t->handle),
8450                 "failed to pause printer");
8451
8452         torture_assert(tctx,
8453                 test_DoPrintTest_properties(tctx, b, &t->handle),
8454                 "failed to test print job properties");
8455
8456         torture_assert(tctx,
8457                 test_ResumePrinter(tctx, b, &t->handle),
8458                 "failed to resume printer");
8459
8460         return true;
8461 }
8462
8463 /* use smbd file IO to spool a print job */
8464 static bool test_print_test_smbd(struct torture_context *tctx,
8465                                  void *private_data)
8466 {
8467         struct torture_printer_context *t =
8468                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8469         struct dcerpc_pipe *p = t->spoolss_pipe;
8470         struct dcerpc_binding_handle *b = p->binding_handle;
8471         NTSTATUS status;
8472         uint32_t count;
8473         union spoolss_JobInfo *info = NULL;
8474         int i;
8475
8476         struct smb2_tree *tree;
8477         struct smb2_handle job_h;
8478         struct cli_credentials *credentials = cmdline_credentials;
8479         struct smbcli_options options;
8480         TALLOC_CTX *mem_ctx = talloc_new(tctx);
8481         /*
8482          * Do not test against the dynamically added printers, printing via
8483          * smbd means that a different spoolss process may handle the
8484          * OpenPrinter request to the one that handled the AddPrinter request.
8485          * This currently leads to an ugly race condition where one process
8486          * sees the new printer and one doesn't.
8487          */
8488         const char *share = TORTURE_PRINTER_STATIC1;
8489
8490         torture_comment(tctx, "Testing smbd job spooling\n");
8491         lpcfg_smbcli_options(tctx->lp_ctx, &options);
8492
8493         status = smb2_connect(mem_ctx,
8494                               torture_setting_string(tctx, "host", NULL),
8495                               lpcfg_smb_ports(tctx->lp_ctx),
8496                               share,
8497                               lpcfg_resolve_context(tctx->lp_ctx),
8498                               credentials,
8499                               &tree,
8500                               tctx->ev,
8501                               &options,
8502                               lpcfg_socket_options(tctx->lp_ctx),
8503                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8504         if (!NT_STATUS_IS_OK(status)) {
8505                 printf("Failed to connect to SMB2 printer %s - %s\n",
8506                        share, nt_errstr(status));
8507                 return false;
8508         }
8509
8510         status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8511         torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8512
8513         status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8514                                  sizeof("exciting print job data"));
8515         torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8516
8517         /* check back end spoolss job was created */
8518         torture_assert(tctx,
8519                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8520                                    &count, &info),
8521                 "EnumJobs level 1 failed");
8522
8523         for (i = 0; i < count; i++) {
8524                 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8525                         break;
8526                 }
8527         }
8528         torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8529
8530         status = smb2_util_close(tree, job_h);
8531         torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8532
8533         /* disconnect from printer share */
8534         talloc_free(mem_ctx);
8535
8536         return true;
8537 }
8538
8539 static bool test_print_test_purge(struct torture_context *tctx,
8540                                   void *private_data)
8541 {
8542         struct torture_printer_context *t =
8543            (struct torture_printer_context *)talloc_get_type_abort(private_data,
8544                                                 struct torture_printer_context);
8545         struct dcerpc_pipe *p = t->spoolss_pipe;
8546         struct dcerpc_binding_handle *b = p->binding_handle;
8547         uint32_t num_jobs = 8;
8548         uint32_t *job_ids;
8549         int i;
8550         bool ret = true;
8551         uint32_t count;
8552         union spoolss_JobInfo *info;
8553
8554         torture_assert(tctx,
8555                 test_PausePrinter(tctx, b, &t->handle),
8556                 "failed to pause printer");
8557
8558         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
8559         for (i=0; i < num_jobs; i++) {
8560                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
8561                                                    "TorturePrintJob",
8562                                                    &job_ids[i]);
8563                 torture_assert(tctx, ret, "failed to add print job");
8564         }
8565
8566         torture_assert(tctx,
8567                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8568                                    &count, &info),
8569                 "EnumJobs level 1 failed");
8570
8571         torture_assert_int_equal(tctx, count, num_jobs,
8572                                  "unexpected number of jobs in queue");
8573
8574         torture_assert(tctx,
8575                 test_printer_purge(tctx, b, &t->handle),
8576                 "failed to purge printer");
8577
8578         torture_assert(tctx,
8579                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8580                                    &count, &info),
8581                 "EnumJobs level 1 failed");
8582
8583         torture_assert_int_equal(tctx, count, 0,
8584                                  "unexpected number of jobs in queue");
8585
8586         torture_assert(tctx,
8587                 test_ResumePrinter(tctx, b, &t->handle),
8588                 "failed to resume printer");
8589
8590         return true;
8591 }
8592
8593 static bool test_printer_sd(struct torture_context *tctx,
8594                             void *private_data)
8595 {
8596         struct torture_printer_context *t =
8597                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8598         struct dcerpc_pipe *p = t->spoolss_pipe;
8599         struct dcerpc_binding_handle *b = p->binding_handle;
8600
8601         torture_assert(tctx,
8602                 test_PrinterInfo_SD(tctx, b, &t->handle),
8603                 "failed to test security descriptors");
8604
8605         return true;
8606 }
8607
8608 static bool test_printer_dm(struct torture_context *tctx,
8609                             void *private_data)
8610 {
8611         struct torture_printer_context *t =
8612                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8613         struct dcerpc_pipe *p = t->spoolss_pipe;
8614
8615         torture_assert(tctx,
8616                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8617                 "failed to test devicemodes");
8618
8619         return true;
8620 }
8621
8622 static bool test_printer_info_winreg(struct torture_context *tctx,
8623                                      void *private_data)
8624 {
8625         struct torture_printer_context *t =
8626                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8627         struct dcerpc_pipe *p = t->spoolss_pipe;
8628
8629         torture_assert(tctx,
8630                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8631                 "failed to test printer info winreg");
8632
8633         return true;
8634 }
8635
8636 static bool test_printer_change_id(struct torture_context *tctx,
8637                                    void *private_data)
8638 {
8639         struct torture_printer_context *t =
8640                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8641         struct dcerpc_pipe *p = t->spoolss_pipe;
8642
8643         torture_assert(tctx,
8644                 test_ChangeID(tctx, p, &t->handle),
8645                 "failed to test change id");
8646
8647         return true;
8648 }
8649
8650 static bool test_printer_keys(struct torture_context *tctx,
8651                               void *private_data)
8652 {
8653         struct torture_printer_context *t =
8654                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8655         struct dcerpc_pipe *p = t->spoolss_pipe;
8656         struct dcerpc_binding_handle *b = p->binding_handle;
8657
8658         torture_assert(tctx,
8659                 test_printer_all_keys(tctx, b, &t->handle),
8660                 "failed to test printer keys");
8661
8662         return true;
8663 }
8664
8665 static bool test_printer_data_consistency(struct torture_context *tctx,
8666                                           void *private_data)
8667 {
8668         struct torture_printer_context *t =
8669                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8670         struct dcerpc_pipe *p = t->spoolss_pipe;
8671
8672         torture_assert(tctx,
8673                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8674                 "failed to test printer data consistency");
8675
8676         return true;
8677 }
8678
8679 static bool test_printer_data_keys(struct torture_context *tctx,
8680                                    void *private_data)
8681 {
8682         struct torture_printer_context *t =
8683                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8684         struct dcerpc_pipe *p = t->spoolss_pipe;
8685
8686         torture_assert(tctx,
8687                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8688                 "failed to test printer data keys");
8689
8690         return true;
8691 }
8692
8693 static bool test_printer_data_values(struct torture_context *tctx,
8694                                      void *private_data)
8695 {
8696         struct torture_printer_context *t =
8697                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8698         struct dcerpc_pipe *p = t->spoolss_pipe;
8699
8700         torture_assert(tctx,
8701                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8702                 "failed to test printer data values");
8703
8704         return true;
8705 }
8706
8707 static bool test_printer_data_set(struct torture_context *tctx,
8708                                   void *private_data)
8709 {
8710         struct torture_printer_context *t =
8711                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8712         struct dcerpc_pipe *p = t->spoolss_pipe;
8713
8714         torture_assert(tctx,
8715                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8716                 "failed to test printer data set");
8717
8718         return true;
8719 }
8720
8721 static bool test_printer_data_winreg(struct torture_context *tctx,
8722                                      void *private_data)
8723 {
8724         struct torture_printer_context *t =
8725                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8726         struct dcerpc_pipe *p = t->spoolss_pipe;
8727
8728         torture_assert(tctx,
8729                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8730                 "failed to test printer data winreg");
8731
8732         return true;
8733 }
8734
8735 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8736                                         void *private_data)
8737 {
8738         struct torture_printer_context *t =
8739                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8740         struct dcerpc_pipe *p = t->spoolss_pipe;
8741
8742         torture_assert(tctx,
8743                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8744                 "failed to test printer data winreg dsspooler");
8745
8746         return true;
8747 }
8748
8749 static bool test_printer_ic(struct torture_context *tctx,
8750                             void *private_data)
8751 {
8752         struct torture_printer_context *t =
8753                 talloc_get_type_abort(private_data,
8754                                       struct torture_printer_context);
8755         struct dcerpc_pipe *p = t->spoolss_pipe;
8756         struct dcerpc_binding_handle *b = p->binding_handle;
8757         struct policy_handle gdi_handle;
8758
8759         if (torture_setting_bool(tctx, "samba3", false)) {
8760                 torture_skip(tctx, "skip printer information context tests against samba");
8761         }
8762
8763         {
8764                 struct spoolss_CreatePrinterIC r;
8765                 struct spoolss_DevmodeContainer devmode_ctr;
8766
8767                 ZERO_STRUCT(devmode_ctr);
8768
8769                 r.in.handle = &t->handle;
8770                 r.in.devmode_ctr = &devmode_ctr;
8771                 r.out.gdi_handle = &gdi_handle;
8772
8773                 torture_assert_ntstatus_ok(tctx,
8774                         dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8775                         "CreatePrinterIC failed");
8776                 torture_assert_werr_ok(tctx, r.out.result,
8777                         "CreatePrinterIC failed");
8778         }
8779
8780         {
8781                 struct spoolss_PlayGDIScriptOnPrinterIC r;
8782                 DATA_BLOB in,out;
8783                 int i;
8784                 uint32_t num_fonts = 0;
8785
8786                 in = data_blob_string_const("");
8787
8788                 r.in.gdi_handle = &gdi_handle;
8789                 r.in.pIn = in.data;
8790                 r.in.cIn = in.length;
8791                 r.in.ul = 0;
8792
8793                 for (i = 0; i < 4; i++) {
8794
8795                         out = data_blob_talloc_zero(tctx, i);
8796
8797                         r.in.cOut = out.length;
8798                         r.out.pOut = out.data;
8799
8800                         torture_assert_ntstatus_ok(tctx,
8801                                 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8802                                 "PlayGDIScriptOnPrinterIC failed");
8803                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8804                                 "PlayGDIScriptOnPrinterIC failed");
8805                 }
8806
8807                 out = data_blob_talloc_zero(tctx, 4);
8808
8809                 r.in.cOut = out.length;
8810                 r.out.pOut = out.data;
8811
8812                 torture_assert_ntstatus_ok(tctx,
8813                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8814                         "PlayGDIScriptOnPrinterIC failed");
8815                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8816                         "PlayGDIScriptOnPrinterIC failed");
8817
8818                 /* now we should have the required length, so retry with a
8819                  * buffer which is large enough to carry all font ids */
8820
8821                 num_fonts = IVAL(r.out.pOut, 0);
8822
8823                 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8824
8825                 out = data_blob_talloc_zero(tctx,
8826                         num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8827
8828                 r.in.cOut = out.length;
8829                 r.out.pOut = out.data;
8830
8831                 torture_assert_ntstatus_ok(tctx,
8832                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8833                         "PlayGDIScriptOnPrinterIC failed");
8834                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8835                         "PlayGDIScriptOnPrinterIC failed");
8836
8837         }
8838
8839         {
8840                 struct spoolss_DeletePrinterIC r;
8841
8842                 r.in.gdi_handle = &gdi_handle;
8843                 r.out.gdi_handle = &gdi_handle;
8844
8845                 torture_assert_ntstatus_ok(tctx,
8846                         dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8847                         "DeletePrinterIC failed");
8848                 torture_assert_werr_ok(tctx, r.out.result,
8849                         "DeletePrinterIC failed");
8850
8851         }
8852
8853         return true;
8854 }
8855
8856 static bool test_printer_bidi(struct torture_context *tctx,
8857                               void *private_data)
8858 {
8859         struct torture_printer_context *t =
8860                 talloc_get_type_abort(private_data,
8861                                       struct torture_printer_context);
8862         struct dcerpc_pipe *p = t->spoolss_pipe;
8863         struct dcerpc_binding_handle *b = p->binding_handle;
8864         struct spoolss_RpcSendRecvBidiData r;
8865         struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8866         struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8867
8868         if (torture_setting_bool(tctx, "samba3", false)) {
8869                 torture_skip(tctx, "skip printer bidirectional tests against samba");
8870         }
8871
8872         ZERO_STRUCT(bidi_req);
8873
8874         r.in.hPrinter = t->handle;
8875         r.in.pAction = "foobar";
8876         r.in.pReqData = &bidi_req;
8877         r.out.ppRespData = &bidi_rep;
8878
8879         torture_assert_ntstatus_ok(tctx,
8880                 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8881                 "RpcSendRecvBidiData failed");
8882         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8883                 "RpcSendRecvBidiData failed");
8884
8885         if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8886                 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8887         }
8888
8889         r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8890
8891         torture_assert_ntstatus_ok(tctx,
8892                 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8893                 "RpcSendRecvBidiData failed");
8894         torture_assert_werr_ok(tctx, r.out.result,
8895                 "RpcSendRecvBidiData failed");
8896
8897         return true;
8898 }
8899
8900 static bool test_printer_set_publish(struct torture_context *tctx,
8901                                        struct dcerpc_binding_handle *b,
8902                                        struct policy_handle *handle)
8903 {
8904         union spoolss_PrinterInfo info;
8905         struct spoolss_SetPrinterInfo7 info7;
8906         struct spoolss_SetPrinterInfoCtr info_ctr;
8907         struct spoolss_DevmodeContainer devmode_ctr;
8908         struct sec_desc_buf secdesc_ctr;
8909
8910         info7.guid = "";
8911         info7.action = DSPRINT_PUBLISH;
8912
8913         ZERO_STRUCT(info_ctr);
8914         ZERO_STRUCT(devmode_ctr);
8915         ZERO_STRUCT(secdesc_ctr);
8916         info_ctr.level = 7;
8917         info_ctr.info.info7 = &info7;
8918
8919         torture_assert(tctx,
8920                        test_SetPrinter(tctx, b, handle, &info_ctr,
8921                                        &devmode_ctr, &secdesc_ctr, 0), "");
8922
8923         torture_assert(tctx,
8924                        test_GetPrinter_level(tctx, b, handle, 2, &info),
8925                        "");
8926         torture_assert(tctx,
8927                        (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8928                        "info2 publish flag not set");
8929         torture_assert(tctx,
8930                        test_GetPrinter_level(tctx, b, handle, 7, &info),
8931                        "");
8932         if (info.info7.action & DSPRINT_PENDING) {
8933                 torture_comment(tctx, "publish is pending\n");
8934                 torture_assert_int_equal(tctx,
8935                                          info.info7.action,
8936                                          (DSPRINT_PENDING | DSPRINT_PUBLISH),
8937                                          "info7 publish flag not set");
8938         } else {
8939                 struct GUID guid;
8940                 torture_assert_int_equal(tctx,
8941                                          info.info7.action,
8942                                          DSPRINT_PUBLISH,
8943                                          "info7 publish flag not set");
8944                 torture_assert_ntstatus_ok(tctx,
8945                                            GUID_from_string(info.info7.guid,
8946                                            &guid),
8947                                            "invalid published printer GUID");
8948         }
8949
8950         return true;
8951 }
8952
8953 static bool test_printer_set_unpublish(struct torture_context *tctx,
8954                                        struct dcerpc_binding_handle *b,
8955                                        struct policy_handle *handle)
8956 {
8957         union spoolss_PrinterInfo info;
8958         struct spoolss_SetPrinterInfo7 info7;
8959         struct spoolss_SetPrinterInfoCtr info_ctr;
8960         struct spoolss_DevmodeContainer devmode_ctr;
8961         struct sec_desc_buf secdesc_ctr;
8962
8963         info7.action = DSPRINT_UNPUBLISH;
8964         info7.guid = "";
8965
8966         ZERO_STRUCT(info_ctr);
8967         ZERO_STRUCT(devmode_ctr);
8968         ZERO_STRUCT(secdesc_ctr);
8969         info_ctr.level = 7;
8970         info_ctr.info.info7 = &info7;
8971
8972         torture_assert(tctx,
8973                        test_SetPrinter(tctx, b, handle, &info_ctr,
8974                                        &devmode_ctr, &secdesc_ctr, 0), "");
8975
8976         torture_assert(tctx,
8977                        test_GetPrinter_level(tctx, b, handle, 2, &info),
8978                        "");
8979         torture_assert(tctx,
8980                        !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8981                        "info2 publish flag still set");
8982         torture_assert(tctx,
8983                        test_GetPrinter_level(tctx, b, handle, 7, &info),
8984                        "");
8985
8986         if (info.info7.action & DSPRINT_PENDING) {
8987                 struct GUID guid;
8988                 torture_comment(tctx, "unpublish is pending\n");
8989                 torture_assert_int_equal(tctx,
8990                                          info.info7.action,
8991                                          (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8992                                          "info7 unpublish flag not set");
8993                 torture_assert_ntstatus_ok(tctx,
8994                                            GUID_from_string(info.info7.guid,
8995                                            &guid),
8996                                            "invalid printer GUID");
8997         } else {
8998                 torture_assert_int_equal(tctx,
8999                                          info.info7.action, DSPRINT_UNPUBLISH,
9000                                          "info7 unpublish flag not set");
9001         }
9002
9003         return true;
9004 }
9005
9006 static bool test_printer_publish_toggle(struct torture_context *tctx,
9007                                            void *private_data)
9008 {
9009         struct torture_printer_context *t =
9010                 talloc_get_type_abort(private_data,
9011                                       struct torture_printer_context);
9012         struct dcerpc_pipe *p = t->spoolss_pipe;
9013         struct dcerpc_binding_handle *b = p->binding_handle;
9014         struct policy_handle *handle = &t->handle;
9015         union spoolss_PrinterInfo info7;
9016         union spoolss_PrinterInfo info2;
9017
9018         /* check publish status via level 7 and level 2 */
9019         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
9020                        "");
9021         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
9022                        "");
9023
9024         if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
9025                 torture_assert_int_equal(tctx,
9026                                          info7.info7.action, DSPRINT_PUBLISH,
9027                                          "info7 publish flag not set");
9028                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9029                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9030         } else {
9031                 torture_assert_int_equal(tctx,
9032                                          info7.info7.action, DSPRINT_UNPUBLISH,
9033                                          "info7 unpublish flag not set");
9034                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9035                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9036         }
9037
9038         return true;
9039 }
9040
9041 static bool test_driver_info_winreg(struct torture_context *tctx,
9042                                     void *private_data)
9043 {
9044         struct torture_printer_context *t =
9045                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9046         struct dcerpc_pipe *p = t->spoolss_pipe;
9047         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
9048
9049         if (!t->have_driver) {
9050                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
9051         }
9052
9053         torture_assert(tctx,
9054                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
9055                 "failed to test driver info winreg");
9056
9057         return true;
9058 }
9059
9060 static bool test_print_job_enum(struct torture_context *tctx,
9061                                 void *private_data)
9062 {
9063         struct torture_printer_context *t =
9064                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9065         struct dcerpc_pipe *p = t->spoolss_pipe;
9066         struct dcerpc_binding_handle *b = p->binding_handle;
9067         bool ret = true;
9068         uint32_t num_jobs = 8;
9069         uint32_t *job_ids;
9070         int i;
9071         union spoolss_JobInfo *info = NULL;
9072         uint32_t count;
9073
9074         torture_assert(tctx,
9075                 test_PausePrinter(tctx, b, &t->handle),
9076                 "failed to pause printer");
9077
9078         /* purge in case of any jobs from previous tests */
9079         torture_assert(tctx,
9080                 test_printer_purge(tctx, b, &t->handle),
9081                 "failed to purge printer");
9082
9083         /* enum before jobs, valid level */
9084         torture_assert(tctx,
9085                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9086                                           &count, &info),
9087                        "EnumJobs with valid level");
9088         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9089         torture_assert(tctx,
9090                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9091                                           &count, &info),
9092                        "EnumJobs with valid level");
9093         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9094         /* enum before jobs, invalid level - expect failure */
9095         torture_assert(tctx,
9096                        test_EnumJobs_args(tctx, b, &t->handle, 100,
9097                                           WERR_INVALID_LEVEL,
9098                                           &count, &info),
9099                        "EnumJobs with invalid level");
9100
9101         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
9102
9103         for (i = 0; i < num_jobs; i++) {
9104                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
9105                                                     "TorturePrintJob",
9106                                                     &job_ids[i]);
9107                 torture_assert(tctx, ret, "failed to add print job");
9108         }
9109
9110         /* enum after jobs, valid level */
9111         torture_assert(tctx,
9112                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9113                                           &count, &info),
9114                        "EnumJobs with valid level");
9115         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9116         torture_assert(tctx,
9117                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9118                                           &count, &info),
9119                        "EnumJobs with valid level");
9120         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9121         /* enum after jobs, invalid level - expect failure */
9122         torture_assert(tctx,
9123                        test_EnumJobs_args(tctx, b, &t->handle, 100,
9124                                           WERR_INVALID_LEVEL,
9125                                           &count, &info),
9126                        "EnumJobs with invalid level");
9127
9128         for (i = 0; i < num_jobs; i++) {
9129                 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
9130                             SPOOLSS_JOB_CONTROL_DELETE);
9131         }
9132
9133         torture_assert(tctx,
9134                 test_ResumePrinter(tctx, b, &t->handle),
9135                 "failed to resume printer");
9136
9137         return true;
9138 }
9139
9140 void torture_tcase_printer(struct torture_tcase *tcase)
9141 {
9142         torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
9143         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
9144         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
9145         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
9146         torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
9147         torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
9148         torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
9149         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
9150         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
9151         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
9152         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
9153         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
9154         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
9155         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
9156         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
9157         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
9158         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
9159         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
9160         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
9161         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
9162         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
9163         torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
9164         torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
9165         torture_tcase_add_simple_test(tcase, "publish_toggle",
9166                                       test_printer_publish_toggle);
9167         torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
9168 }
9169
9170 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
9171 {
9172         struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
9173         struct torture_tcase *tcase;
9174
9175         tcase = torture_suite_add_tcase(suite, "addprinter");
9176
9177         torture_tcase_set_fixture(tcase,
9178                                   torture_rpc_spoolss_printer_setup,
9179                                   torture_rpc_spoolss_printer_teardown);
9180
9181         torture_tcase_printer(tcase);
9182
9183         tcase = torture_suite_add_tcase(suite, "addprinterex");
9184
9185         torture_tcase_set_fixture(tcase,
9186                                   torture_rpc_spoolss_printerex_setup,
9187                                   torture_rpc_spoolss_printer_teardown);
9188
9189         torture_tcase_printer(tcase);
9190
9191         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
9192
9193         torture_tcase_set_fixture(tcase,
9194                                   torture_rpc_spoolss_printerwkn_setup,
9195                                   torture_rpc_spoolss_printer_teardown);
9196
9197         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
9198
9199         torture_tcase_set_fixture(tcase,
9200                                   torture_rpc_spoolss_printerexwkn_setup,
9201                                   torture_rpc_spoolss_printer_teardown);
9202
9203 #if 0
9204         /* test is not correct */
9205         tcase = torture_suite_add_tcase(suite, "addprinterdm");
9206
9207         torture_tcase_set_fixture(tcase,
9208                                   torture_rpc_spoolss_printerdm_setup,
9209                                   torture_rpc_spoolss_printer_teardown);
9210
9211         torture_tcase_printer(tcase);
9212 #endif
9213         return suite;
9214 }
9215
9216 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
9217 {
9218         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
9219         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
9220
9221         torture_tcase_set_fixture(tcase,
9222                                   torture_rpc_spoolss_setup,
9223                                   torture_rpc_spoolss_teardown);
9224
9225         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
9226         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
9227         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
9228         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
9229         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
9230         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
9231         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
9232         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
9233         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
9234         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
9235         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
9236         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
9237         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
9238         torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
9239         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
9240         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
9241         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
9242         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
9243         torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
9244         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
9245         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
9246         torture_tcase_add_simple_test(tcase, "get_core_printer_drivers", test_get_core_printer_drivers);
9247         torture_tcase_add_simple_test(tcase, "get_printer_driver_package_path", test_get_printer_driver_package_path);
9248
9249         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
9250
9251         return suite;
9252 }
9253
9254 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
9255                                                   struct dcerpc_binding_handle *b,
9256                                                   const char *server,
9257                                                   const char *environment,
9258                                                   const char **dir_p)
9259 {
9260         struct spoolss_GetPrinterDriverDirectory r;
9261         uint32_t needed;
9262
9263         r.in.server             = server;
9264         r.in.environment        = environment;
9265         r.in.level              = 1;
9266         r.in.buffer             = NULL;
9267         r.in.offered            = 0;
9268         r.out.needed            = &needed;
9269
9270         torture_assert_ntstatus_ok(tctx,
9271                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9272                 "failed to query driver directory");
9273
9274         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
9275                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
9276                 r.in.buffer = &blob;
9277                 r.in.offered = needed;
9278
9279                 torture_assert_ntstatus_ok(tctx,
9280                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9281                         "failed to query driver directory");
9282         }
9283
9284         torture_assert_werr_ok(tctx, r.out.result,
9285                 "failed to query driver directory");
9286
9287         if (dir_p) {
9288                 *dir_p = r.out.info->info1.directory_name;
9289         }
9290
9291         return true;
9292 }
9293
9294 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9295 {
9296         if (info_ctr == NULL) {
9297                 return NULL;
9298         }
9299
9300         switch (info_ctr->level) {
9301         case 1:
9302                 return info_ctr->info.info1->driver_name;
9303         case 2:
9304                 return info_ctr->info.info2->driver_name;
9305         case 3:
9306                 return info_ctr->info.info3->driver_name;
9307         case 4:
9308                 return info_ctr->info.info4->driver_name;
9309         case 6:
9310                 return info_ctr->info.info6->driver_name;
9311         case 8:
9312                 return info_ctr->info.info8->driver_name;
9313         default:
9314                 return NULL;
9315         }
9316 }
9317
9318 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9319 {
9320         if (info_ctr == NULL) {
9321                 return NULL;
9322         }
9323
9324         switch (info_ctr->level) {
9325         case 2:
9326                 return info_ctr->info.info2->architecture;
9327         case 3:
9328                 return info_ctr->info.info3->architecture;
9329         case 4:
9330                 return info_ctr->info.info4->architecture;
9331         case 6:
9332                 return info_ctr->info.info6->architecture;
9333         case 8:
9334                 return info_ctr->info.info8->architecture;
9335         default:
9336                 return NULL;
9337         }
9338 }
9339
9340
9341 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
9342                                       struct dcerpc_binding_handle *b,
9343                                       const char *servername,
9344                                       struct spoolss_AddDriverInfoCtr *info_ctr,
9345                                       WERROR expected_result)
9346 {
9347         struct spoolss_AddPrinterDriver r;
9348         const char *drivername = get_driver_from_info(info_ctr);
9349         const char *environment = get_environment_from_info(info_ctr);
9350
9351         r.in.servername = servername;
9352         r.in.info_ctr = info_ctr;
9353
9354         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9355                 drivername, info_ctr->level, environment);
9356
9357         torture_assert_ntstatus_ok(tctx,
9358                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
9359                 "spoolss_AddPrinterDriver failed");
9360         torture_assert_werr_equal(tctx, r.out.result, expected_result,
9361                 "spoolss_AddPrinterDriver failed with unexpected result");
9362
9363         return true;
9364
9365 }
9366
9367 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
9368                                         struct dcerpc_binding_handle *b,
9369                                         const char *servername,
9370                                         struct spoolss_AddDriverInfoCtr *info_ctr,
9371                                         uint32_t flags,
9372                                         WERROR expected_result)
9373 {
9374         struct spoolss_AddPrinterDriverEx r;
9375         const char *drivername = get_driver_from_info(info_ctr);
9376         const char *environment = get_environment_from_info(info_ctr);
9377
9378         r.in.servername = servername;
9379         r.in.info_ctr = info_ctr;
9380         r.in.flags = flags;
9381
9382         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9383                 drivername, info_ctr->level, environment);
9384
9385         torture_assert_ntstatus_ok(tctx,
9386                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
9387                 "AddPrinterDriverEx failed");
9388         torture_assert_werr_equal(tctx, r.out.result, expected_result,
9389                 "AddPrinterDriverEx failed with unexpected result");
9390
9391         return true;
9392 }
9393
9394 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9395         if (path && strlen(path)) {\
9396                 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9397         }
9398
9399 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
9400                                                struct dcerpc_binding_handle *b,
9401                                                const char *server_name,
9402                                                struct spoolss_AddDriverInfo8 *r,
9403                                                uint32_t flags,
9404                                                bool ex,
9405                                                const char *remote_driver_dir)
9406 {
9407         struct spoolss_AddDriverInfoCtr info_ctr;
9408         struct spoolss_AddDriverInfo1 info1;
9409
9410         ZERO_STRUCT(info1);
9411
9412         info_ctr.level = 1;
9413         info_ctr.info.info1 = &info1;
9414
9415         if (ex) {
9416                 torture_assert(tctx,
9417                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9418                         "failed to test AddPrinterDriverEx level 1");
9419         } else {
9420                 torture_assert(tctx,
9421                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9422                         "failed to test AddPrinterDriver level 1");
9423         }
9424
9425         info1.driver_name = r->driver_name;
9426
9427         if (ex) {
9428                 torture_assert(tctx,
9429                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9430                         "failed to test AddPrinterDriverEx level 1");
9431         } else {
9432                 torture_assert(tctx,
9433                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9434                         "failed to test AddPrinterDriver level 1");
9435         }
9436
9437         return true;
9438 }
9439
9440 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
9441                                                struct dcerpc_binding_handle *b,
9442                                                const char *server_name,
9443                                                struct spoolss_AddDriverInfo8 *r,
9444                                                uint32_t flags,
9445                                                bool ex,
9446                                                const char *remote_driver_dir)
9447 {
9448         struct spoolss_AddDriverInfoCtr info_ctr;
9449         struct spoolss_AddDriverInfo2 info2;
9450         union spoolss_DriverInfo info;
9451
9452         ZERO_STRUCT(info2);
9453
9454         info_ctr.level = 2;
9455         info_ctr.info.info2 = &info2;
9456
9457         if (ex) {
9458                 torture_assert(tctx,
9459                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9460                         "failed to test AddPrinterDriverEx level 2");
9461         } else {
9462                 torture_assert(tctx,
9463                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9464                         "failed to test AddPrinterDriver level 2");
9465         }
9466
9467         info2.driver_name = r->driver_name;
9468
9469         if (ex) {
9470                 torture_assert(tctx,
9471                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9472                         "failed to test AddPrinterDriverEx level 2");
9473         } else {
9474                 torture_assert(tctx,
9475                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9476                         "failed to test AddPrinterDriver level 2");
9477         }
9478
9479         info2.version = r->version;
9480
9481         if (ex) {
9482                 torture_assert(tctx,
9483                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9484                         "failed to test AddPrinterDriverEx level 2");
9485         } else {
9486                 torture_assert(tctx,
9487                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9488                         "failed to test AddPrinterDriver level 2");
9489         }
9490
9491         info2.architecture = r->architecture;
9492
9493         if (ex) {
9494                 torture_assert(tctx,
9495                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9496                         "failed to test AddPrinterDriverEx level 2");
9497         } else {
9498                 torture_assert(tctx,
9499                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9500                         "failed to test AddPrinterDriver level 2");
9501         }
9502
9503         info2.driver_path = r->driver_path;
9504
9505         if (ex) {
9506                 torture_assert(tctx,
9507                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9508                         "failed to test AddPrinterDriverEx level 2");
9509         } else {
9510                 torture_assert(tctx,
9511                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9512                         "failed to test AddPrinterDriver level 2");
9513         }
9514
9515         info2.data_file = r->data_file;
9516
9517         if (ex) {
9518                 torture_assert(tctx,
9519                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9520                         "failed to test AddPrinterDriverEx level 2");
9521         } else {
9522                 torture_assert(tctx,
9523                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9524                         "failed to test AddPrinterDriver level 2");
9525         }
9526
9527         info2.config_file = r->config_file;
9528
9529         if (ex) {
9530                 torture_assert(tctx,
9531                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9532                         "failed to test AddPrinterDriverEx");
9533         }
9534
9535         if (ex) {
9536                 torture_assert(tctx,
9537                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9538                         "failed to test AddPrinterDriverEx level 2");
9539         } else {
9540                 torture_assert(tctx,
9541                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9542                         "failed to test AddPrinterDriver level 2");
9543         }
9544
9545         torture_assert(tctx,
9546                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9547                 "failed to find added printer driver");
9548
9549         if (remote_driver_dir) {
9550                 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9551                 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9552                 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9553         }
9554
9555         return true;
9556 }
9557
9558 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9559                                                struct dcerpc_binding_handle *b,
9560                                                const char *server_name,
9561                                                struct spoolss_AddDriverInfo8 *r,
9562                                                uint32_t flags,
9563                                                bool ex,
9564                                                const char *remote_driver_dir)
9565 {
9566         struct spoolss_AddDriverInfoCtr info_ctr;
9567         struct spoolss_AddDriverInfo3 info3;
9568         union spoolss_DriverInfo info;
9569
9570         info3.driver_name       = r->driver_name;
9571         info3.version           = r->version;
9572         info3.architecture      = r->architecture;
9573         info3.driver_path       = r->driver_path;
9574         info3.data_file         = r->data_file;
9575         info3.config_file       = r->config_file;
9576         info3.help_file         = r->help_file;
9577         info3.monitor_name      = r->monitor_name;
9578         info3.default_datatype  = r->default_datatype;
9579         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9580         info3.dependent_files   = r->dependent_files;
9581
9582         info_ctr.level = 3;
9583         info_ctr.info.info3 = &info3;
9584
9585         if (ex) {
9586                 torture_assert(tctx,
9587                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9588                         "failed to test AddPrinterDriverEx level 3");
9589         } else {
9590                 torture_assert(tctx,
9591                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9592                         "failed to test AddPrinterDriver level 3");
9593         }
9594
9595         torture_assert(tctx,
9596                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9597                 "failed to find added printer driver");
9598
9599         if (remote_driver_dir) {
9600                 int i;
9601                 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9602                 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9603                 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9604                 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9605                 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9606                         ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9607                 }
9608         }
9609
9610         return true;
9611 }
9612
9613 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9614                                                struct dcerpc_binding_handle *b,
9615                                                const char *server_name,
9616                                                struct spoolss_AddDriverInfo8 *r,
9617                                                uint32_t flags,
9618                                                bool ex,
9619                                                const char *remote_driver_dir)
9620 {
9621         struct spoolss_AddDriverInfoCtr info_ctr;
9622         struct spoolss_AddDriverInfo4 info4;
9623         union spoolss_DriverInfo info;
9624
9625         info4.version           = r->version;
9626         info4.driver_name       = r->driver_name;
9627         info4.architecture      = r->architecture;
9628         info4.driver_path       = r->driver_path;
9629         info4.data_file         = r->data_file;
9630         info4.config_file       = r->config_file;
9631         info4.help_file         = r->help_file;
9632         info4.monitor_name      = r->monitor_name;
9633         info4.default_datatype  = r->default_datatype;
9634         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9635         info4.dependent_files   = r->dependent_files;
9636         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9637         info4.previous_names = r->previous_names;
9638
9639         info_ctr.level = 4;
9640         info_ctr.info.info4 = &info4;
9641
9642         if (ex) {
9643                 torture_assert(tctx,
9644                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9645                         "failed to test AddPrinterDriverEx level 4");
9646         } else {
9647                 torture_assert(tctx,
9648                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9649                         "failed to test AddPrinterDriver level 4");
9650         }
9651
9652         torture_assert(tctx,
9653                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9654                 "failed to find added printer driver");
9655
9656         if (remote_driver_dir) {
9657                 int i;
9658                 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9659                 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9660                 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9661                 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9662                 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9663                         ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9664                 }
9665         }
9666
9667         return true;
9668 }
9669
9670 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9671                                                struct dcerpc_binding_handle *b,
9672                                                const char *server_name,
9673                                                struct spoolss_AddDriverInfo8 *r,
9674                                                uint32_t flags,
9675                                                bool ex,
9676                                                const char *remote_driver_dir)
9677 {
9678         struct spoolss_AddDriverInfoCtr info_ctr;
9679         struct spoolss_AddDriverInfo6 info6;
9680         union spoolss_DriverInfo info;
9681
9682         info6.version           = r->version;
9683         info6.driver_name       = r->driver_name;
9684         info6.architecture      = r->architecture;
9685         info6.driver_path       = r->driver_path;
9686         info6.data_file         = r->data_file;
9687         info6.config_file       = r->config_file;
9688         info6.help_file         = r->help_file;
9689         info6.monitor_name      = r->monitor_name;
9690         info6.default_datatype  = r->default_datatype;
9691         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9692         info6.dependent_files   = r->dependent_files;
9693         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9694         info6.previous_names    = r->previous_names;
9695         info6.driver_date       = r->driver_date;
9696         info6.driver_version    = r->driver_version;
9697         info6.manufacturer_name = r->manufacturer_name;
9698         info6.manufacturer_url  = r->manufacturer_url;
9699         info6.hardware_id       = r->hardware_id;
9700         info6.provider          = r->provider;
9701
9702         info_ctr.level = 6;
9703         info_ctr.info.info6 = &info6;
9704
9705         if (ex) {
9706                 torture_assert(tctx,
9707                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9708                         "failed to test AddPrinterDriverEx level 6");
9709         } else {
9710                 torture_assert(tctx,
9711                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9712                         "failed to test AddPrinterDriver level 6");
9713         }
9714
9715         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9716
9717         if (!ex) {
9718                 return true;
9719         }
9720
9721         torture_assert(tctx,
9722                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9723                 "failed to find added printer driver");
9724
9725         if (remote_driver_dir) {
9726                 int i;
9727                 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9728                 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9729                 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9730                 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9731                 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9732                         ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9733                 }
9734         }
9735
9736         torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9737         torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9738
9739         return true;
9740 }
9741
9742 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9743                                                struct dcerpc_binding_handle *b,
9744                                                const char *server_name,
9745                                                struct spoolss_AddDriverInfo8 *r,
9746                                                uint32_t flags,
9747                                                bool ex,
9748                                                const char *remote_driver_dir)
9749 {
9750         struct spoolss_AddDriverInfoCtr info_ctr;
9751         union spoolss_DriverInfo info;
9752
9753         info_ctr.level = 8;
9754         info_ctr.info.info8 = r;
9755
9756         if (ex) {
9757                 torture_assert(tctx,
9758                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9759                         "failed to test AddPrinterDriverEx level 8");
9760         } else {
9761                 torture_assert(tctx,
9762                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9763                         "failed to test AddPrinterDriver level 8");
9764         }
9765
9766         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9767
9768         if (!ex) {
9769                 return true;
9770         }
9771
9772         torture_assert(tctx,
9773                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9774                 "failed to find added printer driver");
9775
9776         if (remote_driver_dir) {
9777                 int i;
9778                 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9779                 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9780                 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9781                 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9782                 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9783                         ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9784                 }
9785         }
9786
9787         torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9788         torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9789
9790         return true;
9791 }
9792
9793 #undef ASSERT_DRIVER_PATH
9794
9795 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9796                                          struct dcerpc_binding_handle *b,
9797                                          const char *server,
9798                                          const char *driver,
9799                                          const char *environment,
9800                                          WERROR expected_result)
9801 {
9802         struct spoolss_DeletePrinterDriver r;
9803
9804         r.in.server = server;
9805         r.in.architecture = environment;
9806         r.in.driver = driver;
9807
9808         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9809
9810         torture_assert_ntstatus_ok(tctx,
9811                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9812                 "DeletePrinterDriver failed");
9813         torture_assert_werr_equal(tctx, r.out.result, expected_result,
9814                 "DeletePrinterDriver failed with unexpected result");
9815
9816         return true;
9817 }
9818
9819 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9820                                            struct dcerpc_binding_handle *b,
9821                                            const char *server,
9822                                            const char *driver,
9823                                            const char *environment,
9824                                            uint32_t delete_flags,
9825                                            uint32_t version,
9826                                            WERROR expected_result)
9827 {
9828         struct spoolss_DeletePrinterDriverEx r;
9829
9830         r.in.server = server;
9831         r.in.architecture = environment;
9832         r.in.driver = driver;
9833         r.in.delete_flags = delete_flags;
9834         r.in.version = version;
9835
9836         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9837
9838         torture_assert_ntstatus_ok(tctx,
9839                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9840                 "DeletePrinterDriverEx failed");
9841         torture_assert_werr_equal(tctx, r.out.result, expected_result,
9842                 "DeletePrinterDriverEx failed with unexpected result");
9843
9844         return true;
9845 }
9846
9847 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9848                                      struct dcerpc_binding_handle *b,
9849                                      const char *server_name,
9850                                      const char *driver,
9851                                      const char *environment)
9852 {
9853         torture_assert(tctx,
9854                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9855                 "failed to delete driver");
9856
9857         torture_assert(tctx,
9858                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9859                 "failed to delete driver");
9860
9861         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9862                 torture_fail(tctx, "deleted driver still enumerated");
9863         }
9864
9865         torture_assert(tctx,
9866                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9867                 "2nd delete failed");
9868
9869         return true;
9870 }
9871
9872 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9873                                        struct dcerpc_binding_handle *b,
9874                                        const char *server_name,
9875                                        const char *driver,
9876                                        const char *environment,
9877                                        uint32_t delete_flags,
9878                                        uint32_t version)
9879 {
9880         torture_assert(tctx,
9881                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9882                 "failed to delete driver");
9883
9884         torture_assert(tctx,
9885                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9886                 "failed to delete driver");
9887
9888         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9889                 torture_fail(tctx, "deleted driver still enumerated");
9890         }
9891
9892         torture_assert(tctx,
9893                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9894                 "2nd delete failed");
9895
9896         return true;
9897 }
9898
9899 static bool test_PrinterDriver_args(struct torture_context *tctx,
9900                                     struct dcerpc_binding_handle *b,
9901                                     const char *server_name,
9902                                     uint32_t level,
9903                                     struct spoolss_AddDriverInfo8 *r,
9904                                     uint32_t add_flags,
9905                                     uint32_t delete_flags,
9906                                     uint32_t delete_version,
9907                                     bool ex,
9908                                     const char *remote_driver_dir)
9909 {
9910         bool ret = true;
9911
9912         switch (level) {
9913         case 1:
9914                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9915                 break;
9916         case 2:
9917                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9918                 break;
9919         case 3:
9920                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9921                 break;
9922         case 4:
9923                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9924                 break;
9925         case 6:
9926                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9927                 break;
9928         case 8:
9929                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9930                 break;
9931         default:
9932                 return false;
9933         }
9934
9935         if (ret == false) {
9936                 return ret;
9937         }
9938
9939         if (level == 1) {
9940                 return ret;
9941         }
9942
9943         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9944
9945         if (!ex && (level == 6 || level == 8)) {
9946                 return ret;
9947         }
9948
9949         {
9950                 struct dcerpc_pipe *p2;
9951                 struct policy_handle hive_handle;
9952                 struct dcerpc_binding_handle *b2;
9953
9954                 torture_assert_ntstatus_ok(tctx,
9955                         torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9956                         "could not open winreg pipe");
9957                 b2 = p2->binding_handle;
9958
9959                 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9960
9961                 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9962
9963                 test_winreg_CloseKey(tctx, b2, &hive_handle);
9964
9965                 talloc_free(p2);
9966         }
9967
9968         if (ex) {
9969                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9970         } else {
9971                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9972         }
9973 }
9974
9975 static bool fillup_printserver_info(struct torture_context *tctx,
9976                                     struct dcerpc_pipe *p,
9977                                     struct torture_driver_context *d)
9978 {
9979         struct policy_handle server_handle;
9980         struct dcerpc_binding_handle *b = p->binding_handle;
9981         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9982
9983         torture_assert(tctx,
9984                 test_OpenPrinter_server(tctx, p, &server_handle),
9985                 "failed to open printserver");
9986         torture_assert(tctx,
9987                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9988                 "failed to get environment");
9989         torture_assert(tctx,
9990                 test_ClosePrinter(tctx, b, &server_handle),
9991                 "failed to close printserver");
9992
9993         torture_assert(tctx,
9994                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9995                         d->local.environment ? d->local.environment : d->remote.environment,
9996                         &d->remote.driver_directory),
9997                 "failed to get driver directory");
9998
9999         return true;
10000 }
10001
10002 static const char *driver_directory_dir(const char *driver_directory)
10003 {
10004         char *p;
10005
10006         p = strrchr(driver_directory, '\\');
10007         if (p) {
10008                 return p+1;
10009         }
10010
10011         return NULL;
10012 }
10013
10014 static const char *driver_directory_share(struct torture_context *tctx,
10015                                           const char *driver_directory)
10016 {
10017         const char *p;
10018         char *tok;
10019
10020         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
10021                 driver_directory += 2;
10022         }
10023
10024         p = talloc_strdup(tctx, driver_directory);
10025
10026         torture_assert(tctx,
10027                 next_token_talloc(tctx, &p, &tok, "\\"),
10028                 "cannot explode uri");
10029         torture_assert(tctx,
10030                 next_token_talloc(tctx, &p, &tok, "\\"),
10031                 "cannot explode uri");
10032
10033         return tok;
10034 }
10035
10036 static bool upload_printer_driver_file(struct torture_context *tctx,
10037                                        struct smbcli_state *cli,
10038                                        struct torture_driver_context *d,
10039                                        const char *file_name)
10040 {
10041         XFILE *f;
10042         int fnum;
10043         uint8_t *buf;
10044         int maxwrite = 64512;
10045         off_t nread = 0;
10046         size_t start = 0;
10047         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10048         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
10049         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
10050
10051         if (!file_name || strlen(file_name) == 0) {
10052                 return true;
10053         }
10054
10055         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
10056
10057         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
10058         if (fnum == -1) {
10059                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
10060         }
10061
10062         f = x_fopen(local_name, O_RDONLY, 0);
10063         if (f == NULL) {
10064                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
10065         }
10066
10067         buf = talloc_array(tctx, uint8_t, maxwrite);
10068         if (!buf) {
10069                 x_fclose(f);
10070                 return false;
10071         }
10072
10073         while (!x_feof(f)) {
10074                 int n = maxwrite;
10075                 int ret;
10076
10077                 if ((n = x_fread(buf, 1, n, f)) < 1) {
10078                         if((n == 0) && x_feof(f))
10079                                 break; /* Empty local file. */
10080
10081                         torture_warning(tctx,
10082                                 "failed to read file: %s\n", strerror(errno));
10083                         break;
10084                 }
10085
10086                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
10087
10088                 if (n != ret) {
10089                         torture_warning(tctx,
10090                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
10091                         break;
10092                 }
10093
10094                 nread += n;
10095         }
10096
10097         x_fclose(f);
10098
10099         torture_assert_ntstatus_ok(tctx,
10100                 smbcli_close(cli->tree, fnum),
10101                 "failed to close file");
10102
10103         return true;
10104 }
10105
10106 static bool connect_printer_driver_share(struct torture_context *tctx,
10107                                          const char *server_name,
10108                                          const char *share_name,
10109                                          struct smbcli_state **cli)
10110 {
10111         struct smbcli_options smb_options;
10112         struct smbcli_session_options smb_session_options;
10113
10114         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
10115                 share_name, server_name);
10116
10117         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
10118         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
10119
10120         torture_assert_ntstatus_ok(tctx,
10121                 smbcli_full_connection(tctx, cli, server_name,
10122                                         lpcfg_smb_ports(tctx->lp_ctx),
10123                                         share_name, NULL,
10124                                         lpcfg_socket_options(tctx->lp_ctx),
10125                                         cmdline_credentials,
10126                                         lpcfg_resolve_context(tctx->lp_ctx),
10127                                         tctx->ev,
10128                                         &smb_options,
10129                                         &smb_session_options,
10130                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
10131                 "failed to open driver share");
10132
10133         return true;
10134 }
10135
10136 static bool upload_printer_driver(struct torture_context *tctx,
10137                                   const char *server_name,
10138                                   struct torture_driver_context *d)
10139 {
10140         struct smbcli_state *cli;
10141         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10142         int i;
10143
10144         torture_assert(tctx,
10145                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10146                 "failed to connect to driver share");
10147
10148         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
10149                 server_name, share_name);
10150
10151         torture_assert(tctx,
10152                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10153                 "failed to upload driver_path");
10154         torture_assert(tctx,
10155                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
10156                 "failed to upload data_file");
10157         torture_assert(tctx,
10158                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
10159                 "failed to upload config_file");
10160         torture_assert(tctx,
10161                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
10162                 "failed to upload help_file");
10163         if (d->info8.dependent_files) {
10164                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10165                         torture_assert(tctx,
10166                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10167                                 "failed to upload dependent_files");
10168                 }
10169         }
10170
10171         talloc_free(cli);
10172
10173         return true;
10174 }
10175
10176 static bool check_printer_driver_file(struct torture_context *tctx,
10177                                       struct smbcli_state *cli,
10178                                       struct torture_driver_context *d,
10179                                       const char *file_name)
10180 {
10181         const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
10182         const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
10183                                                   remote_arch_dir,
10184                                                   d->info8.version,
10185                                                   file_name);
10186         int fnum;
10187
10188         torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
10189
10190         torture_comment(tctx, "checking for driver file at %s\n", remote_name);
10191
10192         fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
10193         if (fnum == -1) {
10194                 return false;
10195         }
10196
10197         torture_assert_ntstatus_ok(tctx,
10198                 smbcli_close(cli->tree, fnum),
10199                 "failed to close driver file");
10200
10201         return true;
10202 }
10203
10204 static bool check_printer_driver_files(struct torture_context *tctx,
10205                                        const char *server_name,
10206                                        struct torture_driver_context *d,
10207                                        bool expect_exist)
10208 {
10209         struct smbcli_state *cli;
10210         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10211         int i;
10212
10213         torture_assert(tctx,
10214                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10215                 "failed to connect to driver share");
10216
10217         torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
10218                         (expect_exist ? "": "non-"),
10219                         server_name, share_name);
10220
10221         if (d->info8.driver_path && d->info8.driver_path[0]) {
10222                 torture_assert(tctx,
10223                         check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
10224                         "failed driver_path check");
10225         }
10226         if (d->info8.data_file && d->info8.data_file[0]) {
10227                 torture_assert(tctx,
10228                         check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
10229                         "failed data_file check");
10230         }
10231         if (d->info8.config_file && d->info8.config_file[0]) {
10232                 torture_assert(tctx,
10233                         check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
10234                         "failed config_file check");
10235         }
10236         if (d->info8.help_file && d->info8.help_file[0]) {
10237                 torture_assert(tctx,
10238                         check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
10239                         "failed help_file check");
10240         }
10241         if (d->info8.dependent_files) {
10242                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10243                         torture_assert(tctx,
10244                                 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
10245                                 "failed dependent_files check");
10246                 }
10247         }
10248
10249         talloc_free(cli);
10250
10251         return true;
10252 }
10253
10254 static bool remove_printer_driver_file(struct torture_context *tctx,
10255                                        struct smbcli_state *cli,
10256                                        struct torture_driver_context *d,
10257                                        const char *file_name)
10258 {
10259         const char *remote_name;
10260         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
10261
10262         if (!file_name || strlen(file_name) == 0) {
10263                 return true;
10264         }
10265
10266         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
10267
10268         torture_comment(tctx, "Removing %s\n", remote_name);
10269
10270         torture_assert_ntstatus_ok(tctx,
10271                 smbcli_unlink(cli->tree, remote_name),
10272                 "failed to unlink");
10273
10274         return true;
10275 }
10276
10277 static bool remove_printer_driver(struct torture_context *tctx,
10278                                   const char *server_name,
10279                                   struct torture_driver_context *d)
10280 {
10281         struct smbcli_state *cli;
10282         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10283         int i;
10284
10285         torture_assert(tctx,
10286                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10287                 "failed to connect to driver share");
10288
10289         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
10290                 server_name, share_name);
10291
10292         torture_assert(tctx,
10293                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10294                 "failed to remove driver_path");
10295         torture_assert(tctx,
10296                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
10297                 "failed to remove data_file");
10298         if (!strequal(d->info8.config_file, d->info8.driver_path)) {
10299                 torture_assert(tctx,
10300                         remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
10301                         "failed to remove config_file");
10302         }
10303         torture_assert(tctx,
10304                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
10305                 "failed to remove help_file");
10306         if (d->info8.dependent_files) {
10307                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10308                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
10309                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
10310                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
10311                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
10312                                 continue;
10313                         }
10314                         torture_assert(tctx,
10315                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10316                                 "failed to remove dependent_files");
10317                 }
10318         }
10319
10320         talloc_free(cli);
10321
10322         return true;
10323
10324 }
10325
10326 static bool test_add_driver_arg(struct torture_context *tctx,
10327                                 struct dcerpc_pipe *p,
10328                                 struct torture_driver_context *d)
10329 {
10330         bool ret = true;
10331         struct dcerpc_binding_handle *b = p->binding_handle;
10332         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10333         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
10334         int i;
10335         struct spoolss_AddDriverInfo8 info8;
10336         uint32_t add_flags = APD_COPY_NEW_FILES;
10337         uint32_t delete_flags = 0;
10338
10339         ZERO_STRUCT(info8);
10340
10341         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10342                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
10343
10344         torture_assert(tctx,
10345                 fillup_printserver_info(tctx, p, d),
10346                 "failed to fillup printserver info");
10347
10348         if (!directory_exist(d->local.driver_directory)) {
10349                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10350         }
10351
10352         torture_assert(tctx,
10353                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10354                 "failed to upload printer driver");
10355
10356         info8 = d->info8;
10357         if (d->info8.dependent_files) {
10358                 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
10359                 if (d->info8.dependent_files->string) {
10360                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10361                         }
10362                         info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
10363                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10364                                 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
10365                         }
10366                 }
10367         }
10368         info8.architecture      = d->local.environment;
10369
10370         for (i=0; i < ARRAY_SIZE(levels); i++) {
10371
10372                 if (torture_setting_bool(tctx, "samba3", false)) {
10373                         switch (levels[i]) {
10374                         case 2:
10375                         case 4:
10376                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10377                                 continue;
10378                         default:
10379                                 break;
10380                         }
10381                 }
10382                 if (torture_setting_bool(tctx, "w2k3", false)) {
10383                         switch (levels[i]) {
10384                         case 8:
10385                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10386                                 continue;
10387                         default:
10388                                 break;
10389                         }
10390                 }
10391
10392                 torture_comment(tctx,
10393                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
10394                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10395
10396                 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);
10397         }
10398
10399         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
10400         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
10401         if (d->info8.config_file) {
10402                 info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
10403         }
10404         if (d->info8.help_file) {
10405                 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
10406         }
10407         if (d->info8.dependent_files && d->info8.dependent_files->string) {
10408                 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10409                         info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
10410                 }
10411         }
10412
10413         for (i=0; i < ARRAY_SIZE(levels); i++) {
10414
10415                 if (torture_setting_bool(tctx, "samba3", false)) {
10416                         switch (levels[i]) {
10417                         case 2:
10418                         case 4:
10419                                 continue;
10420                         default:
10421                                 break;
10422                         }
10423                 }
10424                 if (torture_setting_bool(tctx, "w2k3", false)) {
10425                         switch (levels[i]) {
10426                         case 8:
10427                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10428                                 continue;
10429                         default:
10430                                 break;
10431                         }
10432                 }
10433
10434                 torture_comment(tctx,
10435                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10436                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10437
10438                 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);
10439         }
10440
10441         torture_assert(tctx,
10442                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10443                 "failed to remove printer driver");
10444
10445         torture_comment(tctx, "\n");
10446
10447         return ret;
10448 }
10449
10450 static bool test_add_driver_ex_64(struct torture_context *tctx,
10451                                   struct dcerpc_pipe *p)
10452 {
10453         struct torture_driver_context *d;
10454
10455         d = talloc_zero(tctx, struct torture_driver_context);
10456
10457         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10458         d->info8.driver_name            = TORTURE_DRIVER_EX;
10459         d->info8.architecture           = NULL;
10460         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10461         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10462         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10463         d->local.environment            = talloc_strdup(d, "Windows x64");
10464         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10465         d->ex                           = true;
10466
10467         return test_add_driver_arg(tctx, p, d);
10468 }
10469
10470 static bool test_add_driver_ex_32(struct torture_context *tctx,
10471                                   struct dcerpc_pipe *p)
10472 {
10473         struct torture_driver_context *d;
10474
10475         d = talloc_zero(tctx, struct torture_driver_context);
10476
10477         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10478         d->info8.driver_name            = TORTURE_DRIVER_EX;
10479         d->info8.architecture           = NULL;
10480         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10481         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10482         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10483         d->local.environment            = talloc_strdup(d, "Windows NT x86");
10484         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10485         d->ex                           = true;
10486
10487         return test_add_driver_arg(tctx, p, d);
10488 }
10489
10490 static bool test_add_driver_64(struct torture_context *tctx,
10491                                struct dcerpc_pipe *p)
10492 {
10493         struct torture_driver_context *d;
10494
10495         d = talloc_zero(tctx, struct torture_driver_context);
10496
10497         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10498         d->info8.driver_name            = TORTURE_DRIVER;
10499         d->info8.architecture           = NULL;
10500         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10501         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10502         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10503         d->local.environment            = talloc_strdup(d, "Windows x64");
10504         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10505         d->ex                           = false;
10506
10507         return test_add_driver_arg(tctx, p, d);
10508 }
10509
10510 static bool test_add_driver_32(struct torture_context *tctx,
10511                                struct dcerpc_pipe *p)
10512 {
10513         struct torture_driver_context *d;
10514
10515         d = talloc_zero(tctx, struct torture_driver_context);
10516
10517         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10518         d->info8.driver_name            = TORTURE_DRIVER;
10519         d->info8.architecture           = NULL;
10520         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10521         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10522         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10523         d->local.environment            = talloc_strdup(d, "Windows NT x86");
10524         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10525         d->ex                           = false;
10526
10527         return test_add_driver_arg(tctx, p, d);
10528 }
10529
10530 static bool test_add_driver_adobe(struct torture_context *tctx,
10531                                   struct dcerpc_pipe *p)
10532 {
10533         struct torture_driver_context *d;
10534
10535         if (!torture_setting_bool(tctx, "samba3", false)) {
10536                 torture_skip(tctx, "skipping adobe test which only works against samba3");
10537         }
10538
10539         d = talloc_zero(tctx, struct torture_driver_context);
10540
10541         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
10542         d->info8.driver_name            = TORTURE_DRIVER_ADOBE;
10543         d->info8.architecture           = NULL;
10544         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
10545         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
10546         d->info8.config_file            = talloc_strdup(d, "ADOBEPS4.DRV");
10547 #if 0
10548         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
10549         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
10550 #endif
10551         d->local.environment            = talloc_strdup(d, "Windows 4.0");
10552         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10553         d->ex                           = false;
10554
10555         return test_add_driver_arg(tctx, p, d);
10556 }
10557
10558 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
10559                                              struct dcerpc_pipe *p)
10560 {
10561         struct torture_driver_context *d;
10562         struct spoolss_StringArray *a;
10563
10564         if (!torture_setting_bool(tctx, "samba3", false)) {
10565                 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10566         }
10567
10568         d = talloc_zero(tctx, struct torture_driver_context);
10569
10570         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
10571         d->info8.driver_name            = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10572         d->info8.architecture           = NULL;
10573         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
10574         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
10575         d->info8.config_file            = NULL;
10576         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
10577         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
10578         d->info8.default_datatype       = talloc_strdup(d, "RAW");
10579
10580         a                               = talloc_zero(d, struct spoolss_StringArray);
10581         a->string                       = talloc_zero_array(a, const char *, 7);
10582         a->string[0]                    = talloc_strdup(a->string, "ADOBEPS4.DRV");
10583         a->string[1]                    = talloc_strdup(a->string, "DEFPRTR2.PPD");
10584         a->string[2]                    = talloc_strdup(a->string, "ADOBEPS4.HLP");
10585         a->string[3]                    = talloc_strdup(a->string, "PSMON.DLL");
10586         a->string[4]                    = talloc_strdup(a->string, "ADFONTS.MFM");
10587         a->string[5]                    = talloc_strdup(a->string, "ICONLIB.DLL");
10588
10589         d->info8.dependent_files        = a;
10590         d->local.environment            = talloc_strdup(d, "Windows 4.0");
10591         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10592         d->ex                           = false;
10593
10594         return test_add_driver_arg(tctx, p, d);
10595 }
10596
10597 static bool test_add_driver_timestamps(struct torture_context *tctx,
10598                                        struct dcerpc_pipe *p)
10599 {
10600         struct torture_driver_context *d;
10601         struct timeval t = timeval_current();
10602
10603         d = talloc_zero(tctx, struct torture_driver_context);
10604
10605         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10606         d->info8.driver_name            = TORTURE_DRIVER_TIMESTAMPS;
10607         d->info8.architecture           = NULL;
10608         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10609         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10610         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10611         d->info8.driver_date            = timeval_to_nttime(&t);
10612         d->local.environment            = talloc_strdup(d, "Windows NT x86");
10613         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10614         d->ex                           = true;
10615
10616         torture_assert(tctx,
10617                 test_add_driver_arg(tctx, p, d),
10618                 "");
10619
10620         unix_to_nt_time(&d->info8.driver_date, 1);
10621
10622         torture_assert(tctx,
10623                 test_add_driver_arg(tctx, p, d),
10624                 "");
10625
10626         return true;
10627 }
10628
10629 static bool test_multiple_drivers(struct torture_context *tctx,
10630                                   struct dcerpc_pipe *p)
10631 {
10632         struct torture_driver_context *d;
10633         struct dcerpc_binding_handle *b = p->binding_handle;
10634         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10635         int i;
10636         struct spoolss_AddDriverInfo8 info8;
10637         uint32_t add_flags = APD_COPY_NEW_FILES;
10638         uint32_t delete_flags = 0;
10639
10640         d = talloc_zero(tctx, struct torture_driver_context);
10641
10642         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10643         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10644         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10645         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10646         d->local.environment            = talloc_strdup(d, "Windows NT x86");
10647         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10648         d->ex                           = true;
10649
10650         torture_assert(tctx,
10651                 fillup_printserver_info(tctx, p, d),
10652                 "failed to fillup printserver info");
10653
10654         if (!directory_exist(d->local.driver_directory)) {
10655                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10656         }
10657
10658         torture_assert(tctx,
10659                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10660                 "failed to upload printer driver");
10661
10662         info8 = d->info8;
10663         info8.architecture      = d->local.environment;
10664
10665         for (i=0; i < 3; i++) {
10666                 info8.driver_name               = talloc_asprintf(d, "torture_test_driver_%d", i);
10667
10668                 torture_assert(tctx,
10669                         test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10670                         "failed to add driver");
10671         }
10672
10673         torture_assert(tctx,
10674                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10675                 "failed to delete driver");
10676
10677         torture_assert(tctx,
10678                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10679                 "torture_test_driver_1 no longer on the server");
10680
10681         torture_assert(tctx,
10682                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10683                 "torture_test_driver_2 no longer on the server");
10684
10685         torture_assert(tctx,
10686                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10687                 "failed to delete driver");
10688
10689         torture_assert(tctx,
10690                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10691                 "torture_test_driver_2 no longer on the server");
10692
10693         torture_assert(tctx,
10694                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10695                 "failed to delete driver");
10696
10697         torture_assert(tctx,
10698                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10699                 "failed to remove printer driver");
10700
10701         return true;
10702 }
10703
10704 static bool test_del_driver_all_files(struct torture_context *tctx,
10705                                       struct dcerpc_pipe *p)
10706 {
10707         struct torture_driver_context *d;
10708         struct spoolss_StringArray *a;
10709         uint32_t add_flags = APD_COPY_NEW_FILES;
10710         uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10711         struct dcerpc_binding_handle *b = p->binding_handle;
10712         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10713
10714         d = talloc_zero(tctx, struct torture_driver_context);
10715
10716         d->ex                           = true;
10717         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
10718         d->info8.driver_name            = TORTURE_DRIVER_DELETER;
10719         d->info8.architecture           = NULL;
10720         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
10721         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
10722         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
10723         d->info8.help_file              = talloc_strdup(d, "pscript.hlp");
10724         d->local.environment            = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10725         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10726
10727         a                               = talloc_zero(d, struct spoolss_StringArray);
10728         a->string                       = talloc_zero_array(a, const char *, 3);
10729         a->string[0]                    = talloc_strdup(a->string, "cups6.inf");
10730         a->string[1]                    = talloc_strdup(a->string, "cups6.ini");
10731
10732         d->info8.dependent_files        = a;
10733         d->info8.architecture           = d->local.environment;
10734
10735         torture_assert(tctx,
10736                 fillup_printserver_info(tctx, p, d),
10737                 "failed to fillup printserver info");
10738
10739         if (!directory_exist(d->local.driver_directory)) {
10740                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10741         }
10742
10743         torture_assert(tctx,
10744                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10745                 "failed to upload printer driver");
10746
10747         torture_assert(tctx,
10748                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10749                 "failed to add driver");
10750
10751         torture_assert(tctx,
10752                 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10753                                            d->info8.driver_name,
10754                                            d->local.environment,
10755                                            delete_flags,
10756                                            d->info8.version),
10757                 "failed to delete driver");
10758
10759         torture_assert(tctx,
10760                 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10761                 "printer driver file check failed");
10762
10763         talloc_free(d);
10764         return true;
10765 }
10766
10767 static bool test_del_driver_unused_files(struct torture_context *tctx,
10768                                          struct dcerpc_pipe *p)
10769 {
10770         struct torture_driver_context *d1;
10771         struct torture_driver_context *d2;
10772         uint32_t add_flags = APD_COPY_NEW_FILES;
10773         struct dcerpc_binding_handle *b = p->binding_handle;
10774         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10775
10776         d1 = talloc_zero(tctx, struct torture_driver_context);
10777         d1->ex                          = true;
10778         d1->info8.version               = SPOOLSS_DRIVER_VERSION_200X;
10779         d1->info8.driver_name           = TORTURE_DRIVER_DELETER;
10780         d1->info8.architecture          = NULL;
10781         d1->info8.driver_path           = talloc_strdup(d1, "pscript5.dll");
10782         d1->info8.data_file             = talloc_strdup(d1, "cups6.ppd");
10783         d1->info8.config_file           = talloc_strdup(d1, "cupsui6.dll");
10784         d1->info8.help_file             = talloc_strdup(d1, "pscript.hlp");
10785         d1->local.environment           = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10786         d1->local.driver_directory      = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10787         d1->info8.architecture          = d1->local.environment;
10788
10789         d2 = talloc_zero(tctx, struct torture_driver_context);
10790         d2->ex                          = true;
10791         d2->info8.version               = SPOOLSS_DRIVER_VERSION_200X;
10792         d2->info8.driver_name           = TORTURE_DRIVER_DELETERIN;
10793         d2->info8.architecture          = NULL;
10794         d2->info8.driver_path           = talloc_strdup(d2, "pscript5.dll");    /* overlapping */
10795         d2->info8.data_file             = talloc_strdup(d2, "cupsps6.dll");
10796         d2->info8.config_file           = talloc_strdup(d2, "cups6.ini");
10797         d2->info8.help_file             = talloc_strdup(d2, "pscript.hlp");     /* overlapping */
10798         d2->local.environment           = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10799         d2->local.driver_directory      = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10800         d2->info8.architecture          = d2->local.environment;
10801
10802         torture_assert(tctx,
10803                 fillup_printserver_info(tctx, p, d1),
10804                 "failed to fillup printserver info");
10805         torture_assert(tctx,
10806                 fillup_printserver_info(tctx, p, d2),
10807                 "failed to fillup printserver info");
10808
10809         if (!directory_exist(d1->local.driver_directory)) {
10810                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10811         }
10812
10813         torture_assert(tctx,
10814                 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10815                 "failed to upload printer driver");
10816         torture_assert(tctx,
10817                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10818                 "failed to add driver");
10819
10820         torture_assert(tctx,
10821                 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10822                 "failed to upload printer driver");
10823         torture_assert(tctx,
10824                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10825                 "failed to add driver");
10826
10827         /* some files are in use by a separate driver, should fail */
10828         torture_assert(tctx,
10829                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10830                                                d1->info8.driver_name,
10831                                                d1->local.environment,
10832                                                DPD_DELETE_ALL_FILES,
10833                                                d1->info8.version,
10834                                                WERR_PRINTER_DRIVER_IN_USE),
10835                 "invalid delete driver response");
10836
10837         /* should only delete files not in use by other driver */
10838         torture_assert(tctx,
10839                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10840                                                d1->info8.driver_name,
10841                                                d1->local.environment,
10842                                                DPD_DELETE_UNUSED_FILES,
10843                                                d1->info8.version,
10844                                                WERR_OK),
10845                 "failed to delete driver (unused files)");
10846
10847         /* check non-overlapping were deleted */
10848         d1->info8.driver_path = NULL;
10849         d1->info8.help_file = NULL;
10850         torture_assert(tctx,
10851                 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10852                 "printer driver file check failed");
10853         /* d2 files should be uneffected */
10854         torture_assert(tctx,
10855                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10856                 "printer driver file check failed");
10857
10858         torture_assert(tctx,
10859                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10860                                                d2->info8.driver_name,
10861                                                d2->local.environment,
10862                                                DPD_DELETE_ALL_FILES,
10863                                                d2->info8.version,
10864                                                WERR_OK),
10865                 "failed to delete driver");
10866
10867         torture_assert(tctx,
10868                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10869                 "printer driver file check failed");
10870
10871         talloc_free(d1);
10872         talloc_free(d2);
10873         return true;
10874 }
10875
10876 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10877 {
10878         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10879
10880         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10881                                                         "driver", &ndr_table_spoolss);
10882         torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10883         torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10884
10885         torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10886         torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10887
10888         torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10889
10890         torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10891
10892         torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10893
10894         torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10895
10896         torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10897
10898         torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10899
10900         return suite;
10901 }