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