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