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