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