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