b1229ac3aab836e54e49ffdb6afa65a7883d754f
[kai/samba.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2011
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
44
45 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
46 #define TORTURE_PRINTER                 "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX              "torture_printer_ex"
49 #define TORTURE_DRIVER                  "torture_driver"
50 #define TORTURE_DRIVER_EX               "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE            "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE         "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS       "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER          "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN        "torture_driver_deleterin"
57 #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           = 0;
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           = 0;
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 = 0;
1421                 r->info.info2->devmode_ptr = 0;
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 = 0;
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 = 0;
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
2675         if (level != 1) {
2676                 torture_skip(tctx, "only level 1 supported");
2677         }
2678
2679         r.in.handle     = handle;
2680         r.in.level      = level;
2681         r.in.info       = *info;
2682
2683         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2684                 r.in.info.info1->form_name, r.in.level,
2685                 r.in.info.info1->flags);
2686
2687         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2688                 "AddForm failed");
2689         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2690                 "AddForm gave unexpected result");
2691
2692         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2693                 "2nd AddForm failed");
2694         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2695                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2696                         "2nd AddForm gave unexpected result");
2697         } else {
2698                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2699                         "2nd AddForm gave unexpected result");
2700         }
2701
2702         return true;
2703 }
2704
2705 static bool test_SetForm(struct torture_context *tctx,
2706                          struct dcerpc_binding_handle *b,
2707                          struct policy_handle *handle,
2708                          const char *form_name,
2709                          uint32_t level,
2710                          union spoolss_AddFormInfo *info)
2711 {
2712         struct spoolss_SetForm r;
2713
2714         r.in.handle     = handle;
2715         r.in.form_name  = form_name;
2716         r.in.level      = level;
2717         r.in.info       = *info;
2718
2719         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2720                 form_name, r.in.level);
2721
2722         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2723                 "SetForm failed");
2724
2725         torture_assert_werr_ok(tctx, r.out.result,
2726                 "SetForm failed");
2727
2728         return true;
2729 }
2730
2731 static bool test_GetForm_winreg(struct torture_context *tctx,
2732                                 struct dcerpc_binding_handle *b,
2733                                 struct policy_handle *handle,
2734                                 const char *key_name,
2735                                 const char *form_name,
2736                                 enum winreg_Type *w_type,
2737                                 uint32_t *w_size,
2738                                 uint32_t *w_length,
2739                                 uint8_t **w_data);
2740
2741 static bool test_Forms_args(struct torture_context *tctx,
2742                             struct dcerpc_binding_handle *b,
2743                             struct policy_handle *handle,
2744                             bool print_server,
2745                             const char *printer_name,
2746                             struct dcerpc_binding_handle *winreg_handle,
2747                             struct policy_handle *hive_handle,
2748                             const char *form_name,
2749                             struct spoolss_AddFormInfo1 *info1,
2750                             WERROR expected_add_result,
2751                             WERROR expected_delete_result)
2752 {
2753         union spoolss_FormInfo info;
2754         union spoolss_AddFormInfo add_info;
2755
2756         enum winreg_Type w_type;
2757         uint32_t w_size;
2758         uint32_t w_length;
2759         uint8_t *w_data;
2760
2761         add_info.info1 = info1;
2762
2763         torture_assert(tctx,
2764                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2765                 "failed to add form");
2766
2767         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2768
2769                 struct spoolss_FormInfo1 i1;
2770
2771                 torture_assert(tctx,
2772                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2773                         "failed to get form via winreg");
2774
2775                 i1.size.width   = IVAL(w_data, 0);
2776                 i1.size.height  = IVAL(w_data, 4);
2777                 i1.area.left    = IVAL(w_data, 8);
2778                 i1.area.top     = IVAL(w_data, 12);
2779                 i1.area.right   = IVAL(w_data, 16);
2780                 i1.area.bottom  = IVAL(w_data, 20);
2781                 /* skip index here */
2782                 i1.flags        = IVAL(w_data, 28);
2783
2784                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2785                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2786                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2787                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2788                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2789                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2790                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2791                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2792                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2793                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2794         }
2795
2796         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2797                 torture_assert(tctx,
2798                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2799                         "failed to get added form");
2800
2801                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2802                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2803                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2804                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2805                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2806                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2807                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2808
2809                 if (winreg_handle && hive_handle) {
2810
2811                         struct spoolss_FormInfo1 i1;
2812
2813                         i1.size.width   = IVAL(w_data, 0);
2814                         i1.size.height  = IVAL(w_data, 4);
2815                         i1.area.left    = IVAL(w_data, 8);
2816                         i1.area.top     = IVAL(w_data, 12);
2817                         i1.area.right   = IVAL(w_data, 16);
2818                         i1.area.bottom  = IVAL(w_data, 20);
2819                         /* skip index here */
2820                         i1.flags        = IVAL(w_data, 28);
2821
2822                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2823                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2824                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2825                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2826                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2827                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2828                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2829                 }
2830
2831                 add_info.info1->size.width = 1234;
2832
2833                 torture_assert(tctx,
2834                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2835                         "failed to set form");
2836                 torture_assert(tctx,
2837                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2838                         "failed to get setted form");
2839
2840                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2841         }
2842
2843         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2844                 torture_assert(tctx,
2845                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2846                         "Newly added form not found in enum call");
2847         }
2848
2849         torture_assert(tctx,
2850                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2851                 "failed to delete form");
2852
2853         return true;
2854 }
2855
2856 static bool test_Forms(struct torture_context *tctx,
2857                        struct dcerpc_binding_handle *b,
2858                        struct policy_handle *handle,
2859                        bool print_server,
2860                        const char *printer_name,
2861                        struct dcerpc_binding_handle *winreg_handle,
2862                        struct policy_handle *hive_handle)
2863 {
2864         const struct spoolss_FormSize size = {
2865                 .width  = 50,
2866                 .height = 25
2867         };
2868         const struct spoolss_FormArea area = {
2869                 .left   = 5,
2870                 .top    = 10,
2871                 .right  = 45,
2872                 .bottom = 15
2873         };
2874         int i;
2875
2876         struct {
2877                 struct spoolss_AddFormInfo1 info1;
2878                 WERROR expected_add_result;
2879                 WERROR expected_delete_result;
2880         } forms[] = {
2881                 {
2882                         .info1 = {
2883                                 .flags          = SPOOLSS_FORM_USER,
2884                                 .form_name      = "testform_user",
2885                                 .size           = size,
2886                                 .area           = area,
2887                         },
2888                         .expected_add_result    = WERR_OK,
2889                         .expected_delete_result = WERR_OK
2890                 },
2891 /*
2892                 weird, we can add a builtin form but we can never remove it
2893                 again - gd
2894
2895                 {
2896                         .info1 = {
2897                                 .flags          = SPOOLSS_FORM_BUILTIN,
2898                                 .form_name      = "testform_builtin",
2899                                 .size           = size,
2900                                 .area           = area,
2901                         },
2902                         .expected_add_result    = WERR_OK,
2903                         .expected_delete_result = WERR_INVALID_PARAM,
2904                 },
2905 */
2906                 {
2907                         .info1 = {
2908                                 .flags          = SPOOLSS_FORM_PRINTER,
2909                                 .form_name      = "testform_printer",
2910                                 .size           = size,
2911                                 .area           = area,
2912                         },
2913                         .expected_add_result    = WERR_OK,
2914                         .expected_delete_result = WERR_OK
2915                 },
2916                 {
2917                         .info1 = {
2918                                 .flags          = SPOOLSS_FORM_USER,
2919                                 .form_name      = "Letter",
2920                                 .size           = size,
2921                                 .area           = area,
2922                         },
2923                         .expected_add_result    = WERR_FILE_EXISTS,
2924                         .expected_delete_result = WERR_INVALID_PARAM
2925                 },
2926                 {
2927                         .info1 = {
2928                                 .flags          = SPOOLSS_FORM_BUILTIN,
2929                                 .form_name      = "Letter",
2930                                 .size           = size,
2931                                 .area           = area,
2932                         },
2933                         .expected_add_result    = WERR_FILE_EXISTS,
2934                         .expected_delete_result = WERR_INVALID_PARAM
2935                 },
2936                 {
2937                         .info1 = {
2938                                 .flags          = SPOOLSS_FORM_PRINTER,
2939                                 .form_name      = "Letter",
2940                                 .size           = size,
2941                                 .area           = area,
2942                         },
2943                         .expected_add_result    = WERR_FILE_EXISTS,
2944                         .expected_delete_result = WERR_INVALID_PARAM
2945                 },
2946                 {
2947                         .info1 = {
2948                                 .flags          = 12345,
2949                                 .form_name      = "invalid_flags",
2950                                 .size           = size,
2951                                 .area           = area,
2952                         },
2953                         .expected_add_result    = WERR_INVALID_PARAM,
2954                         .expected_delete_result = WERR_INVALID_FORM_NAME
2955                 }
2956
2957         };
2958
2959         for (i=0; i < ARRAY_SIZE(forms); i++) {
2960                 torture_assert(tctx,
2961                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2962                                         winreg_handle, hive_handle,
2963                                         forms[i].info1.form_name,
2964                                         &forms[i].info1,
2965                                         forms[i].expected_add_result,
2966                                         forms[i].expected_delete_result),
2967                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2968         }
2969
2970         return true;
2971 }
2972
2973 static bool test_EnumPorts_old(struct torture_context *tctx,
2974                                void *private_data)
2975 {
2976         struct test_spoolss_context *ctx =
2977                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2978
2979         NTSTATUS status;
2980         struct spoolss_EnumPorts r;
2981         uint32_t needed;
2982         uint32_t count;
2983         union spoolss_PortInfo *info;
2984         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2985         struct dcerpc_binding_handle *b = p->binding_handle;
2986
2987         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2988                                           dcerpc_server_name(p));
2989         r.in.level = 2;
2990         r.in.buffer = NULL;
2991         r.in.offered = 0;
2992         r.out.needed = &needed;
2993         r.out.count = &count;
2994         r.out.info = &info;
2995
2996         torture_comment(tctx, "Testing EnumPorts\n");
2997
2998         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2999
3000         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3001
3002         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3003                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3004                 r.in.buffer = &blob;
3005                 r.in.offered = needed;
3006
3007                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3008                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3009                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3010
3011                 torture_assert(tctx, info, "No ports returned");
3012         }
3013
3014         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3015
3016         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3017
3018         return true;
3019 }
3020
3021 static bool test_AddPort(struct torture_context *tctx,
3022                          void *private_data)
3023 {
3024         struct test_spoolss_context *ctx =
3025                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3026
3027         NTSTATUS status;
3028         struct spoolss_AddPort r;
3029         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3030         struct dcerpc_binding_handle *b = p->binding_handle;
3031
3032         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3033                                            dcerpc_server_name(p));
3034         r.in.unknown = 0;
3035         r.in.monitor_name = "foo";
3036
3037         torture_comment(tctx, "Testing AddPort\n");
3038
3039         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3040
3041         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3042
3043         /* win2k3 returns WERR_NOT_SUPPORTED */
3044
3045 #if 0
3046
3047         if (!W_ERROR_IS_OK(r.out.result)) {
3048                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3049                 return false;
3050         }
3051
3052 #endif
3053
3054         return true;
3055 }
3056
3057 static bool test_GetJob_args(struct torture_context *tctx,
3058                              struct dcerpc_binding_handle *b,
3059                              struct policy_handle *handle,
3060                              uint32_t job_id,
3061                              uint32_t level,
3062                              union spoolss_JobInfo *info_p)
3063 {
3064         NTSTATUS status;
3065         struct spoolss_GetJob r;
3066         union spoolss_JobInfo info;
3067         uint32_t needed;
3068
3069         r.in.handle = handle;
3070         r.in.job_id = job_id;
3071         r.in.level = level;
3072         r.in.buffer = NULL;
3073         r.in.offered = 0;
3074         r.out.needed = &needed;
3075         r.out.info = &info;
3076
3077         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3078
3079         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3080         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3081         if (level == 0) {
3082                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3083         }
3084
3085         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3086                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3087                 r.in.buffer = &blob;
3088                 r.in.offered = needed;
3089
3090                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3091                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3092         }
3093
3094         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3095         torture_assert(tctx, r.out.info, "No job info returned");
3096
3097         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3098
3099         if (info_p) {
3100                 *info_p = *r.out.info;
3101         }
3102
3103         return true;
3104 }
3105
3106 static bool test_GetJob(struct torture_context *tctx,
3107                         struct dcerpc_binding_handle *b,
3108                         struct policy_handle *handle,
3109                         uint32_t job_id)
3110 {
3111         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3112         uint32_t i;
3113
3114         for (i=0; i < ARRAY_SIZE(levels); i++) {
3115                 torture_assert(tctx,
3116                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3117                         "GetJob failed");
3118         }
3119
3120         return true;
3121 }
3122
3123 static bool test_SetJob(struct torture_context *tctx,
3124                         struct dcerpc_binding_handle *b,
3125                         struct policy_handle *handle,
3126                         uint32_t job_id,
3127                         struct spoolss_JobInfoContainer *ctr,
3128                         enum spoolss_JobControl command)
3129 {
3130         NTSTATUS status;
3131         struct spoolss_SetJob r;
3132
3133         r.in.handle     = handle;
3134         r.in.job_id     = job_id;
3135         r.in.ctr        = ctr;
3136         r.in.command    = command;
3137
3138         switch (command) {
3139         case SPOOLSS_JOB_CONTROL_PAUSE:
3140                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3141                 break;
3142         case SPOOLSS_JOB_CONTROL_RESUME:
3143                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3144                 break;
3145         case SPOOLSS_JOB_CONTROL_CANCEL:
3146                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3147                 break;
3148         case SPOOLSS_JOB_CONTROL_RESTART:
3149                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3150                 break;
3151         case SPOOLSS_JOB_CONTROL_DELETE:
3152                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3153                 break;
3154         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3155                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3156                 break;
3157         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3158                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3159                 break;
3160         case SPOOLSS_JOB_CONTROL_RETAIN:
3161                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3162                 break;
3163         case SPOOLSS_JOB_CONTROL_RELEASE:
3164                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3165                 break;
3166         default:
3167                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3168                 break;
3169         }
3170
3171         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3172         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3173         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3174
3175         return true;
3176 }
3177
3178 static bool test_AddJob(struct torture_context *tctx,
3179                         struct dcerpc_binding_handle *b,
3180                         struct policy_handle *handle)
3181 {
3182         NTSTATUS status;
3183         struct spoolss_AddJob r;
3184         uint32_t needed;
3185
3186         r.in.level = 0;
3187         r.in.handle = handle;
3188         r.in.offered = 0;
3189         r.out.needed = &needed;
3190         r.in.buffer = r.out.buffer = NULL;
3191
3192         torture_comment(tctx, "Testing AddJob\n");
3193
3194         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3195         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3196
3197         r.in.level = 1;
3198
3199         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3200         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3201
3202         return true;
3203 }
3204
3205
3206 static bool test_EnumJobs_args(struct torture_context *tctx,
3207                                struct dcerpc_binding_handle *b,
3208                                struct policy_handle *handle,
3209                                uint32_t level,
3210                                uint32_t *count_p,
3211                                union spoolss_JobInfo **info_p)
3212 {
3213         NTSTATUS status;
3214         struct spoolss_EnumJobs r;
3215         uint32_t needed;
3216         uint32_t count;
3217         union spoolss_JobInfo *info;
3218
3219         r.in.handle = handle;
3220         r.in.firstjob = 0;
3221         r.in.numjobs = 0xffffffff;
3222         r.in.level = level;
3223         r.in.buffer = NULL;
3224         r.in.offered = 0;
3225         r.out.needed = &needed;
3226         r.out.count = &count;
3227         r.out.info = &info;
3228
3229         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3230
3231         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3232
3233         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3234
3235         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3236                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3237                 r.in.buffer = &blob;
3238                 r.in.offered = needed;
3239
3240                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3241
3242                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3243                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3244                 torture_assert(tctx, info, "No jobs returned");
3245
3246                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3247
3248         } else {
3249                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3250         }
3251
3252         if (count_p) {
3253                 *count_p = count;
3254         }
3255         if (info_p) {
3256                 *info_p = info;
3257         }
3258
3259         return true;
3260 }
3261
3262 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3263                                          struct dcerpc_binding_handle *b,
3264                                          struct policy_handle *handle,
3265                                          const char *document_name,
3266                                          uint32_t *job_id)
3267 {
3268         NTSTATUS status;
3269         struct spoolss_StartDocPrinter s;
3270         struct spoolss_DocumentInfo1 info1;
3271         struct spoolss_StartPagePrinter sp;
3272         struct spoolss_WritePrinter w;
3273         struct spoolss_EndPagePrinter ep;
3274         struct spoolss_EndDocPrinter e;
3275         int i;
3276         uint32_t num_written;
3277
3278         torture_comment(tctx, "Testing StartDocPrinter\n");
3279
3280         s.in.handle             = handle;
3281         s.in.level              = 1;
3282         s.in.info.info1         = &info1;
3283         s.out.job_id            = job_id;
3284         info1.document_name     = document_name;
3285         info1.output_file       = NULL;
3286         info1.datatype          = "RAW";
3287
3288         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3289         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3290         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3291
3292         for (i=1; i < 4; i++) {
3293                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3294
3295                 sp.in.handle            = handle;
3296
3297                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3298                 torture_assert_ntstatus_ok(tctx, status,
3299                                            "dcerpc_spoolss_StartPagePrinter failed");
3300                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3301
3302                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3303
3304                 w.in.handle             = handle;
3305                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3306                 w.out.num_written       = &num_written;
3307
3308                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3309                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3310                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3311
3312                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3313
3314                 ep.in.handle            = handle;
3315
3316                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3317                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3318                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3319         }
3320
3321         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3322
3323         e.in.handle = handle;
3324
3325         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3326         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3327         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3328
3329         return true;
3330 }
3331
3332 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3333                                         struct dcerpc_binding_handle *b,
3334                                         struct policy_handle *handle,
3335                                         uint32_t num_jobs,
3336                                         uint32_t *job_ids)
3337 {
3338         uint32_t count;
3339         union spoolss_JobInfo *info = NULL;
3340         int i;
3341
3342         torture_assert(tctx,
3343                 test_AddJob(tctx, b, handle),
3344                 "AddJob failed");
3345
3346         torture_assert(tctx,
3347                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3348                 "EnumJobs level 1 failed");
3349
3350         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3351
3352         for (i=0; i < num_jobs; i++) {
3353                 union spoolss_JobInfo ginfo;
3354                 const char *document_name;
3355                 const char *new_document_name = "any_other_docname";
3356                 struct spoolss_JobInfoContainer ctr;
3357                 struct spoolss_SetJobInfo1 info1;
3358
3359                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3360
3361                 torture_assert(tctx,
3362                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3363                         "failed to call test_GetJob");
3364
3365                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3366
3367                 document_name = ginfo.info1.document_name;
3368
3369                 info1.job_id            = ginfo.info1.job_id;
3370                 info1.printer_name      = ginfo.info1.printer_name;
3371                 info1.server_name       = ginfo.info1.server_name;
3372                 info1.user_name         = ginfo.info1.user_name;
3373                 info1.document_name     = new_document_name;
3374                 info1.data_type         = ginfo.info1.data_type;
3375                 info1.text_status       = ginfo.info1.text_status;
3376                 info1.status            = ginfo.info1.status;
3377                 info1.priority          = ginfo.info1.priority;
3378                 info1.position          = ginfo.info1.position;
3379                 info1.total_pages       = ginfo.info1.total_pages;
3380                 info1.pages_printed     = ginfo.info1.pages_printed;
3381                 info1.submitted         = ginfo.info1.submitted;
3382
3383                 ctr.level = 1;
3384                 ctr.info.info1 = &info1;
3385
3386                 torture_assert(tctx,
3387                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3388                         "failed to call test_SetJob level 1");
3389
3390                 torture_assert(tctx,
3391                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3392                         "failed to call test_GetJob");
3393
3394                 if (strequal(ginfo.info1.document_name, document_name)) {
3395                         torture_warning(tctx,
3396                                         "document_name did *NOT* change from '%s' to '%s'\n",
3397                                         document_name, new_document_name);
3398                 }
3399         }
3400
3401         for (i=0; i < num_jobs; i++) {
3402                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3403                         torture_warning(tctx, "failed to pause printjob\n");
3404                 }
3405                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3406                         torture_warning(tctx, "failed to resume printjob\n");
3407                 }
3408         }
3409
3410         return true;
3411 }
3412
3413 static bool test_DoPrintTest(struct torture_context *tctx,
3414                              struct dcerpc_binding_handle *b,
3415                              struct policy_handle *handle)
3416 {
3417         bool ret = true;
3418         uint32_t num_jobs = 8;
3419         uint32_t *job_ids;
3420         int i;
3421
3422         torture_comment(tctx, "Testing real print operations\n");
3423
3424         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3425
3426         for (i=0; i < num_jobs; i++) {
3427                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3428         }
3429
3430         for (i=0; i < num_jobs; i++) {
3431                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3432         }
3433
3434         if (ret == true) {
3435                 torture_comment(tctx, "real print operations test succeeded\n\n");
3436         }
3437
3438         return ret;
3439 }
3440
3441 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3442                                       struct dcerpc_binding_handle *b,
3443                                       struct policy_handle *handle)
3444 {
3445         bool ret = true;
3446         uint32_t num_jobs = 8;
3447         uint32_t *job_ids;
3448         int i;
3449         torture_comment(tctx, "Testing real print operations (extended)\n");
3450
3451         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3452
3453         for (i=0; i < num_jobs; i++) {
3454                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3455         }
3456
3457         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3458
3459         for (i=0; i < num_jobs; i++) {
3460                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3461         }
3462
3463         if (ret == true) {
3464                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3465         }
3466
3467         return ret;
3468 }
3469
3470 static bool test_PausePrinter(struct torture_context *tctx,
3471                               struct dcerpc_binding_handle *b,
3472                               struct policy_handle *handle)
3473 {
3474         NTSTATUS status;
3475         struct spoolss_SetPrinter r;
3476         struct spoolss_SetPrinterInfoCtr info_ctr;
3477         struct spoolss_DevmodeContainer devmode_ctr;
3478         struct sec_desc_buf secdesc_ctr;
3479
3480         info_ctr.level = 0;
3481         info_ctr.info.info0 = NULL;
3482
3483         ZERO_STRUCT(devmode_ctr);
3484         ZERO_STRUCT(secdesc_ctr);
3485
3486         r.in.handle             = handle;
3487         r.in.info_ctr           = &info_ctr;
3488         r.in.devmode_ctr        = &devmode_ctr;
3489         r.in.secdesc_ctr        = &secdesc_ctr;
3490         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3491
3492         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3493
3494         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3495
3496         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3497
3498         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3499
3500         return true;
3501 }
3502
3503 static bool test_ResumePrinter(struct torture_context *tctx,
3504                                struct dcerpc_binding_handle *b,
3505                                struct policy_handle *handle)
3506 {
3507         NTSTATUS status;
3508         struct spoolss_SetPrinter r;
3509         struct spoolss_SetPrinterInfoCtr info_ctr;
3510         struct spoolss_DevmodeContainer devmode_ctr;
3511         struct sec_desc_buf secdesc_ctr;
3512
3513         info_ctr.level = 0;
3514         info_ctr.info.info0 = NULL;
3515
3516         ZERO_STRUCT(devmode_ctr);
3517         ZERO_STRUCT(secdesc_ctr);
3518
3519         r.in.handle             = handle;
3520         r.in.info_ctr           = &info_ctr;
3521         r.in.devmode_ctr        = &devmode_ctr;
3522         r.in.secdesc_ctr        = &secdesc_ctr;
3523         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3524
3525         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3526
3527         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3528
3529         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3530
3531         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3532
3533         return true;
3534 }
3535
3536 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3537                                           struct dcerpc_binding_handle *b,
3538                                           struct policy_handle *handle,
3539                                           const char *value_name,
3540                                           enum winreg_Type *expected_type,
3541                                           enum winreg_Type *type_p,
3542                                           uint8_t **data_p,
3543                                           uint32_t *needed_p)
3544 {
3545         NTSTATUS status;
3546         struct spoolss_GetPrinterData r;
3547         uint32_t needed;
3548         enum winreg_Type type;
3549         union spoolss_PrinterData data;
3550
3551         r.in.handle = handle;
3552         r.in.value_name = value_name;
3553         r.in.offered = 0;
3554         r.out.needed = &needed;
3555         r.out.type = &type;
3556         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3557
3558         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3559
3560         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3561         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3562
3563         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3564                 if (expected_type) {
3565                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3566                 }
3567                 r.in.offered = needed;
3568                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3569                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3570                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3571         }
3572
3573         torture_assert_werr_ok(tctx, r.out.result,
3574                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3575
3576         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3577
3578         if (type_p) {
3579                 *type_p = type;
3580         }
3581
3582         if (data_p) {
3583                 *data_p = r.out.data;
3584         }
3585
3586         if (needed_p) {
3587                 *needed_p = needed;
3588         }
3589
3590         return true;
3591 }
3592
3593 static bool test_GetPrinterData(struct torture_context *tctx,
3594                                 struct dcerpc_binding_handle *b,
3595                                 struct policy_handle *handle,
3596                                 const char *value_name,
3597                                 enum winreg_Type *type_p,
3598                                 uint8_t **data_p,
3599                                 uint32_t *needed_p)
3600 {
3601         return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3602                                              NULL, type_p, data_p, needed_p);
3603 }
3604
3605 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3606                                             struct dcerpc_pipe *p,
3607                                             struct policy_handle *handle,
3608                                             const char *key_name,
3609                                             const char *value_name,
3610                                             enum winreg_Type *expected_type,
3611                                             enum winreg_Type *type_p,
3612                                             uint8_t **data_p,
3613                                             uint32_t *needed_p)
3614 {
3615         NTSTATUS status;
3616         struct spoolss_GetPrinterDataEx r;
3617         enum winreg_Type type;
3618         uint32_t needed;
3619         union spoolss_PrinterData data;
3620         struct dcerpc_binding_handle *b = p->binding_handle;
3621
3622         r.in.handle = handle;
3623         r.in.key_name = key_name;
3624         r.in.value_name = value_name;
3625         r.in.offered = 0;
3626         r.out.type = &type;
3627         r.out.needed = &needed;
3628         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3629
3630         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3631                 r.in.key_name, r.in.value_name);
3632
3633         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3634         if (!NT_STATUS_IS_OK(status)) {
3635                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3636                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3637                 }
3638                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3639         }
3640
3641         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3642                 if (expected_type) {
3643                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3644                 }
3645                 r.in.offered = needed;
3646                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3647                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3648                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3649         }
3650
3651         torture_assert_werr_ok(tctx, r.out.result,
3652                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3653
3654         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3655
3656         if (type_p) {
3657                 *type_p = type;
3658         }
3659
3660         if (data_p) {
3661                 *data_p = r.out.data;
3662         }
3663
3664         if (needed_p) {
3665                 *needed_p = needed;
3666         }
3667
3668         return true;
3669 }
3670
3671 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3672                                   struct dcerpc_pipe *p,
3673                                   struct policy_handle *handle,
3674                                   const char *key_name,
3675                                   const char *value_name,
3676                                   enum winreg_Type *type_p,
3677                                   uint8_t **data_p,
3678                                   uint32_t *needed_p)
3679 {
3680         return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3681                                                NULL, type_p, data_p, needed_p);
3682 }
3683
3684 static bool test_get_environment(struct torture_context *tctx,
3685                                  struct dcerpc_binding_handle *b,
3686                                  struct policy_handle *handle,
3687                                  const char **architecture)
3688 {
3689         DATA_BLOB blob;
3690         enum winreg_Type type;
3691         uint8_t *data;
3692         uint32_t needed;
3693
3694         torture_assert(tctx,
3695                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3696                 "failed to get Architecture");
3697
3698         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3699
3700         blob = data_blob_const(data, needed);
3701         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3702
3703         return true;
3704 }
3705
3706 static bool test_GetPrinterData_list(struct torture_context *tctx,
3707                                      void *private_data)
3708 {
3709         struct test_spoolss_context *ctx =
3710                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3711         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3712         struct dcerpc_binding_handle *b = p->binding_handle;
3713         const char *list[] = {
3714                 "W3SvcInstalled",
3715                 "BeepEnabled",
3716                 "EventLog",
3717                 /* "NetPopup", not on w2k8 */
3718                 /* "NetPopupToComputer", not on w2k8 */
3719                 "MajorVersion",
3720                 "MinorVersion",
3721                 "DefaultSpoolDirectory",
3722                 "Architecture",
3723                 "DsPresent",
3724                 "OSVersion",
3725                 /* "OSVersionEx", not on s3 */
3726                 "DNSMachineName"
3727         };
3728         int i;
3729
3730         for (i=0; i < ARRAY_SIZE(list); i++) {
3731                 enum winreg_Type type, type_ex;
3732                 uint8_t *data, *data_ex;
3733                 uint32_t needed, needed_ex;
3734
3735                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3736                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3737                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3738                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3739                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3740                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3741                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3742         }
3743
3744         return true;
3745 }
3746
3747 static bool test_EnumPrinterData(struct torture_context *tctx,
3748                                  struct dcerpc_pipe *p,
3749                                  struct policy_handle *handle,
3750                                  uint32_t enum_index,
3751                                  uint32_t value_offered,
3752                                  uint32_t data_offered,
3753                                  enum winreg_Type *type_p,
3754                                  uint32_t *value_needed_p,
3755                                  uint32_t *data_needed_p,
3756                                  const char **value_name_p,
3757                                  uint8_t **data_p,
3758                                  WERROR *result_p)
3759 {
3760         struct spoolss_EnumPrinterData r;
3761         uint32_t data_needed;
3762         uint32_t value_needed;
3763         enum winreg_Type type;
3764         struct dcerpc_binding_handle *b = p->binding_handle;
3765
3766         r.in.handle = handle;
3767         r.in.enum_index = enum_index;
3768         r.in.value_offered = value_offered;
3769         r.in.data_offered = data_offered;
3770         r.out.data_needed = &data_needed;
3771         r.out.value_needed = &value_needed;
3772         r.out.type = &type;
3773         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3774         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3775
3776         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3777
3778         torture_assert_ntstatus_ok(tctx,
3779                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3780                 "EnumPrinterData failed");
3781
3782         if (type_p) {
3783                 *type_p = type;
3784         }
3785         if (value_needed_p) {
3786                 *value_needed_p = value_needed;
3787         }
3788         if (data_needed_p) {
3789                 *data_needed_p = data_needed;
3790         }
3791         if (value_name_p) {
3792                 *value_name_p = r.out.value_name;
3793         }
3794         if (data_p) {
3795                 *data_p = r.out.data;
3796         }
3797         if (result_p) {
3798                 *result_p = r.out.result;
3799         }
3800
3801         return true;
3802 }
3803
3804
3805 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3806                                      struct dcerpc_pipe *p,
3807                                      struct policy_handle *handle)
3808 {
3809         uint32_t enum_index = 0;
3810         enum winreg_Type type;
3811         uint32_t value_needed;
3812         uint32_t data_needed;
3813         uint8_t *data;
3814         const char *value_name;
3815         WERROR result;
3816
3817         torture_comment(tctx, "Testing EnumPrinterData\n");
3818
3819         do {
3820                 torture_assert(tctx,
3821                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3822                                              &type, &value_needed, &data_needed,
3823                                              &value_name, &data, &result),
3824                         "EnumPrinterData failed");
3825
3826                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3827                         break;
3828                 }
3829
3830                 torture_assert(tctx,
3831                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3832                                              &type, &value_needed, &data_needed,
3833                                              &value_name, &data, &result),
3834                         "EnumPrinterData failed");
3835
3836                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3837                         break;
3838                 }
3839
3840                 enum_index++;
3841
3842         } while (W_ERROR_IS_OK(result));
3843
3844         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3845
3846         return true;
3847 }
3848
3849 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3850                                    struct dcerpc_binding_handle *b,
3851                                    struct policy_handle *handle,
3852                                    const char *key_name,
3853                                    uint32_t *count_p,
3854                                    struct spoolss_PrinterEnumValues **info_p)
3855 {
3856         struct spoolss_EnumPrinterDataEx r;
3857         struct spoolss_PrinterEnumValues *info;
3858         uint32_t needed;
3859         uint32_t count;
3860
3861         r.in.handle = handle;
3862         r.in.key_name = key_name;
3863         r.in.offered = 0;
3864         r.out.needed = &needed;
3865         r.out.count = &count;
3866         r.out.info = &info;
3867
3868         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3869
3870         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3871                 "EnumPrinterDataEx failed");
3872         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3873                 r.in.offered = needed;
3874                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3875                         "EnumPrinterDataEx failed");
3876         }
3877
3878         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3879
3880         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3881
3882         if (count_p) {
3883                 *count_p = count;
3884         }
3885         if (info_p) {
3886                 *info_p = info;
3887         }
3888
3889         return true;
3890 }
3891
3892 static bool test_SetPrinterData(struct torture_context *tctx,
3893                                 struct dcerpc_binding_handle *b,
3894                                 struct policy_handle *handle,
3895                                 const char *value_name,
3896                                 enum winreg_Type type,
3897                                 uint8_t *data,
3898                                 uint32_t offered);
3899 static bool test_DeletePrinterData(struct torture_context *tctx,
3900                                    struct dcerpc_binding_handle *b,
3901                                    struct policy_handle *handle,
3902                                    const char *value_name);
3903
3904 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3905                                              struct dcerpc_pipe *p,
3906                                              struct policy_handle *handle)
3907 {
3908         uint32_t count;
3909         struct spoolss_PrinterEnumValues *info;
3910         int i;
3911         uint32_t value_needed, data_needed;
3912         uint32_t value_offered, data_offered;
3913         WERROR result;
3914         struct dcerpc_binding_handle *b = p->binding_handle;
3915
3916         enum winreg_Type type;
3917         DATA_BLOB blob;
3918
3919         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3920
3921         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3922         type = REG_SZ;
3923
3924         torture_assert(tctx,
3925                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3926                 "SetPrinterData failed");
3927
3928         blob = data_blob_string_const("torture_data2");
3929
3930         torture_assert(tctx,
3931                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3932                 "SetPrinterData failed");
3933
3934         blob = data_blob_talloc(tctx, NULL, 4);
3935         SIVAL(blob.data, 0, 0x11223344);
3936
3937         torture_assert(tctx,
3938                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3939                 "SetPrinterData failed");
3940
3941         torture_assert(tctx,
3942                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3943                 "failed to call EnumPrinterDataEx");
3944
3945         /* get the max sizes for value and data */
3946
3947         torture_assert(tctx,
3948                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3949                                      NULL, &value_needed, &data_needed,
3950                                      NULL, NULL, &result),
3951                 "EnumPrinterData failed");
3952         torture_assert_werr_ok(tctx, result, "unexpected result");
3953
3954         /* check if the reply from the EnumPrinterData really matches max values */
3955
3956         for (i=0; i < count; i++) {
3957                 if (info[i].value_name_len > value_needed) {
3958                         torture_fail(tctx,
3959                                 talloc_asprintf(tctx,
3960                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3961                                 info[i].value_name_len, value_needed));
3962                 }
3963                 if (info[i].data_length > data_needed) {
3964                         torture_fail(tctx,
3965                                 talloc_asprintf(tctx,
3966                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3967                                 info[i].data_length, data_needed));
3968                 }
3969         }
3970
3971         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3972          * sort or not sort the replies by value name, we should be able to do
3973          * the following entry comparison */
3974
3975         data_offered = data_needed;
3976         value_offered = value_needed;
3977
3978         for (i=0; i < count; i++) {
3979
3980                 const char *value_name;
3981                 uint8_t *data;
3982
3983                 torture_assert(tctx,
3984                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3985                                              &type, &value_needed, &data_needed,
3986                                              &value_name, &data, &result),
3987                         "EnumPrinterData failed");
3988
3989                 if (i -1 == count) {
3990                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3991                                 "unexpected result");
3992                         break;
3993                 } else {
3994                         torture_assert_werr_ok(tctx, result, "unexpected result");
3995                 }
3996
3997                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3998                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3999                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4000                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4001                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4002         }
4003
4004         torture_assert(tctx,
4005                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4006                 "DeletePrinterData failed");
4007         torture_assert(tctx,
4008                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4009                 "DeletePrinterData failed");
4010         torture_assert(tctx,
4011                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4012                 "DeletePrinterData failed");
4013
4014         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4015
4016         return true;
4017 }
4018
4019 static bool test_DeletePrinterData(struct torture_context *tctx,
4020                                    struct dcerpc_binding_handle *b,
4021                                    struct policy_handle *handle,
4022                                    const char *value_name)
4023 {
4024         NTSTATUS status;
4025         struct spoolss_DeletePrinterData r;
4026
4027         r.in.handle = handle;
4028         r.in.value_name = value_name;
4029
4030         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4031                 r.in.value_name);
4032
4033         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4034
4035         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4036         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4037
4038         return true;
4039 }
4040
4041 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4042                                      struct dcerpc_binding_handle *b,
4043                                      struct policy_handle *handle,
4044                                      const char *key_name,
4045                                      const char *value_name)
4046 {
4047         struct spoolss_DeletePrinterDataEx r;
4048
4049         r.in.handle = handle;
4050         r.in.key_name = key_name;
4051         r.in.value_name = value_name;
4052
4053         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4054                 r.in.key_name, r.in.value_name);
4055
4056         torture_assert_ntstatus_ok(tctx,
4057                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4058                 "DeletePrinterDataEx failed");
4059         torture_assert_werr_ok(tctx, r.out.result,
4060                 "DeletePrinterDataEx failed");
4061
4062         return true;
4063 }
4064
4065 static bool test_DeletePrinterKey(struct torture_context *tctx,
4066                                   struct dcerpc_binding_handle *b,
4067                                   struct policy_handle *handle,
4068                                   const char *key_name)
4069 {
4070         struct spoolss_DeletePrinterKey r;
4071
4072         r.in.handle = handle;
4073         r.in.key_name = key_name;
4074
4075         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4076
4077         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4078                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4079                 return true;
4080         }
4081
4082         torture_assert_ntstatus_ok(tctx,
4083                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4084                 "DeletePrinterKey failed");
4085         torture_assert_werr_ok(tctx, r.out.result,
4086                 "DeletePrinterKey failed");
4087
4088         return true;
4089 }
4090
4091 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4092                                  struct dcerpc_binding_handle *b,
4093                                  struct policy_handle *handle)
4094 {
4095         struct winreg_OpenHKLM r;
4096
4097         r.in.system_name = NULL;
4098         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4099         r.out.handle = handle;
4100
4101         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4102
4103         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4104         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4105
4106         return true;
4107 }
4108
4109 static void init_winreg_String(struct winreg_String *name, const char *s)
4110 {
4111         name->name = s;
4112         if (s) {
4113                 name->name_len = 2 * (strlen_m(s) + 1);
4114                 name->name_size = name->name_len;
4115         } else {
4116                 name->name_len = 0;
4117                 name->name_size = 0;
4118         }
4119 }
4120
4121 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4122                                      struct dcerpc_binding_handle *b,
4123                                      struct policy_handle *hive_handle,
4124                                      const char *keyname,
4125                                      uint32_t options,
4126                                      struct policy_handle *key_handle)
4127 {
4128         struct winreg_OpenKey r;
4129
4130         r.in.parent_handle = hive_handle;
4131         init_winreg_String(&r.in.keyname, keyname);
4132         r.in.options = options;
4133         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4134         r.out.handle = key_handle;
4135
4136         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4137
4138         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4139         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4140
4141         return true;
4142 }
4143
4144 static bool test_winreg_OpenKey(struct torture_context *tctx,
4145                                 struct dcerpc_binding_handle *b,
4146                                 struct policy_handle *hive_handle,
4147                                 const char *keyname,
4148                                 struct policy_handle *key_handle)
4149 {
4150         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4151                                         REG_OPTION_NON_VOLATILE, key_handle);
4152 }
4153
4154 static bool test_winreg_CloseKey(struct torture_context *tctx,
4155                                  struct dcerpc_binding_handle *b,
4156                                  struct policy_handle *handle)
4157 {
4158         struct winreg_CloseKey r;
4159
4160         r.in.handle = handle;
4161         r.out.handle = handle;
4162
4163         torture_comment(tctx, "Testing winreg_CloseKey\n");
4164
4165         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4166         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4167
4168         return true;
4169 }
4170
4171 bool test_winreg_QueryValue(struct torture_context *tctx,
4172                             struct dcerpc_binding_handle *b,
4173                             struct policy_handle *handle,
4174                             const char *value_name,
4175                             enum winreg_Type *type_p,
4176                             uint32_t *data_size_p,
4177                             uint32_t *data_length_p,
4178                             uint8_t **data_p)
4179 {
4180         struct winreg_QueryValue r;
4181         enum winreg_Type type = REG_NONE;
4182         uint32_t data_size = 0;
4183         uint32_t data_length = 0;
4184         struct winreg_String valuename;
4185         uint8_t *data = NULL;
4186
4187         init_winreg_String(&valuename, value_name);
4188
4189         data = talloc_zero_array(tctx, uint8_t, 0);
4190
4191         r.in.handle = handle;
4192         r.in.value_name = &valuename;
4193         r.in.type = &type;
4194         r.in.data_size = &data_size;
4195         r.in.data_length = &data_length;
4196         r.in.data = data;
4197         r.out.type = &type;
4198         r.out.data = data;
4199         r.out.data_size = &data_size;
4200         r.out.data_length = &data_length;
4201
4202         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4203
4204         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4205         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4206                 *r.in.data_size = *r.out.data_size;
4207                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4208                 r.in.data = data;
4209                 r.out.data = data;
4210                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4211         }
4212         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4213
4214         if (type_p) {
4215                 *type_p = *r.out.type;
4216         }
4217         if (data_size_p) {
4218                 *data_size_p = *r.out.data_size;
4219         }
4220         if (data_length_p) {
4221                 *data_length_p = *r.out.data_length;
4222         }
4223         if (data_p) {
4224                 *data_p = r.out.data;
4225         }
4226
4227         return true;
4228 }
4229
4230 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4231                                           struct dcerpc_binding_handle *b,
4232                                           struct policy_handle *handle,
4233                                           const char *printer_name,
4234                                           const char *key_name,
4235                                           const char *value_name,
4236                                           enum winreg_Type *w_type,
4237                                           uint32_t *w_size,
4238                                           uint32_t *w_length,
4239                                           uint8_t **w_data)
4240 {
4241         const char *printer_key;
4242         struct policy_handle key_handle;
4243
4244         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4245                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4246
4247         torture_assert(tctx,
4248                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4249
4250         torture_assert(tctx,
4251                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4252
4253         torture_assert(tctx,
4254                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4255
4256         return true;
4257 }
4258
4259 static bool test_GetForm_winreg(struct torture_context *tctx,
4260                                 struct dcerpc_binding_handle *b,
4261                                 struct policy_handle *handle,
4262                                 const char *key_name,
4263                                 const char *form_name,
4264                                 enum winreg_Type *w_type,
4265                                 uint32_t *w_size,
4266                                 uint32_t *w_length,
4267                                 uint8_t **w_data)
4268 {
4269         struct policy_handle key_handle;
4270
4271         torture_assert(tctx,
4272                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4273
4274         torture_assert(tctx,
4275                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4276
4277         torture_assert(tctx,
4278                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4279
4280         return true;
4281 }
4282
4283 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4284                                       struct dcerpc_binding_handle *b,
4285                                       struct policy_handle *handle,
4286                                       const char *symlink_keyname,
4287                                       const char *symlink_destination)
4288 {
4289         /* check if the first key is a symlink to the second key */
4290
4291         enum winreg_Type w_type;
4292         uint32_t w_size;
4293         uint32_t w_length;
4294         uint8_t *w_data;
4295         struct policy_handle key_handle;
4296         DATA_BLOB blob;
4297         const char *str;
4298
4299         if (torture_setting_bool(tctx, "samba3", false)) {
4300                 torture_skip(tctx, "skip winreg symlink test against samba");
4301         }
4302
4303         torture_assert(tctx,
4304                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4305                         "failed to open key link");
4306
4307         torture_assert(tctx,
4308                 test_winreg_QueryValue(tctx, b, &key_handle,
4309                                        "SymbolicLinkValue",
4310                                        &w_type, &w_size, &w_length, &w_data),
4311                 "failed to query for 'SymbolicLinkValue' attribute");
4312
4313         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4314
4315         blob = data_blob(w_data, w_size);
4316         str = reg_val_data_string(tctx, REG_SZ, blob);
4317
4318         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4319
4320         torture_assert(tctx,
4321                 test_winreg_CloseKey(tctx, b, &key_handle),
4322                 "failed to close key link");
4323
4324         return true;
4325 }
4326
4327 static const char *strip_unc(const char *unc)
4328 {
4329         char *name;
4330
4331         if (!unc) {
4332                 return NULL;
4333         }
4334
4335         if (unc[0] == '\\' && unc[1] == '\\') {
4336                 unc +=2;
4337         }
4338
4339         name = strchr(unc, '\\');
4340         if (name) {
4341                 return name+1;
4342         }
4343
4344         return unc;
4345 }
4346
4347 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4348                                        struct dcerpc_binding_handle *b,
4349                                        struct policy_handle *handle,
4350                                        const char *printer_name,
4351                                        struct dcerpc_binding_handle *winreg_handle,
4352                                        struct policy_handle *hive_handle)
4353 {
4354         union spoolss_PrinterInfo info;
4355         const char *keys[] = {
4356                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4357                 TOP_LEVEL_PRINT_PRINTERS_KEY
4358         };
4359         int i;
4360         const char *printername, *sharename;
4361
4362         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4363
4364         torture_assert(tctx,
4365                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4366                 "failed to get printer info level 2");
4367
4368         printername = strip_unc(info.info2.printername);
4369         sharename = strip_unc(info.info2.sharename);
4370
4371 #define test_sz(wname, iname) \
4372 do {\
4373         DATA_BLOB blob;\
4374         const char *str;\
4375         enum winreg_Type w_type;\
4376         uint32_t w_size;\
4377         uint32_t w_length;\
4378         uint8_t *w_data;\
4379         torture_assert(tctx,\
4380                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4381                                        &w_type, &w_size, &w_length, &w_data),\
4382                 "failed to query winreg");\
4383         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4384         blob = data_blob(w_data, w_size);\
4385         str = reg_val_data_string(tctx, REG_SZ, blob);\
4386         if (w_size == 2 && iname == NULL) {\
4387                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4388         } else {\
4389                 torture_assert_str_equal(tctx, str, iname,\
4390                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4391         }\
4392 } while(0);
4393
4394 #define test_dword(wname, iname) \
4395 do {\
4396         uint32_t value;\
4397         enum winreg_Type w_type;\
4398         uint32_t w_size;\
4399         uint32_t w_length;\
4400         uint8_t *w_data;\
4401         torture_assert(tctx,\
4402                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4403                                        &w_type, &w_size, &w_length, &w_data),\
4404                 "failed to query winreg");\
4405         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4406         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4407         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4408         value = IVAL(w_data, 0);\
4409         torture_assert_int_equal(tctx, value, iname,\
4410                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4411 } while(0);
4412
4413 #define test_binary(wname, iname) \
4414 do {\
4415         enum winreg_Type w_type;\
4416         uint32_t w_size;\
4417         uint32_t w_length;\
4418         uint8_t *w_data;\
4419         torture_assert(tctx,\
4420                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4421                                        &w_type, &w_size, &w_length, &w_data),\
4422                 "failed to query winreg");\
4423         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4424         torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4425         torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4426                 "binary unequal");\
4427 } while(0);
4428
4429
4430 #define test_dm(wname, iname) \
4431 do {\
4432         DATA_BLOB blob;\
4433         struct spoolss_DeviceMode dm;\
4434         enum ndr_err_code ndr_err;\
4435         enum winreg_Type w_type;\
4436         uint32_t w_size;\
4437         uint32_t w_length;\
4438         uint8_t *w_data;\
4439         torture_assert(tctx,\
4440                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4441                                        &w_type, &w_size, &w_length, &w_data),\
4442                 "failed to query winreg");\
4443         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4444         blob = data_blob(w_data, w_size);\
4445         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4446                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4447         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4448         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4449                 "dm unequal");\
4450 } while(0);
4451
4452 #define test_sd(wname, iname) \
4453 do {\
4454         DATA_BLOB blob;\
4455         struct security_descriptor sd;\
4456         enum ndr_err_code ndr_err;\
4457         enum winreg_Type w_type;\
4458         uint32_t w_size;\
4459         uint32_t w_length;\
4460         uint8_t *w_data;\
4461         torture_assert(tctx,\
4462                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4463                                        &w_type, &w_size, &w_length, &w_data),\
4464                 "failed to query winreg");\
4465         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4466         blob = data_blob(w_data, w_size);\
4467         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4468                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4469         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4470         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4471                 "sd unequal");\
4472 } while(0);
4473
4474 #define test_multi_sz(wname, iname) \
4475 do {\
4476         DATA_BLOB blob;\
4477         const char **array;\
4478         enum winreg_Type w_type;\
4479         uint32_t w_size;\
4480         uint32_t w_length;\
4481         uint8_t *w_data;\
4482         int i;\
4483         torture_assert(tctx,\
4484                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4485                                        &w_type, &w_size, &w_length, &w_data),\
4486                 "failed to query winreg");\
4487         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4488         blob = data_blob(w_data, w_size);\
4489         torture_assert(tctx, \
4490                 pull_reg_multi_sz(tctx, &blob, &array),\
4491                 "failed to pull multi sz");\
4492         for (i=0; array[i] != NULL; i++) {\
4493                 torture_assert_str_equal(tctx, array[i], iname[i],\
4494                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4495         }\
4496 } while(0);
4497
4498         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4499                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4500                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4501         {
4502                 torture_warning(tctx, "failed to check for winreg symlink");
4503         }
4504
4505         for (i=0; i < ARRAY_SIZE(keys); i++) {
4506
4507                 const char *printer_key;
4508                 struct policy_handle key_handle;
4509
4510                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4511                         keys[i], printer_name);
4512
4513                 torture_assert(tctx,
4514                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4515
4516                 test_sz("Name", printername);
4517                 test_sz("Share Name", sharename);
4518                 test_sz("Port", info.info2.portname);
4519                 test_sz("Printer Driver", info.info2.drivername);
4520                 test_sz("Description", info.info2.comment);
4521                 test_sz("Location", info.info2.location);
4522                 test_sz("Separator File", info.info2.sepfile);
4523                 test_sz("Print Processor", info.info2.printprocessor);
4524                 test_sz("Datatype", info.info2.datatype);
4525                 test_sz("Parameters", info.info2.parameters);
4526                 /* winreg: 0, spoolss not */
4527 /*              test_dword("Attributes", info.info2.attributes); */
4528                 test_dword("Priority", info.info2.priority);
4529                 test_dword("Default Priority", info.info2.defaultpriority);
4530                 /* winreg: 60, spoolss: 0 */
4531 /*              test_dword("StartTime", info.info2.starttime); */
4532 /*              test_dword("UntilTime", info.info2.untiltime); */
4533                 /* winreg != spoolss */
4534 /*              test_dword("Status", info.info2.status); */
4535                 test_dm("Default DevMode", info.info2.devmode);
4536                 test_sd("Security", info.info2.secdesc);
4537
4538                 torture_assert(tctx,
4539                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4540         }
4541
4542 #undef test_dm
4543 #undef test_sd
4544
4545         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4546
4547         return true;
4548 }
4549
4550 static bool test_PrintProcessors(struct torture_context *tctx,
4551                                  struct dcerpc_binding_handle *b,
4552                                  const char *environment,
4553                                  struct dcerpc_binding_handle *winreg_handle,
4554                                  struct policy_handle *hive_handle)
4555 {
4556         union spoolss_PrintProcessorInfo *info;
4557         uint32_t count;
4558         int i;
4559
4560         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4561
4562         torture_assert(tctx,
4563                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4564                 "failed to enum print processors level 1");
4565
4566         for (i=0; i < count; i++) {
4567
4568                 const char *processor_key;
4569                 struct policy_handle key_handle;
4570
4571                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4572                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4573                                                 environment,
4574                                                 info[i].info1.print_processor_name);
4575
4576                 torture_assert(tctx,
4577                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4578
4579                 /* nothing to check in there so far */
4580
4581                 torture_assert(tctx,
4582                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4583         }
4584
4585         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4586
4587         return true;
4588 }
4589
4590 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4591                                          struct dcerpc_binding_handle *b,
4592                                          struct policy_handle *handle,
4593                                          const char *driver_name,
4594                                          const char *architecture,
4595                                          uint32_t level,
4596                                          uint32_t client_major_version,
4597                                          uint32_t client_minor_version,
4598                                          union spoolss_DriverInfo *info_p,
4599                                          WERROR *result);
4600
4601 static const char *strip_path(const char *path)
4602 {
4603         char *p;
4604
4605         if (path == NULL) {
4606                 return NULL;
4607         }
4608
4609         p = strrchr(path, '\\');
4610         if (p) {
4611                 return p+1;
4612         }
4613
4614         return path;
4615 }
4616
4617 static const char **strip_paths(const char **path_array)
4618 {
4619         int i;
4620
4621         if (path_array == NULL) {
4622                 return NULL;
4623         }
4624
4625         for (i=0; path_array[i] != NULL; i++) {
4626                 path_array[i] = strip_path(path_array[i]);
4627         }
4628
4629         return path_array;
4630 }
4631
4632 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4633 {
4634         time_t t;
4635         struct tm *tm;
4636
4637         if (nt == 0) {
4638                 return talloc_strdup(mem_ctx, "01/01/1601");
4639         }
4640
4641         t = nt_time_to_unix(nt);
4642         tm = localtime(&t);
4643
4644         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4645                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4646 }
4647
4648 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4649 {
4650         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4651                 (unsigned)((v >> 48) & 0xFFFF),
4652                 (unsigned)((v >> 32) & 0xFFFF),
4653                 (unsigned)((v >> 16) & 0xFFFF),
4654                 (unsigned)(v & 0xFFFF));
4655 }
4656
4657 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4658                                       struct dcerpc_binding_handle *b,
4659                                       struct policy_handle *handle,
4660                                       const char *printer_name,
4661                                       const char *driver_name,
4662                                       const char *environment,
4663                                       enum spoolss_DriverOSVersion version,
4664                                       struct dcerpc_binding_handle *winreg_handle,
4665                                       struct policy_handle *hive_handle,
4666                                       const char *server_name_slash)
4667 {
4668         WERROR result;
4669         union spoolss_DriverInfo info;
4670         const char *driver_key;
4671         struct policy_handle key_handle;
4672
4673         const char *driver_path;
4674         const char *data_file;
4675         const char *config_file;
4676         const char *help_file;
4677         const char **dependent_files;
4678
4679         const char *driver_date;
4680         const char *inbox_driver_date;
4681
4682         const char *driver_version;
4683         const char *inbox_driver_version;
4684
4685         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4686
4687         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4688                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4689                                      environment,
4690                                      version,
4691                                      driver_name);
4692
4693         torture_assert(tctx,
4694                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4695                 "failed to open driver key");
4696
4697         if (torture_setting_bool(tctx, "samba3", false) ||
4698             torture_setting_bool(tctx, "w2k3", false)) {
4699                 goto try_level6;
4700         }
4701
4702         if (handle) {
4703                 torture_assert(tctx,
4704                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4705                         "failed to get driver info level 8");
4706         } else {
4707                 torture_assert(tctx,
4708                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4709                         "failed to get driver info level 8");
4710         }
4711
4712         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4713                 goto try_level6;
4714         }
4715
4716         driver_path     = strip_path(info.info8.driver_path);
4717         data_file       = strip_path(info.info8.data_file);
4718         config_file     = strip_path(info.info8.config_file);
4719         help_file       = strip_path(info.info8.help_file);
4720         dependent_files = strip_paths(info.info8.dependent_files);
4721
4722         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4723         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4724
4725         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4726         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4727
4728         test_sz("Configuration File",           config_file);
4729         test_sz("Data File",                    data_file);
4730         test_sz("Datatype",                     info.info8.default_datatype);
4731         test_sz("Driver",                       driver_path);
4732         test_sz("DriverDate",                   driver_date);
4733         test_sz("DriverVersion",                driver_version);
4734         test_sz("HardwareID",                   info.info8.hardware_id);
4735         test_sz("Help File",                    help_file);
4736         test_sz("InfPath",                      info.info8.inf_path);
4737         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4738         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4739         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4740         test_sz("Monitor",                      info.info8.monitor_name);
4741         test_sz("OEM URL",                      info.info8.manufacturer_url);
4742         test_sz("Print Processor",              info.info8.print_processor);
4743         test_sz("Provider",                     info.info8.provider);
4744         test_sz("VendorSetup",                  info.info8.vendor_setup);
4745         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4746         test_multi_sz("Dependent Files",        dependent_files);
4747         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4748         test_multi_sz("Previous Names",         info.info8.previous_names);
4749 /*      test_dword("Attributes",                ?); */
4750         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4751         test_dword("Version",                   info.info8.version);
4752 /*      test_dword("TempDir",                   ?); */
4753
4754  try_level6:
4755
4756         if (handle) {
4757                 torture_assert(tctx,
4758                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4759                         "failed to get driver info level 6");
4760         } else {
4761                 torture_assert(tctx,
4762                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4763                         "failed to get driver info level 6");
4764         }
4765
4766         driver_path     = strip_path(info.info6.driver_path);
4767         data_file       = strip_path(info.info6.data_file);
4768         config_file     = strip_path(info.info6.config_file);
4769         help_file       = strip_path(info.info6.help_file);
4770         dependent_files = strip_paths(info.info6.dependent_files);
4771
4772         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4773
4774         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4775
4776         test_sz("Configuration File",           config_file);
4777         test_sz("Data File",                    data_file);
4778         test_sz("Datatype",                     info.info6.default_datatype);
4779         test_sz("Driver",                       driver_path);
4780         if (torture_setting_bool(tctx, "w2k3", false)) {
4781                 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4782                 push_nttime(blob.data, 0, info.info6.driver_date);
4783                 test_binary("DriverDate",       blob);
4784                 SBVAL(blob.data, 0, info.info6.driver_version);
4785                 test_binary("DriverVersion",    blob);
4786         } else {
4787                 test_sz("DriverDate",           driver_date);
4788                 test_sz("DriverVersion",        driver_version);
4789         }
4790         test_sz("HardwareID",                   info.info6.hardware_id);
4791         test_sz("Help File",                    help_file);
4792         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4793         test_sz("Monitor",                      info.info6.monitor_name);
4794         test_sz("OEM URL",                      info.info6.manufacturer_url);
4795         test_sz("Provider",                     info.info6.provider);
4796         test_multi_sz("Dependent Files",        dependent_files);
4797         test_multi_sz("Previous Names",         info.info6.previous_names);
4798 /*      test_dword("Attributes",                ?); */
4799         test_dword("Version",                   info.info6.version);
4800 /*      test_dword("TempDir",                   ?); */
4801
4802         if (handle) {
4803                 torture_assert(tctx,
4804                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4805                         "failed to get driver info level 3");
4806         } else {
4807                 torture_assert(tctx,
4808                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4809                         "failed to get driver info level 3");
4810         }
4811
4812         driver_path     = strip_path(info.info3.driver_path);
4813         data_file       = strip_path(info.info3.data_file);
4814         config_file     = strip_path(info.info3.config_file);
4815         help_file       = strip_path(info.info3.help_file);
4816         dependent_files = strip_paths(info.info3.dependent_files);
4817
4818         test_sz("Configuration File",           config_file);
4819         test_sz("Data File",                    data_file);
4820         test_sz("Datatype",                     info.info3.default_datatype);
4821         test_sz("Driver",                       driver_path);
4822         test_sz("Help File",                    help_file);
4823         test_sz("Monitor",                      info.info3.monitor_name);
4824         test_multi_sz("Dependent Files",        dependent_files);
4825 /*      test_dword("Attributes",                ?); */
4826         test_dword("Version",                   info.info3.version);
4827 /*      test_dword("TempDir",                   ?); */
4828
4829
4830         torture_assert(tctx,
4831                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4832
4833         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4834
4835         return true;
4836 }
4837
4838 #undef test_sz
4839 #undef test_dword
4840
4841 static bool test_SetPrinterData(struct torture_context *tctx,
4842                                 struct dcerpc_binding_handle *b,
4843                                 struct policy_handle *handle,
4844                                 const char *value_name,
4845                                 enum winreg_Type type,
4846                                 uint8_t *data,
4847                                 uint32_t offered)
4848 {
4849         struct spoolss_SetPrinterData r;
4850
4851         r.in.handle = handle;
4852         r.in.value_name = value_name;
4853         r.in.type = type;
4854         r.in.data = data;
4855         r.in.offered = offered;
4856
4857         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4858                 r.in.value_name);
4859
4860         torture_assert_ntstatus_ok(tctx,
4861                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4862                 "SetPrinterData failed");
4863         torture_assert_werr_ok(tctx, r.out.result,
4864                 "SetPrinterData failed");
4865
4866         return true;
4867 }
4868
4869 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4870                                        struct dcerpc_binding_handle *b,
4871                                        struct policy_handle *handle,
4872                                        const char *printer_name,
4873                                        struct dcerpc_binding_handle *winreg_handle,
4874                                        struct policy_handle *hive_handle)
4875 {
4876         const char *values[] = {
4877                 "spootyfoot",
4878                 "spooty\\foot",
4879 #if 0
4880         /* FIXME: not working with s3 atm. */
4881                 "spooty,foot",
4882                 "spooty,fo,ot",
4883 #endif
4884                 "spooty foot",
4885 #if 0
4886         /* FIXME: not working with s3 atm. */
4887                 "spooty\\fo,ot",
4888                 "spooty,fo\\ot"
4889 #endif
4890         };
4891         int i;
4892
4893         for (i=0; i < ARRAY_SIZE(values); i++) {
4894
4895                 enum winreg_Type type, expected_type = REG_SZ;
4896                 DATA_BLOB blob;
4897                 uint8_t *data;
4898                 uint32_t needed;
4899
4900                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4901                 type = REG_SZ;
4902
4903                 torture_assert(tctx,
4904                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4905                         "SetPrinterData failed");
4906
4907                 torture_assert(tctx,
4908                         test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4909                         "GetPrinterData failed");
4910
4911                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4912                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4913                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4914
4915                 if (winreg_handle && hive_handle) {
4916
4917                         enum winreg_Type w_type;
4918                         uint32_t w_size;
4919                         uint32_t w_length;
4920                         uint8_t *w_data;
4921
4922                         torture_assert(tctx,
4923                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4924                                         printer_name, "PrinterDriverData", values[i],
4925                                         &w_type, &w_size, &w_length, &w_data), "");
4926
4927                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4928                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4929                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4930                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4931                 }
4932
4933                 torture_assert(tctx,
4934                         test_DeletePrinterData(tctx, b, handle, values[i]),
4935                         "DeletePrinterData failed");
4936         }
4937
4938         return true;
4939 }
4940
4941
4942 static bool test_EnumPrinterKey(struct torture_context *tctx,
4943                                 struct dcerpc_binding_handle *b,
4944                                 struct policy_handle *handle,
4945                                 const char *key_name,
4946                                 const char ***array);
4947
4948 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4949                                   struct dcerpc_binding_handle *b,
4950                                   struct policy_handle *handle,
4951                                   const char *key_name,
4952                                   const char *value_name,
4953                                   enum winreg_Type type,
4954                                   uint8_t *data,
4955                                   uint32_t offered)
4956 {
4957         NTSTATUS status;
4958         struct spoolss_SetPrinterDataEx r;
4959
4960         r.in.handle = handle;
4961         r.in.key_name = key_name;
4962         r.in.value_name = value_name;
4963         r.in.type = type;
4964         r.in.data = data;
4965         r.in.offered = offered;
4966
4967         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4968                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4969
4970         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4971
4972         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4973         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4974
4975         return true;
4976 }
4977
4978 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4979                                        struct dcerpc_pipe *p,
4980                                        struct policy_handle *handle)
4981 {
4982         struct dcerpc_binding_handle *b = p->binding_handle;
4983         const char *value_name = "dog";
4984         const char *keys[] = {
4985                 "torturedataex",
4986                 "torture data ex",
4987                 "torturedataex_with_subkey\\subkey",
4988                 "torturedataex_with_subkey\\subkey:0",
4989                 "torturedataex_with_subkey\\subkey:1",
4990                 "torturedataex_with_subkey\\subkey\\subsubkey",
4991                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4992                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4993                 "torture,data",
4994                 "torture,data,ex",
4995                 "torture,data\\ex",
4996                 "torture\\data,ex",
4997                 "torture/data",
4998                 "torture/data ex",
4999                 "torture/data ex/sub",
5000                 "torture//data",
5001                 "torture//data ex",
5002                 "torture//data ex/sub",
5003                 "torture//data ex//sub",
5004         };
5005         int i;
5006
5007         for (i=0; i < ARRAY_SIZE(keys); i++) {
5008
5009                 char *c;
5010                 const char *key;
5011                 enum winreg_Type type;
5012                 DATA_BLOB blob_in, blob_out;
5013                 const char **subkeys;
5014                 uint32_t ecount;
5015                 struct spoolss_PrinterEnumValues *einfo;
5016                 uint32_t needed;
5017
5018                 blob_in = data_blob_talloc(tctx, NULL, 42);
5019
5020                 generate_random_buffer(blob_in.data, blob_in.length);
5021
5022                 torture_assert(tctx,
5023                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5024                         "failed to call SetPrinterDataEx");
5025
5026                 torture_assert(tctx,
5027                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5028                         "failed to call GetPrinterDataEx");
5029
5030                 blob_out.length = needed;
5031                 torture_assert(tctx,
5032                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5033                         "failed to call EnumPrinterDataEx");
5034
5035                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5036                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5037                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5038
5039                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5040                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5041                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5042                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5043                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5044                 if (einfo[0].data_length > 0) {
5045                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5046                 }
5047
5048                 key = talloc_strdup(tctx, keys[i]);
5049
5050                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5051                         return false;
5052                 }
5053
5054                 c = strchr(key, '\\');
5055                 if (c) {
5056                         int k;
5057
5058                         /* we have subkeys */
5059
5060                         *c = 0;
5061
5062                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5063                                 return false;
5064                         }
5065
5066                         for (k=0; subkeys && subkeys[k]; k++) {
5067
5068                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5069
5070                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5071                                         return false;
5072                                 }
5073                         }
5074
5075                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5076                                 return false;
5077                         }
5078
5079                 } else {
5080                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5081                                 return false;
5082                         }
5083                 }
5084         }
5085
5086         return true;
5087 }
5088
5089 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5090                                          struct dcerpc_pipe *p,
5091                                          struct policy_handle *handle)
5092 {
5093         struct dcerpc_binding_handle *b = p->binding_handle;
5094         const char *key = "torturedataex";
5095         const char *values[] = {
5096                 "torture_value",
5097                 "torture value",
5098                 "torture,value",
5099                 "torture/value",
5100                 "torture\\value",
5101                 "torture\\\\value"
5102         };
5103         int i;
5104
5105         for (i=0; i < ARRAY_SIZE(values); i++) {
5106
5107                 enum winreg_Type type;
5108                 DATA_BLOB blob_in, blob_out;
5109                 uint32_t ecount;
5110                 struct spoolss_PrinterEnumValues *einfo;
5111                 uint32_t needed;
5112
5113                 if (torture_setting_bool(tctx, "samba3", false)) {
5114                         char *q;
5115                         q = strrchr(values[i], ',');
5116                         if (q) {
5117                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5118                                                 values[i]);
5119                                 continue;
5120                         }
5121                 }
5122
5123                 blob_in = data_blob_talloc(tctx, NULL, 42);
5124
5125                 generate_random_buffer(blob_in.data, blob_in.length);
5126
5127                 torture_assert(tctx,
5128                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5129                         "failed to call SetPrinterDataEx");
5130
5131                 torture_assert(tctx,
5132                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5133                         "failed to call GetPrinterDataEx");
5134
5135                 blob_out.length = needed;
5136                 torture_assert(tctx,
5137                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5138                         "failed to call EnumPrinterDataEx");
5139
5140                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5141                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5142                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5143
5144                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5145                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5146                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5147                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5148                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5149                 if (einfo[0].data_length > 0) {
5150                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5151                 }
5152
5153                 torture_assert(tctx,
5154                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5155                         "failed to call DeletePrinterDataEx");
5156         }
5157
5158         return true;
5159 }
5160
5161
5162 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5163                                          struct dcerpc_pipe *p,
5164                                          struct policy_handle *handle,
5165                                          const char *printername,
5166                                          struct dcerpc_binding_handle *winreg_handle,
5167                                          struct policy_handle *hive_handle)
5168 {
5169         struct dcerpc_binding_handle *b = p->binding_handle;
5170         const char *value_name = "dog";
5171         const char *key_name = "torturedataex";
5172         enum winreg_Type types[] = {
5173                 REG_SZ,
5174                 REG_MULTI_SZ,
5175                 REG_DWORD,
5176                 REG_BINARY
5177         };
5178         const char *str = "abcdefghi";
5179         int t, s;
5180
5181         for (t=0; t < ARRAY_SIZE(types); t++) {
5182         for (s=0; s < strlen(str); s++) {
5183
5184                 enum winreg_Type type;
5185                 const char *string = talloc_strndup(tctx, str, s);
5186                 const char *array[2];
5187                 DATA_BLOB blob = data_blob_string_const(string);
5188                 DATA_BLOB data;
5189                 uint8_t *data_out;
5190                 uint32_t needed, offered = 0;
5191                 uint32_t ecount;
5192                 struct spoolss_PrinterEnumValues *einfo;
5193
5194                 array[0] = talloc_strdup(tctx, string);
5195                 array[1] = NULL;
5196
5197                 if (types[t] == REG_DWORD) {
5198                         s = 0xffff;
5199                 }
5200
5201                 switch (types[t]) {
5202                 case REG_BINARY:
5203                         data = blob;
5204                         offered = blob.length;
5205                         break;
5206                 case REG_DWORD:
5207                         data = data_blob_talloc(tctx, NULL, 4);
5208                         SIVAL(data.data, 0, 0x12345678);
5209                         offered = 4;
5210                         break;
5211                 case REG_SZ:
5212                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5213                         type = REG_SZ;
5214                         offered = data.length;
5215                         /*strlen_m_term(data.string)*2;*/
5216                         break;
5217                 case REG_MULTI_SZ:
5218                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5219                         type = REG_MULTI_SZ;
5220                         offered = data.length;
5221                         break;
5222                 default:
5223                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5224                 }
5225
5226                 torture_assert(tctx,
5227                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5228                         "failed to call SetPrinterDataEx");
5229
5230                 torture_assert(tctx,
5231                         test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5232                         "failed to call GetPrinterDataEx");
5233
5234                 torture_assert(tctx,
5235                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5236                         "failed to call EnumPrinterDataEx");
5237
5238                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5239                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5240                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5241
5242                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5243                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5244                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5245                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5246                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5247                 if (einfo[0].data_length > 0) {
5248                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5249                 }
5250
5251                 if (winreg_handle && hive_handle) {
5252                         enum winreg_Type w_type;
5253                         uint32_t w_size;
5254                         uint32_t w_length;
5255                         uint8_t *w_data;
5256
5257                         torture_assert(tctx,
5258                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5259                                         printername, key_name, value_name,
5260                                         &w_type, &w_size, &w_length, &w_data), "");
5261
5262                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5263                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5264                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5265                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5266                 }
5267
5268                 torture_assert(tctx,
5269                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5270                         "failed to call DeletePrinterDataEx");
5271         }
5272         }
5273
5274         return true;
5275 }
5276
5277 static bool test_PrinterData_winreg(struct torture_context *tctx,
5278                                     struct dcerpc_pipe *p,
5279                                     struct policy_handle *handle,
5280                                     const char *printer_name)
5281 {
5282         struct dcerpc_binding_handle *b = p->binding_handle;
5283         struct dcerpc_pipe *p2;
5284         bool ret = true;
5285         struct policy_handle hive_handle;
5286         struct dcerpc_binding_handle *b2;
5287
5288         torture_assert_ntstatus_ok(tctx,
5289                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5290                 "could not open winreg pipe");
5291         b2 = p2->binding_handle;
5292
5293         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5294
5295         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5296         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5297
5298         test_winreg_CloseKey(tctx, b2, &hive_handle);
5299
5300         talloc_free(p2);
5301
5302         return ret;
5303 }
5304
5305 static bool test_Forms_winreg(struct torture_context *tctx,
5306                               struct dcerpc_binding_handle *b,
5307                               struct policy_handle *handle,
5308                               bool print_server,
5309                               const char *printer_name)
5310 {
5311         struct dcerpc_pipe *p2;
5312         bool ret = true;
5313         struct policy_handle hive_handle;
5314         struct dcerpc_binding_handle *b2;
5315
5316         torture_assert_ntstatus_ok(tctx,
5317                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5318                 "could not open winreg pipe");
5319         b2 = p2->binding_handle;
5320
5321         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5322
5323         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5324
5325         test_winreg_CloseKey(tctx, b2, &hive_handle);
5326
5327         talloc_free(p2);
5328
5329         return ret;
5330 }
5331
5332 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5333                                     struct dcerpc_pipe *p,
5334                                     struct policy_handle *handle,
5335                                     const char *printer_name)
5336 {
5337         struct dcerpc_binding_handle *b = p->binding_handle;
5338         struct dcerpc_pipe *p2;
5339         bool ret = true;
5340         struct policy_handle hive_handle;
5341         struct dcerpc_binding_handle *b2;
5342
5343         torture_assert_ntstatus_ok(tctx,
5344                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5345                 "could not open winreg pipe");
5346         b2 = p2->binding_handle;
5347
5348         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5349
5350         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5351
5352         test_winreg_CloseKey(tctx, b2, &hive_handle);
5353
5354         talloc_free(p2);
5355
5356         return ret;
5357 }
5358
5359 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5360                                    struct dcerpc_pipe *p,
5361                                    struct policy_handle *handle,
5362                                    const char *printer_name,
5363                                    const char *driver_name,
5364                                    const char *environment,
5365                                    enum spoolss_DriverOSVersion version)
5366 {
5367         struct dcerpc_binding_handle *b = p->binding_handle;
5368         struct dcerpc_pipe *p2;
5369         bool ret = true;
5370         struct policy_handle hive_handle;
5371         struct dcerpc_binding_handle *b2;
5372
5373         torture_assert_ntstatus_ok(tctx,
5374                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5375                 "could not open winreg pipe");
5376         b2 = p2->binding_handle;
5377
5378         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5379
5380         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5381
5382         test_winreg_CloseKey(tctx, b2, &hive_handle);
5383
5384         talloc_free(p2);
5385
5386         return ret;
5387 }
5388
5389 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5390                                         struct dcerpc_binding_handle *b,
5391                                         const char *environment)
5392 {
5393         struct dcerpc_pipe *p2;
5394         bool ret = true;
5395         struct policy_handle hive_handle;
5396         struct dcerpc_binding_handle *b2;
5397
5398         torture_assert_ntstatus_ok(tctx,
5399                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5400                 "could not open winreg pipe");
5401         b2 = p2->binding_handle;
5402
5403         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5404
5405         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5406
5407         test_winreg_CloseKey(tctx, b2, &hive_handle);
5408
5409         talloc_free(p2);
5410
5411         return ret;
5412 }
5413
5414 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5415                                        struct dcerpc_pipe *p,
5416                                        struct policy_handle *handle,
5417                                        const char *printer_name)
5418 {
5419         struct spoolss_SetPrinterInfoCtr info_ctr;
5420         struct spoolss_DevmodeContainer devmode_ctr;
5421         struct sec_desc_buf secdesc_ctr;
5422         union spoolss_SetPrinterInfo sinfo;
5423         union spoolss_PrinterInfo info;
5424         struct dcerpc_binding_handle *b = p->binding_handle;
5425         const char *pname;
5426
5427         ZERO_STRUCT(info_ctr);
5428         ZERO_STRUCT(devmode_ctr);
5429         ZERO_STRUCT(secdesc_ctr);
5430
5431         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5432
5433         torture_assert(tctx,
5434                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5435                 "failed to query Printer level 2");
5436
5437         torture_assert(tctx,
5438                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5439                 "failed to convert");
5440
5441         info_ctr.level = 2;
5442         info_ctr.info = sinfo;
5443
5444 #define TEST_SZ(wname, iname) \
5445 do {\
5446         enum winreg_Type type;\
5447         uint8_t *data;\
5448         uint32_t needed;\
5449         DATA_BLOB blob;\
5450         const char *str;\
5451         torture_assert(tctx,\
5452                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5453                 "failed to query");\
5454         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5455         blob = data_blob_const(data, needed);\
5456         torture_assert(tctx,\
5457                 pull_reg_sz(tctx, &blob, &str),\
5458                 "failed to pull REG_SZ");\
5459         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5460 } while(0);
5461
5462
5463 #define TEST_SET_SZ(wname, iname, val) \
5464 do {\
5465         enum winreg_Type type;\
5466         uint8_t *data;\
5467         uint32_t needed;\
5468         DATA_BLOB blob;\
5469         const char *str;\
5470         sinfo.info2->iname = val;\
5471         torture_assert(tctx,\
5472                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5473                 "failed to call SetPrinter");\
5474         torture_assert(tctx,\
5475                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5476                 "failed to query");\
5477         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5478         blob = data_blob_const(data, needed);\
5479         torture_assert(tctx,\
5480                 pull_reg_sz(tctx, &blob, &str),\
5481                 "failed to pull REG_SZ");\
5482         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5483 } while(0);
5484
5485 #define TEST_SET_DWORD(wname, iname, val) \
5486 do {\
5487         enum winreg_Type type;\
5488         uint8_t *data;\
5489         uint32_t needed;\
5490         uint32_t value;\
5491         sinfo.info2->iname = val;\
5492         torture_assert(tctx,\
5493                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5494                 "failed to call SetPrinter");\
5495         torture_assert(tctx,\
5496                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5497                 "failed to query");\
5498         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5499         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5500         value = IVAL(data, 0); \
5501         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5502 } while(0);
5503
5504         TEST_SET_SZ("description", comment, "newval");
5505         TEST_SET_SZ("location", location, "newval");
5506         TEST_SET_SZ("driverName", drivername, "newval");
5507 /*      TEST_SET_DWORD("priority", priority, 25); */
5508
5509         torture_assert(tctx,
5510                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5511                 "failed to query Printer level 2");
5512
5513         TEST_SZ("description", info.info2.comment);
5514         TEST_SZ("driverName", info.info2.drivername);
5515         TEST_SZ("location", info.info2.location);
5516
5517         pname = strrchr(info.info2.printername, '\\');
5518         if (pname == NULL) {
5519                 pname = info.info2.printername;
5520         } else {
5521                 pname++;
5522         }
5523         TEST_SZ("printerName", pname);
5524         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5525         /* TEST_SZ("printShareName", info.info2.sharename); */
5526
5527         /* FIXME gd: complete the list */
5528
5529 #undef TEST_SZ
5530 #undef TEST_SET_SZ
5531 #undef TEST_DWORD
5532
5533         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5534
5535         return true;
5536 }
5537
5538 static bool test_print_processors_winreg(struct torture_context *tctx,
5539                                          void *private_data)
5540 {
5541         struct test_spoolss_context *ctx =
5542                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5543         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5544         struct dcerpc_binding_handle *b = p->binding_handle;
5545
5546         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5547 }
5548
5549 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5550                                          struct dcerpc_binding_handle *b,
5551                                          struct policy_handle *handle,
5552                                          uint32_t *change_id)
5553 {
5554         enum winreg_Type type;
5555         uint8_t *data;
5556         uint32_t needed;
5557
5558         torture_assert(tctx,
5559                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5560                 "failed to call GetPrinterData");
5561
5562         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5563         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5564
5565         *change_id = IVAL(data, 0);
5566
5567         return true;
5568 }
5569
5570 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5571                                            struct dcerpc_pipe *p,
5572                                            struct policy_handle *handle,
5573                                            uint32_t *change_id)
5574 {
5575         enum winreg_Type type;
5576         uint8_t *data;
5577         uint32_t needed;
5578
5579         torture_assert(tctx,
5580                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5581                 "failed to call GetPrinterData");
5582
5583         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5584         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5585
5586         *change_id = IVAL(data, 0);
5587
5588         return true;
5589 }
5590
5591 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5592                                          struct dcerpc_binding_handle *b,
5593                                          struct policy_handle *handle,
5594                                          uint32_t *change_id)
5595 {
5596         union spoolss_PrinterInfo info;
5597
5598         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5599                 "failed to query Printer level 0");
5600
5601         *change_id = info.info0.change_id;
5602
5603         return true;
5604 }
5605
5606 static bool test_ChangeID(struct torture_context *tctx,
5607                           struct dcerpc_pipe *p,
5608                           struct policy_handle *handle)
5609 {
5610         uint32_t change_id, change_id_ex, change_id_info;
5611         uint32_t change_id2, change_id_ex2, change_id_info2;
5612         union spoolss_PrinterInfo info;
5613         const char *comment;
5614         struct dcerpc_binding_handle *b = p->binding_handle;
5615
5616         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5617
5618         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5619                 "failed to query for ChangeID");
5620         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5621                 "failed to query for ChangeID");
5622         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5623                 "failed to query for ChangeID");
5624
5625         torture_assert_int_equal(tctx, change_id, change_id_ex,
5626                 "change_ids should all be equal");
5627         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5628                 "change_ids should all be equal");
5629
5630
5631         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5632
5633         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5634                 "failed to query for ChangeID");
5635         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5636                 "failed to query Printer level 2");
5637         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5638                 "failed to query for ChangeID");
5639         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5640                 "failed to query for ChangeID");
5641         torture_assert_int_equal(tctx, change_id, change_id_ex,
5642                 "change_id should not have changed");
5643         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5644                 "change_id should not have changed");
5645
5646
5647         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5648
5649         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5650                 "failed to query for ChangeID");
5651         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5652                 "failed to query for ChangeID");
5653         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5654                 "failed to query for ChangeID");
5655         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5656                 "failed to query Printer level 2");
5657         comment = talloc_strdup(tctx, info.info2.comment);
5658
5659         {
5660                 struct spoolss_SetPrinterInfoCtr info_ctr;
5661                 struct spoolss_DevmodeContainer devmode_ctr;
5662                 struct sec_desc_buf secdesc_ctr;
5663                 union spoolss_SetPrinterInfo sinfo;
5664
5665                 ZERO_STRUCT(info_ctr);
5666                 ZERO_STRUCT(devmode_ctr);
5667                 ZERO_STRUCT(secdesc_ctr);
5668
5669
5670                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5671                 sinfo.info2->comment    = "torture_comment";
5672
5673                 info_ctr.level = 2;
5674                 info_ctr.info = sinfo;
5675
5676                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5677                         "failed to call SetPrinter");
5678
5679                 sinfo.info2->comment    = comment;
5680
5681                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5682                         "failed to call SetPrinter");
5683
5684         }
5685
5686         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5687                 "failed to query for ChangeID");
5688         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5689                 "failed to query for ChangeID");
5690         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5691                 "failed to query for ChangeID");
5692
5693         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5694                 "change_ids should all be equal");
5695         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5696                 "change_ids should all be equal");
5697
5698         torture_assert(tctx, (change_id < change_id2),
5699                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5700                 change_id2, change_id));
5701         torture_assert(tctx, (change_id_ex < change_id_ex2),
5702                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5703                 change_id_ex2, change_id_ex));
5704         torture_assert(tctx, (change_id_info < change_id_info2),
5705                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5706                 change_id_info2, change_id_info));
5707
5708         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5709
5710         return true;
5711 }
5712
5713 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5714                                        struct dcerpc_pipe *p,
5715                                        struct policy_handle *handle)
5716 {
5717         NTSTATUS status;
5718         struct dcerpc_binding *b;
5719         struct dcerpc_pipe *p2;
5720         struct spoolss_ClosePrinter cp;
5721
5722         /* only makes sense on SMB */
5723         if (p->conn->transport.transport != NCACN_NP) {
5724                 return true;
5725         }
5726
5727         torture_comment(tctx, "Testing close on secondary pipe\n");
5728
5729         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5730         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5731
5732         status = dcerpc_secondary_connection(p, &p2, b);
5733         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5734
5735         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5736         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5737
5738         cp.in.handle = handle;
5739         cp.out.handle = handle;
5740
5741         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5742         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5743                         "ERROR: Allowed close on secondary connection");
5744
5745         talloc_free(p2);
5746
5747         return true;
5748 }
5749
5750 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5751                                      struct dcerpc_binding_handle *b, const char *name)
5752 {
5753         NTSTATUS status;
5754         struct spoolss_OpenPrinter op;
5755         struct spoolss_OpenPrinterEx opEx;
5756         struct policy_handle handle;
5757         bool ret = true;
5758
5759         op.in.printername       = name;
5760         op.in.datatype          = NULL;
5761         op.in.devmode_ctr.devmode= NULL;
5762         op.in.access_mask       = 0;
5763         op.out.handle           = &handle;
5764
5765         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5766
5767         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5768         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5769         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5770                 "unexpected result");
5771
5772         if (W_ERROR_IS_OK(op.out.result)) {
5773                 ret &=test_ClosePrinter(tctx, b, &handle);
5774         }
5775
5776         opEx.in.printername             = name;
5777         opEx.in.datatype                = NULL;
5778         opEx.in.devmode_ctr.devmode     = NULL;
5779         opEx.in.access_mask             = 0;
5780         opEx.in.level                   = 1;
5781         opEx.in.userlevel.level1        = NULL;
5782         opEx.out.handle                 = &handle;
5783
5784         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5785
5786         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5787         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5788         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5789                 "unexpected result");
5790
5791         if (W_ERROR_IS_OK(opEx.out.result)) {
5792                 ret &=test_ClosePrinter(tctx, b, &handle);
5793         }
5794
5795         return ret;
5796 }
5797
5798 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5799                                           void *private_data)
5800 {
5801         struct test_spoolss_context *ctx =
5802                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5803
5804         const char *badnames[] = {
5805                 "__INVALID_PRINTER__",
5806                 "\\\\__INVALID_HOST__",
5807                 "",
5808                 "\\\\\\",
5809                 "\\\\\\__INVALID_PRINTER__"
5810         };
5811         const char *badname;
5812         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5813         const char *server_name = dcerpc_server_name(p);
5814         struct dcerpc_binding_handle *b = p->binding_handle;
5815         int i;
5816
5817         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5818                 torture_assert(tctx,
5819                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5820                         "");
5821         }
5822
5823         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5824         torture_assert(tctx,
5825                 test_OpenPrinter_badname(tctx, b, badname),
5826                 "");
5827
5828         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5829         torture_assert(tctx,
5830                 test_OpenPrinter_badname(tctx, b, badname),
5831                 "");
5832
5833         return true;
5834 }
5835
5836 static bool test_OpenPrinter(struct torture_context *tctx,
5837                              struct dcerpc_pipe *p,
5838                              const char *name,
5839                              const char *environment,
5840                              bool open_only)
5841 {
5842         NTSTATUS status;
5843         struct spoolss_OpenPrinter r;
5844         struct policy_handle handle;
5845         bool ret = true;
5846         struct dcerpc_binding_handle *b = p->binding_handle;
5847
5848         r.in.printername        = name;
5849         r.in.datatype           = NULL;
5850         r.in.devmode_ctr.devmode= NULL;
5851         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5852         r.out.handle            = &handle;
5853
5854         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5855
5856         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5857
5858         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5859
5860         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5861
5862         if (open_only) {
5863                 goto close_printer;
5864         }
5865
5866         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5867                 ret = false;
5868         }
5869
5870         if (!torture_setting_bool(tctx, "samba3", false)) {
5871                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5872                         ret = false;
5873                 }
5874         }
5875
5876  close_printer:
5877         if (!test_ClosePrinter(tctx, b, &handle)) {
5878                 ret = false;
5879         }
5880
5881         return ret;
5882 }
5883
5884 static bool test_OpenPrinterEx(struct torture_context *tctx,
5885                                struct dcerpc_binding_handle *b,
5886                                const char *printername,
5887                                const char *datatype,
5888                                struct spoolss_DeviceMode *devmode,
5889                                uint32_t access_mask,
5890                                uint32_t level,
5891                                union spoolss_UserLevel *userlevel,
5892                                struct policy_handle *handle,
5893                                WERROR expected_result)
5894 {
5895         struct spoolss_OpenPrinterEx r;
5896
5897         r.in.printername        = printername;
5898         r.in.datatype           = datatype;
5899         r.in.devmode_ctr.devmode= devmode;
5900         r.in.access_mask        = access_mask;
5901         r.in.level              = level;
5902         r.in.userlevel          = *userlevel;
5903         r.out.handle            = handle;
5904
5905         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5906
5907         torture_assert_ntstatus_ok(tctx,
5908                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5909                 "OpenPrinterEx failed");
5910
5911         torture_assert_werr_equal(tctx, r.out.result, expected_result,
5912                 "OpenPrinterEx failed");
5913
5914         return true;
5915 }
5916
5917 static bool call_OpenPrinterEx(struct torture_context *tctx,
5918                                struct dcerpc_pipe *p,
5919                                const char *name,
5920                                struct spoolss_DeviceMode *devmode,
5921                                struct policy_handle *handle)
5922 {
5923         union spoolss_UserLevel userlevel;
5924         struct spoolss_UserLevel1 userlevel1;
5925         struct dcerpc_binding_handle *b = p->binding_handle;
5926
5927         userlevel1.size = 1234;
5928         userlevel1.client = "hello";
5929         userlevel1.user = "spottyfoot!";
5930         userlevel1.build = 1;
5931         userlevel1.major = 2;
5932         userlevel1.minor = 3;
5933         userlevel1.processor = 4;
5934
5935         userlevel.level1 = &userlevel1;
5936
5937         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5938                                   SEC_FLAG_MAXIMUM_ALLOWED,
5939                                   1,
5940                                   &userlevel,
5941                                   handle,
5942                                   WERR_OK);
5943 }
5944
5945 static bool test_printer_rename(struct torture_context *tctx,
5946                                 void *private_data)
5947 {
5948         struct torture_printer_context *t =
5949                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5950         struct dcerpc_pipe *p = t->spoolss_pipe;
5951
5952         bool ret = true;
5953         union spoolss_PrinterInfo info;
5954         union spoolss_SetPrinterInfo sinfo;
5955         struct spoolss_SetPrinterInfoCtr info_ctr;
5956         struct spoolss_DevmodeContainer devmode_ctr;
5957         struct sec_desc_buf secdesc_ctr;
5958         const char *printer_name;
5959         const char *printer_name_orig;
5960         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5961         struct policy_handle new_handle;
5962         const char *q;
5963         struct dcerpc_binding_handle *b = p->binding_handle;
5964
5965         ZERO_STRUCT(devmode_ctr);
5966         ZERO_STRUCT(secdesc_ctr);
5967
5968         torture_comment(tctx, "Testing Printer rename operations\n");
5969
5970         torture_assert(tctx,
5971                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5972                 "failed to call GetPrinter level 2");
5973
5974         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5975
5976         q = strrchr(info.info2.printername, '\\');
5977         if (q) {
5978                 torture_warning(tctx,
5979                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5980         }
5981
5982         torture_assert(tctx,
5983                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5984
5985         sinfo.info2->printername = printer_name_new;
5986
5987         info_ctr.level = 2;
5988         info_ctr.info = sinfo;
5989
5990         torture_assert(tctx,
5991                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5992                 "failed to call SetPrinter level 2");
5993
5994         torture_assert(tctx,
5995                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5996                 "failed to call GetPrinter level 2");
5997
5998         printer_name = talloc_strdup(tctx, info.info2.printername);
5999
6000         q = strrchr(info.info2.printername, '\\');
6001         if (q) {
6002                 torture_warning(tctx,
6003                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6004                 q++;
6005                 printer_name = q;
6006         }
6007
6008         torture_assert_str_equal(tctx, printer_name, printer_name_new,
6009                 "new printer name was not set");
6010
6011         /* samba currently cannot fully rename printers */
6012         if (!torture_setting_bool(tctx, "samba3", false)) {
6013                 torture_assert(tctx,
6014                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
6015                         "still can open printer with oldname after rename");
6016         } else {
6017                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6018         }
6019
6020         torture_assert(tctx,
6021                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6022                 "failed to open printer with new name");
6023
6024         torture_assert(tctx,
6025                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6026                 "failed to call GetPrinter level 2");
6027
6028         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6029                 "new printer name was not set");
6030
6031         torture_assert(tctx,
6032                 test_ClosePrinter(tctx, b, &new_handle),
6033                 "failed to close printer");
6034
6035         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6036
6037         return ret;
6038 }
6039
6040 static bool test_openprinter(struct torture_context *tctx,
6041                              struct dcerpc_binding_handle *b,
6042                              const char *real_printername)
6043 {
6044         union spoolss_UserLevel userlevel;
6045         struct policy_handle handle;
6046         struct spoolss_UserLevel1 userlevel1;
6047         const char *printername = NULL;
6048         int i;
6049
6050         struct {
6051                 const char *suffix;
6052                 WERROR expected_result;
6053         } tests[] = {
6054                 {
6055                         .suffix                 = "rubbish",
6056                         .expected_result        = WERR_INVALID_PRINTER_NAME
6057                 },{
6058                         .suffix                 = ", LocalOnl",
6059                         .expected_result        = WERR_INVALID_PRINTER_NAME
6060                 },{
6061                         .suffix                 = ", localOnly",
6062                         .expected_result        = WERR_INVALID_PRINTER_NAME
6063                 },{
6064                         .suffix                 = ", localonl",
6065                         .expected_result        = WERR_INVALID_PRINTER_NAME
6066                 },{
6067                         .suffix                 = ",LocalOnl",
6068                         .expected_result        = WERR_INVALID_PRINTER_NAME
6069                 },{
6070                         .suffix                 = ",localOnl2",
6071                         .expected_result        = WERR_INVALID_PRINTER_NAME
6072                 },{
6073                         .suffix                 = ", DrvConver2t",
6074                         .expected_result        = WERR_INVALID_PRINTER_NAME
6075                 },{
6076                         .suffix                 = ", drvconvert",
6077                         .expected_result        = WERR_INVALID_PRINTER_NAME
6078                 },{
6079                         .suffix                 = ",drvconvert",
6080                         .expected_result        = WERR_INVALID_PRINTER_NAME
6081                 },{
6082                         .suffix                 = ", DrvConvert",
6083                         .expected_result        = WERR_OK
6084                 },{
6085                         .suffix                 = " , DrvConvert",
6086                         .expected_result        = WERR_INVALID_PRINTER_NAME
6087                 },{
6088                         .suffix                 = ",DrvConvert",
6089                         .expected_result        = WERR_OK
6090                 },{
6091                         .suffix                 = ", DrvConvertsadfasdf",
6092                         .expected_result        = WERR_OK
6093                 },{
6094                         .suffix                 = ",DrvConvertasdfasd",
6095                         .expected_result        = WERR_OK
6096                 },{
6097                         .suffix                 = ", LocalOnly",
6098                         .expected_result        = WERR_OK
6099                 },{
6100                         .suffix                 = " , LocalOnly",
6101                         .expected_result        = WERR_INVALID_PRINTER_NAME
6102                 },{
6103                         .suffix                 = ",LocalOnly",
6104                         .expected_result        = WERR_OK
6105                 },{
6106                         .suffix                 = ", LocalOnlysagi4gjfkd",
6107                         .expected_result        = WERR_OK
6108                 },{
6109                         .suffix                 = ",LocalOnlysagi4gjfkd",
6110                         .expected_result        = WERR_OK
6111                 }
6112         };
6113
6114         userlevel1.size = 1234;
6115         userlevel1.client = "hello";
6116         userlevel1.user = "spottyfoot!";
6117         userlevel1.build = 1;
6118         userlevel1.major = 2;
6119         userlevel1.minor = 3;
6120         userlevel1.processor = 4;
6121
6122         userlevel.level1 = &userlevel1;
6123
6124         torture_comment(tctx, "Testing openprinterex printername pattern\n");
6125
6126         torture_assert(tctx,
6127                 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6128                                    &userlevel, &handle,
6129                                    WERR_OK),
6130                 "OpenPrinterEx failed");
6131         test_ClosePrinter(tctx, b, &handle);
6132
6133         for (i=0; i < ARRAY_SIZE(tests); i++) {
6134
6135                 printername = talloc_asprintf(tctx, "%s%s",
6136                                               real_printername,
6137                                               tests[i].suffix);
6138
6139                 torture_assert(tctx,
6140                         test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6141                                            &userlevel, &handle,
6142                                            tests[i].expected_result),
6143                         "OpenPrinterEx failed");
6144                 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6145                         test_ClosePrinter(tctx, b, &handle);
6146                 }
6147         }
6148
6149         return true;
6150 }
6151
6152
6153 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6154                                                 struct dcerpc_pipe *p,
6155                                                 const char *name,
6156                                                 const char *environment)
6157 {
6158         struct policy_handle handle;
6159         bool ret = true;
6160         struct dcerpc_binding_handle *b = p->binding_handle;
6161
6162         if (!test_openprinter(tctx, b, name)) {
6163                 return false;
6164         }
6165
6166         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6167                 return false;
6168         }
6169
6170         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6171                 ret = false;
6172         }
6173
6174         if (!test_GetPrinter(tctx, b, &handle, environment)) {
6175                 ret = false;
6176         }
6177
6178         if (!test_EnumForms_all(tctx, b, &handle, false)) {
6179                 ret = false;
6180         }
6181
6182         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6183                 ret = false;
6184         }
6185
6186         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6187                 ret = false;
6188         }
6189
6190         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6191                 ret = false;
6192         }
6193
6194         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6195                 ret = false;
6196         }
6197
6198         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6199                 ret = false;
6200         }
6201
6202         if (!test_printer_all_keys(tctx, b, &handle)) {
6203                 ret = false;
6204         }
6205
6206         if (!test_PausePrinter(tctx, b, &handle)) {
6207                 ret = false;
6208         }
6209
6210         if (!test_DoPrintTest(tctx, b, &handle)) {
6211                 ret = false;
6212         }
6213
6214         if (!test_ResumePrinter(tctx, b, &handle)) {
6215                 ret = false;
6216         }
6217
6218         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6219                 ret = false;
6220         }
6221
6222         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6223                 ret = false;
6224         }
6225
6226         if (!torture_setting_bool(tctx, "samba3", false)) {
6227                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6228                         ret = false;
6229                 }
6230         }
6231
6232         if (!test_ClosePrinter(tctx, b, &handle)) {
6233                 ret = false;
6234         }
6235
6236         return ret;
6237 }
6238
6239 static bool test_EnumPrinters_old(struct torture_context *tctx,
6240                                   void *private_data)
6241 {
6242         struct test_spoolss_context *ctx =
6243                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6244         struct spoolss_EnumPrinters r;
6245         NTSTATUS status;
6246         uint16_t levels[] = {1, 2, 4, 5};
6247         int i;
6248         bool ret = true;
6249         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6250         struct dcerpc_binding_handle *b = p->binding_handle;
6251
6252         for (i=0;i<ARRAY_SIZE(levels);i++) {
6253                 union spoolss_PrinterInfo *info;
6254                 int j;
6255                 uint32_t needed;
6256                 uint32_t count;
6257
6258                 r.in.flags      = PRINTER_ENUM_LOCAL;
6259                 r.in.server     = "";
6260                 r.in.level      = levels[i];
6261                 r.in.buffer     = NULL;
6262                 r.in.offered    = 0;
6263                 r.out.needed    = &needed;
6264                 r.out.count     = &count;
6265                 r.out.info      = &info;
6266
6267                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6268
6269                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6270                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6271
6272                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6273                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6274                         r.in.buffer = &blob;
6275                         r.in.offered = needed;
6276                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6277                 }
6278
6279                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6280
6281                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6282
6283                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6284
6285                 if (!info) {
6286                         torture_comment(tctx, "No printers returned\n");
6287                         return true;
6288                 }
6289
6290                 for (j=0;j<count;j++) {
6291                         if (r.in.level == 1) {
6292                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
6293                                 char *slash, *name, *full_name;
6294                                 name = unc;
6295                                 if (unc[0] == '\\' && unc[1] == '\\') {
6296                                         unc +=2;
6297                                 }
6298                                 slash = strchr(unc, '\\');
6299                                 if (slash) {
6300                                         slash++;
6301                                         name = slash;
6302                                 }
6303                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6304                                                             dcerpc_server_name(p), name);
6305                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6306                                         ret = false;
6307                                 }
6308                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6309                                         ret = false;
6310                                 }
6311                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6312                                         ret = false;
6313                                 }
6314                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6315                                         ret = false;
6316                                 }
6317                         }
6318                 }
6319         }
6320
6321         return ret;
6322 }
6323
6324 static bool test_EnumPrinters_level(struct torture_context *tctx,
6325                                     struct dcerpc_binding_handle *b,
6326                                     uint32_t flags,
6327                                     const char *servername,
6328                                     uint32_t level,
6329                                     uint32_t *count_p,
6330                                     union spoolss_PrinterInfo **info_p)
6331 {
6332         struct spoolss_EnumPrinters r;
6333         union spoolss_PrinterInfo *info;
6334         uint32_t needed;
6335         uint32_t count;
6336
6337         r.in.flags      = flags;
6338         r.in.server     = servername;
6339         r.in.level      = level;
6340         r.in.buffer     = NULL;
6341         r.in.offered    = 0;
6342         r.out.needed    = &needed;
6343         r.out.count     = &count;
6344         r.out.info      = &info;
6345
6346         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6347                 r.in.server, r.in.level);
6348
6349         torture_assert_ntstatus_ok(tctx,
6350                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6351                 "EnumPrinters failed");
6352         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6353                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6354                 r.in.buffer = &blob;
6355                 r.in.offered = needed;
6356                 torture_assert_ntstatus_ok(tctx,
6357                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6358                         "EnumPrinters failed");
6359         }
6360
6361         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6362
6363         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6364
6365         if (count_p) {
6366                 *count_p = count;
6367         }
6368         if (info_p) {
6369                 *info_p = info;
6370         }
6371
6372         return true;
6373 }
6374
6375 static const char *get_short_printername(struct torture_context *tctx,
6376                                          const char *name)
6377 {
6378         const char *short_name;
6379
6380         if (name[0] == '\\' && name[1] == '\\') {
6381                 name += 2;
6382                 short_name = strchr(name, '\\');
6383                 if (short_name) {
6384                         return talloc_strdup(tctx, short_name+1);
6385                 }
6386         }
6387
6388         return name;
6389 }
6390
6391 static const char *get_full_printername(struct torture_context *tctx,
6392                                         const char *name)
6393 {
6394         const char *full_name = talloc_strdup(tctx, name);
6395         char *p;
6396
6397         if (name && name[0] == '\\' && name[1] == '\\') {
6398                 name += 2;
6399                 p = strchr(name, '\\');
6400                 if (p) {
6401                         return full_name;
6402                 }
6403         }
6404
6405         return NULL;
6406 }
6407
6408 static bool test_OnePrinter_servername(struct torture_context *tctx,
6409                                        struct dcerpc_pipe *p,
6410                                        struct dcerpc_binding_handle *b,
6411                                        const char *servername,
6412                                        const char *printername)
6413 {
6414         union spoolss_PrinterInfo info;
6415         const char *short_name = get_short_printername(tctx, printername);
6416         const char *full_name = get_full_printername(tctx, printername);
6417
6418         if (short_name) {
6419                 struct policy_handle handle;
6420                 torture_assert(tctx,
6421                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6422                         "failed to open printer");
6423
6424                 torture_assert(tctx,
6425                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6426                         "failed to get printer info");
6427
6428                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6429                         "unexpected servername");
6430                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6431                         "unexpected printername");
6432
6433                 if (info.info2.devmode) {
6434                         const char *expected_devicename;
6435                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6436                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6437                                 "unexpected devicemode devicename");
6438                 }
6439
6440                 torture_assert(tctx,
6441                         test_ClosePrinter(tctx, b, &handle),
6442                         "failed to close printer");
6443         }
6444
6445         if (full_name) {
6446                 struct policy_handle handle;
6447
6448                 torture_assert(tctx,
6449                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6450                         "failed to open printer");
6451
6452                 torture_assert(tctx,
6453                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6454                         "failed to get printer info");
6455
6456                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6457                         "unexpected servername");
6458                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6459                         "unexpected printername");
6460
6461                 if (info.info2.devmode) {
6462                         const char *expected_devicename;
6463                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6464                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6465                                 "unexpected devicemode devicename");
6466                 }
6467
6468                 torture_assert(tctx,
6469                         test_ClosePrinter(tctx, b, &handle),
6470                         "failed to close printer");
6471         }
6472
6473         return true;
6474 }
6475
6476 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6477                                          void *private_data)
6478 {
6479         struct test_spoolss_context *ctx =
6480                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6481         int i;
6482         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6483         struct dcerpc_binding_handle *b = p->binding_handle;
6484         uint32_t count;
6485         union spoolss_PrinterInfo *info;
6486         const char *servername;
6487         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6488
6489         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6490
6491         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6492
6493         torture_assert(tctx,
6494                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6495                 "failed to enumerate printers");
6496
6497         for (i=0; i < count; i++) {
6498
6499                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6500                         "unexpected servername");
6501
6502                 torture_assert(tctx,
6503                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6504                         "failed to check printer");
6505         }
6506
6507         servername = "";
6508
6509         torture_assert(tctx,
6510                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6511                 "failed to enumerate printers");
6512
6513         for (i=0; i < count; i++) {
6514
6515                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6516                         "unexpected servername");
6517
6518                 torture_assert(tctx,
6519                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6520                         "failed to check printer");
6521         }
6522
6523
6524         return true;
6525 }
6526
6527
6528 static bool test_GetPrinterDriver(struct torture_context *tctx,
6529                                   struct dcerpc_binding_handle *b,
6530                                   struct policy_handle *handle,
6531                                   const char *driver_name)
6532 {
6533         struct spoolss_GetPrinterDriver r;
6534         uint32_t needed;
6535
6536         r.in.handle = handle;
6537         r.in.architecture = "W32X86";
6538         r.in.level = 1;
6539         r.in.buffer = NULL;
6540         r.in.offered = 0;
6541         r.out.needed = &needed;
6542
6543         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6544
6545         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6546                 "failed to call GetPrinterDriver");
6547         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6548                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6549                 r.in.buffer = &blob;
6550                 r.in.offered = needed;
6551                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6552                         "failed to call GetPrinterDriver");
6553         }
6554
6555         torture_assert_werr_ok(tctx, r.out.result,
6556                 "failed to call GetPrinterDriver");
6557
6558         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6559
6560         return true;
6561 }
6562
6563 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6564                                          struct dcerpc_binding_handle *b,
6565                                          struct policy_handle *handle,
6566                                          const char *driver_name,
6567                                          const char *architecture,
6568                                          uint32_t level,
6569                                          uint32_t client_major_version,
6570                                          uint32_t client_minor_version,
6571                                          union spoolss_DriverInfo *info_p,
6572                                          WERROR *result_p)
6573
6574 {
6575         struct spoolss_GetPrinterDriver2 r;
6576         uint32_t needed;
6577         uint32_t server_major_version;
6578         uint32_t server_minor_version;
6579
6580         r.in.handle = handle;
6581         r.in.architecture = architecture;
6582         r.in.client_major_version = client_major_version;
6583         r.in.client_minor_version = client_minor_version;
6584         r.in.buffer = NULL;
6585         r.in.offered = 0;
6586         r.in.level = level;
6587         r.out.needed = &needed;
6588         r.out.server_major_version = &server_major_version;
6589         r.out.server_minor_version = &server_minor_version;
6590
6591         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6592                 driver_name, r.in.level);
6593
6594         torture_assert_ntstatus_ok(tctx,
6595                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6596                 "failed to call GetPrinterDriver2");
6597         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6598                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6599                 r.in.buffer = &blob;
6600                 r.in.offered = needed;
6601                 torture_assert_ntstatus_ok(tctx,
6602                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6603                         "failed to call GetPrinterDriver2");
6604         }
6605
6606         if (result_p) {
6607                 *result_p = r.out.result;
6608         }
6609
6610         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6611                 switch (r.in.level) {
6612                 case 101:
6613                 case 8:
6614                         torture_comment(tctx,
6615                                 "level %d not implemented, not considering as an error\n",
6616                                 r.in.level);
6617                         return true;
6618                 default:
6619                         break;
6620                 }
6621         }
6622
6623         torture_assert_werr_ok(tctx, r.out.result,
6624                 "failed to call GetPrinterDriver2");
6625
6626         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6627
6628         if (info_p) {
6629                 *info_p = *r.out.info;
6630         }
6631
6632         return true;
6633 }
6634
6635 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6636                                    struct dcerpc_binding_handle *b,
6637                                    struct policy_handle *handle,
6638                                    const char *driver_name,
6639                                    const char *architecture)
6640 {
6641         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6642         int i;
6643
6644
6645         for (i=0;i<ARRAY_SIZE(levels);i++) {
6646
6647                 torture_assert(tctx,
6648                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6649                         "");
6650         }
6651
6652         return true;
6653 }
6654
6655 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6656                                         void *private_data)
6657 {
6658         struct test_spoolss_context *ctx =
6659                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6660         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6661         int i;
6662         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6663         struct dcerpc_binding_handle *b = p->binding_handle;
6664         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6665
6666         for (i=0;i<ARRAY_SIZE(levels);i++) {
6667
6668                 uint32_t count;
6669                 union spoolss_DriverInfo *info;
6670
6671                 torture_assert(tctx,
6672                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6673                         "failed to enumerate drivers");
6674
6675                 if (!info) {
6676                         torture_comment(tctx, "No printer drivers returned\n");
6677                         break;
6678                 }
6679         }
6680
6681         return true;
6682 }
6683
6684 static bool test_DeletePrinter(struct torture_context *tctx,
6685                                struct dcerpc_binding_handle *b,
6686                                struct policy_handle *handle)
6687 {
6688         struct spoolss_DeletePrinter r;
6689
6690         torture_comment(tctx, "Testing DeletePrinter\n");
6691
6692         r.in.handle = handle;
6693
6694         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6695                 "failed to delete printer");
6696         torture_assert_werr_ok(tctx, r.out.result,
6697                 "failed to delete printer");
6698
6699         return true;
6700 }
6701
6702 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6703                                        struct dcerpc_binding_handle *b,
6704                                        uint32_t flags,
6705                                        uint32_t level,
6706                                        const char *name,
6707                                        bool *found)
6708 {
6709         struct spoolss_EnumPrinters e;
6710         uint32_t count;
6711         union spoolss_PrinterInfo *info;
6712         uint32_t needed;
6713         int i;
6714
6715         *found = false;
6716
6717         e.in.flags = flags;
6718         e.in.server = NULL;
6719         e.in.level = level;
6720         e.in.buffer = NULL;
6721         e.in.offered = 0;
6722         e.out.count = &count;
6723         e.out.info = &info;
6724         e.out.needed = &needed;
6725
6726         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6727                 "failed to enum printers");
6728
6729         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6730                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6731                 e.in.buffer = &blob;
6732                 e.in.offered = needed;
6733
6734                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6735                         "failed to enum printers");
6736         }
6737
6738         torture_assert_werr_ok(tctx, e.out.result,
6739                 "failed to enum printers");
6740
6741         for (i=0; i < count; i++) {
6742
6743                 const char *current = NULL;
6744                 const char *q;
6745
6746                 switch (level) {
6747                 case 1:
6748                         current = info[i].info1.name;
6749                         break;
6750                 }
6751
6752                 if (strequal(current, name)) {
6753                         *found = true;
6754                         break;
6755                 }
6756
6757                 q = strrchr(current, '\\');
6758                 if (q) {
6759                         if (!e.in.server) {
6760                                 torture_warning(tctx,
6761                                         "server returns printername %s incl. servername although we did not set servername", current);
6762                         }
6763                         q++;
6764                         if (strequal(q, name)) {
6765                                 *found = true;
6766                                 break;
6767                         }
6768                 }
6769         }
6770
6771         return true;
6772 }
6773
6774 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6775                                       struct dcerpc_pipe *p,
6776                                       const char *printername,
6777                                       bool ex)
6778 {
6779         WERROR result;
6780         struct spoolss_AddPrinter r;
6781         struct spoolss_AddPrinterEx rex;
6782         struct spoolss_SetPrinterInfoCtr info_ctr;
6783         struct spoolss_SetPrinterInfo1 info1;
6784         struct spoolss_DevmodeContainer devmode_ctr;
6785         struct sec_desc_buf secdesc_ctr;
6786         struct spoolss_UserLevelCtr userlevel_ctr;
6787         struct policy_handle handle;
6788         bool found = false;
6789         struct dcerpc_binding_handle *b = p->binding_handle;
6790
6791         ZERO_STRUCT(devmode_ctr);
6792         ZERO_STRUCT(secdesc_ctr);
6793         ZERO_STRUCT(userlevel_ctr);
6794         ZERO_STRUCT(info1);
6795
6796         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6797                         ex ? "Ex":"", printername);
6798
6799         /* try to add printer to wellknown printer list (level 1) */
6800
6801         userlevel_ctr.level = 1;
6802
6803         info_ctr.info.info1 = &info1;
6804         info_ctr.level = 1;
6805
6806         rex.in.server = NULL;
6807         rex.in.info_ctr = &info_ctr;
6808         rex.in.devmode_ctr = &devmode_ctr;
6809         rex.in.secdesc_ctr = &secdesc_ctr;
6810         rex.in.userlevel_ctr = &userlevel_ctr;
6811         rex.out.handle = &handle;
6812
6813         r.in.server = NULL;
6814         r.in.info_ctr = &info_ctr;
6815         r.in.devmode_ctr = &devmode_ctr;
6816         r.in.secdesc_ctr = &secdesc_ctr;
6817         r.out.handle = &handle;
6818
6819         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6820                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6821                 "failed to add printer");
6822         result = ex ? rex.out.result : r.out.result;
6823         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6824                 "unexpected result code");
6825
6826         info1.name = printername;
6827         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6828
6829         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6830                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6831                 "failed to add printer");
6832         result = ex ? rex.out.result : r.out.result;
6833         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6834                 "unexpected result code");
6835
6836         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6837            better do a real check to see the printer is really there */
6838
6839         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6840                                                         PRINTER_ENUM_NETWORK, 1,
6841                                                         printername,
6842                                                         &found),
6843                         "failed to enum printers");
6844
6845         torture_assert(tctx, found, "failed to find newly added printer");
6846
6847         info1.flags = 0;
6848
6849         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6850                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6851                 "failed to add printer");
6852         result = ex ? rex.out.result : r.out.result;
6853         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6854                 "unexpected result code");
6855
6856         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6857            better do a real check to see the printer has really been removed
6858            from the well known printer list */
6859
6860         found = false;
6861
6862         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6863                                                         PRINTER_ENUM_NETWORK, 1,
6864                                                         printername,
6865                                                         &found),
6866                         "failed to enum printers");
6867 #if 0
6868         torture_assert(tctx, !found, "printer still in well known printer list");
6869 #endif
6870         return true;
6871 }
6872
6873 static bool test_AddPrinter_normal(struct torture_context *tctx,
6874                                    struct dcerpc_pipe *p,
6875                                    struct policy_handle *handle_p,
6876                                    const char *printername,
6877                                    const char *drivername,
6878                                    const char *portname,
6879                                    struct spoolss_DeviceMode *devmode,
6880                                    bool ex)
6881 {
6882         WERROR result;
6883         struct spoolss_AddPrinter r;
6884         struct spoolss_AddPrinterEx rex;
6885         struct spoolss_SetPrinterInfoCtr info_ctr;
6886         struct spoolss_SetPrinterInfo2 info2;
6887         struct spoolss_DevmodeContainer devmode_ctr;
6888         struct sec_desc_buf secdesc_ctr;
6889         struct spoolss_UserLevelCtr userlevel_ctr;
6890         struct policy_handle handle;
6891         bool found = false;
6892         bool existing_printer_deleted = false;
6893         struct dcerpc_binding_handle *b = p->binding_handle;
6894
6895         ZERO_STRUCT(devmode_ctr);
6896         ZERO_STRUCT(secdesc_ctr);
6897         ZERO_STRUCT(userlevel_ctr);
6898
6899         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6900                         ex ? "Ex":"", printername);
6901
6902         devmode_ctr.devmode = devmode;
6903
6904         userlevel_ctr.level = 1;
6905
6906         rex.in.server = NULL;
6907         rex.in.info_ctr = &info_ctr;
6908         rex.in.devmode_ctr = &devmode_ctr;
6909         rex.in.secdesc_ctr = &secdesc_ctr;
6910         rex.in.userlevel_ctr = &userlevel_ctr;
6911         rex.out.handle = &handle;
6912
6913         r.in.server = NULL;
6914         r.in.info_ctr = &info_ctr;
6915         r.in.devmode_ctr = &devmode_ctr;
6916         r.in.secdesc_ctr = &secdesc_ctr;
6917         r.out.handle = &handle;
6918
6919  again:
6920
6921         /* try to add printer to printer list (level 2) */
6922
6923         ZERO_STRUCT(info2);
6924
6925         info_ctr.info.info2 = &info2;
6926         info_ctr.level = 2;
6927
6928         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6929                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6930                 "failed to add printer");
6931         result = ex ? rex.out.result : r.out.result;
6932         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6933                 "unexpected result code");
6934
6935         info2.printername = printername;
6936
6937         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6938                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6939                 "failed to add printer");
6940         result = ex ? rex.out.result : r.out.result;
6941
6942         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6943                 struct policy_handle printer_handle;
6944
6945                 if (existing_printer_deleted) {
6946                         torture_fail(tctx, "already deleted printer still existing?");
6947                 }
6948
6949                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6950                         "failed to open printer handle");
6951
6952                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6953                         "failed to delete printer");
6954
6955                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6956                         "failed to close server handle");
6957
6958                 existing_printer_deleted = true;
6959
6960                 goto again;
6961         }
6962
6963         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6964                 "unexpected result code");
6965
6966         info2.portname = portname;
6967
6968         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6969                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6970                 "failed to add printer");
6971         result = ex ? rex.out.result : r.out.result;
6972         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6973                 "unexpected result code");
6974
6975         info2.drivername = drivername;
6976
6977         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6978                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6979                 "failed to add printer");
6980         result = ex ? rex.out.result : r.out.result;
6981
6982         /* w2k8r2 allows to add printer w/o defining printprocessor */
6983
6984         if (!W_ERROR_IS_OK(result)) {
6985                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6986                         "unexpected result code");
6987
6988                 info2.printprocessor = "winprint";
6989
6990                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6991                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6992                         "failed to add printer");
6993                 result = ex ? rex.out.result : r.out.result;
6994                 torture_assert_werr_ok(tctx, result,
6995                         "failed to add printer");
6996         }
6997
6998         *handle_p = handle;
6999
7000         /* we are paranoid, really check if the printer is there now */
7001
7002         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7003                                                         PRINTER_ENUM_LOCAL, 1,
7004                                                         printername,
7005                                                         &found),
7006                         "failed to enum printers");
7007         torture_assert(tctx, found, "failed to find newly added printer");
7008
7009         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7010                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7011                 "failed to add printer");
7012         result = ex ? rex.out.result : r.out.result;
7013         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7014                 "unexpected result code");
7015
7016         return true;
7017 }
7018
7019 static bool test_printer_info(struct torture_context *tctx,
7020                               void *private_data)
7021 {
7022         struct torture_printer_context *t =
7023                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7024         struct dcerpc_pipe *p = t->spoolss_pipe;
7025         struct dcerpc_binding_handle *b = p->binding_handle;
7026
7027         bool ret = true;
7028
7029         if (torture_setting_bool(tctx, "samba3", false)) {
7030                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7031         }
7032
7033         if (!test_PrinterInfo(tctx, b, &t->handle)) {
7034                 ret = false;
7035         }
7036
7037         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7038                 ret = false;
7039         }
7040
7041         return ret;
7042 }
7043
7044 static bool test_EnumPrinterKey(struct torture_context *tctx,
7045                                 struct dcerpc_binding_handle *b,
7046                                 struct policy_handle *handle,
7047                                 const char *key_name,
7048                                 const char ***array)
7049 {
7050         struct spoolss_EnumPrinterKey r;
7051         uint32_t needed = 0;
7052         union spoolss_KeyNames key_buffer;
7053         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7054         uint32_t _ndr_size;
7055         int i;
7056
7057         r.in.handle = handle;
7058         r.in.key_name = key_name;
7059         r.out.key_buffer = &key_buffer;
7060         r.out.needed = &needed;
7061         r.out._ndr_size = &_ndr_size;
7062
7063         for (i=0; i < ARRAY_SIZE(offered); i++) {
7064
7065                 if (offered[i] < 0 && needed) {
7066                         if (needed <= 4) {
7067                                 continue;
7068                         }
7069                         r.in.offered = needed + offered[i];
7070                 } else {
7071                         r.in.offered = offered[i];
7072                 }
7073
7074                 ZERO_STRUCT(key_buffer);
7075
7076                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7077
7078                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7079                         "failed to call EnumPrinterKey");
7080                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7081
7082                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
7083                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7084                                         _ndr_size, r.in.offered/2));
7085
7086                         r.in.offered = needed;
7087                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7088                                 "failed to call EnumPrinterKey");
7089                 }
7090
7091                 if (offered[i] > 0) {
7092                         torture_assert_werr_ok(tctx, r.out.result,
7093                                 "failed to call EnumPrinterKey");
7094                 }
7095
7096                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7097                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7098                                 _ndr_size, r.in.offered/2));
7099
7100                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7101                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7102
7103                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7104                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7105
7106                 if (key_buffer.string_array) {
7107                         uint32_t calc_needed = 0;
7108                         int s;
7109                         for (s=0; key_buffer.string_array[s]; s++) {
7110                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7111                         }
7112                         if (!key_buffer.string_array[0]) {
7113                                 calc_needed += 2;
7114                         }
7115                         calc_needed += 2;
7116
7117                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7118                                 "EnumPrinterKey unexpected size");
7119                 }
7120         }
7121
7122         if (array) {
7123                 *array = key_buffer.string_array;
7124         }
7125
7126         return true;
7127 }
7128
7129 bool test_printer_all_keys(struct torture_context *tctx,
7130                            struct dcerpc_binding_handle *b,
7131                            struct policy_handle *handle)
7132 {
7133         const char **key_array = NULL;
7134         int i;
7135
7136         torture_comment(tctx, "Testing Printer Keys\n");
7137
7138         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7139                 "failed to call test_EnumPrinterKey");
7140
7141         for (i=0; key_array && key_array[i]; i++) {
7142                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7143                         "failed to call test_EnumPrinterKey");
7144         }
7145         for (i=0; key_array && key_array[i]; i++) {
7146                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7147                         "failed to call test_EnumPrinterDataEx");
7148         }
7149
7150         torture_comment(tctx, "Printer Keys test succeeded\n\n");
7151
7152         return true;
7153 }
7154
7155 static bool test_openprinter_wrap(struct torture_context *tctx,
7156                                   void *private_data)
7157 {
7158         struct torture_printer_context *t =
7159                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7160         struct dcerpc_pipe *p = t->spoolss_pipe;
7161         struct dcerpc_binding_handle *b = p->binding_handle;
7162         const char *printername = t->info2.printername;
7163
7164         return test_openprinter(tctx, b, printername);
7165 }
7166
7167 static bool test_csetprinter(struct torture_context *tctx,
7168                              void *private_data)
7169 {
7170         struct torture_printer_context *t =
7171                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7172         struct dcerpc_pipe *p = t->spoolss_pipe;
7173
7174         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7175         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7176         const char *portname = t->info2.portname;
7177
7178         union spoolss_PrinterInfo info;
7179         struct policy_handle new_handle, new_handle2;
7180         struct dcerpc_binding_handle *b = p->binding_handle;
7181
7182         torture_comment(tctx, "Testing c_setprinter\n");
7183
7184         torture_assert(tctx,
7185                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7186                 "failed to get level 0 printer info");
7187         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7188                 info.info0.c_setprinter);
7189
7190         /* check if c_setprinter on 1st handle increases after a printer has
7191          * been added */
7192
7193         torture_assert(tctx,
7194                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7195                 "failed to add new printer");
7196         torture_assert(tctx,
7197                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7198                 "failed to get level 0 printer info");
7199         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7200                 info.info0.c_setprinter);
7201
7202         /* check if c_setprinter on new handle increases after a printer has
7203          * been added */
7204
7205         torture_assert(tctx,
7206                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7207                 "failed to get level 0 printer info");
7208         torture_comment(tctx, "csetprinter on created handle: %d\n",
7209                 info.info0.c_setprinter);
7210
7211         /* open the new printer and check if c_setprinter increases */
7212
7213         torture_assert(tctx,
7214                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7215                 "failed to open created printer");
7216         torture_assert(tctx,
7217                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7218                 "failed to get level 0 printer info");
7219         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7220                 info.info0.c_setprinter);
7221
7222         /* cleanup */
7223
7224         torture_assert(tctx,
7225                 test_ClosePrinter(tctx, b, &new_handle2),
7226                 "failed to close printer");
7227         torture_assert(tctx,
7228                 test_DeletePrinter(tctx, b, &new_handle),
7229                 "failed to delete new printer");
7230
7231         return true;
7232 }
7233
7234 static bool compose_local_driver_directory(struct torture_context *tctx,
7235                                            const char *environment,
7236                                            const char *local_dir,
7237                                            const char **path)
7238 {
7239         char *p;
7240
7241         p = strrchr(local_dir, '/');
7242         if (!p) {
7243                 return NULL;
7244         }
7245         p++;
7246
7247         if (strequal(environment, "Windows x64")) {
7248                 if (!strequal(p, "x64")) {
7249                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7250                 }
7251         } else if (strequal(environment, "Windows NT x86")) {
7252                 if (!strequal(p, "i386")) {
7253                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7254                 }
7255         } else {
7256                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7257         }
7258
7259         return true;
7260 }
7261
7262 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7263                                                      const char *devicename)
7264 {
7265         struct spoolss_DeviceMode *r;
7266
7267         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7268         if (r == NULL) {
7269                 return NULL;
7270         }
7271
7272         r->devicename           = talloc_strdup(r, devicename);
7273         r->specversion          = DMSPEC_NT4_AND_ABOVE;
7274         r->driverversion        = 0x0600;
7275         r->size                 = 0x00dc;
7276         r->__driverextra_length = 0;
7277         r->fields               = DEVMODE_FORMNAME |
7278                                   DEVMODE_TTOPTION |
7279                                   DEVMODE_PRINTQUALITY |
7280                                   DEVMODE_DEFAULTSOURCE |
7281                                   DEVMODE_COPIES |
7282                                   DEVMODE_SCALE |
7283                                   DEVMODE_PAPERSIZE |
7284                                   DEVMODE_ORIENTATION;
7285         r->orientation          = DMORIENT_PORTRAIT;
7286         r->papersize            = DMPAPER_LETTER;
7287         r->paperlength          = 0;
7288         r->paperwidth           = 0;
7289         r->scale                = 100;
7290         r->copies               = 55;
7291         r->defaultsource        = DMBIN_FORMSOURCE;
7292         r->printquality         = DMRES_HIGH;
7293         r->color                = DMRES_MONOCHROME;
7294         r->duplex               = DMDUP_SIMPLEX;
7295         r->yresolution          = 0;
7296         r->ttoption             = DMTT_SUBDEV;
7297         r->collate              = DMCOLLATE_FALSE;
7298         r->formname             = talloc_strdup(r, "Letter");
7299
7300         return r;
7301 }
7302
7303 static bool test_architecture_buffer(struct torture_context *tctx,
7304                                      void *private_data)
7305 {
7306         struct test_spoolss_context *ctx =
7307                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7308
7309         struct spoolss_OpenPrinterEx r;
7310         struct spoolss_UserLevel1 u1;
7311         struct policy_handle handle;
7312         uint32_t architectures[] = {
7313                 PROCESSOR_ARCHITECTURE_INTEL,
7314                 PROCESSOR_ARCHITECTURE_IA64,
7315                 PROCESSOR_ARCHITECTURE_AMD64
7316         };
7317         uint32_t needed[3];
7318         int i;
7319         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7320         struct dcerpc_binding_handle *b = p->binding_handle;
7321
7322         for (i=0; i < ARRAY_SIZE(architectures); i++) {
7323
7324                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7325
7326                 u1.size = 0;
7327                 u1.client = NULL;
7328                 u1.user = NULL;
7329                 u1.build = 0;
7330                 u1.major = 3;
7331                 u1.minor = 0;
7332                 u1.processor = architectures[i];
7333
7334                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7335                 r.in.datatype           = NULL;
7336                 r.in.devmode_ctr.devmode= NULL;
7337                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
7338                 r.in.level               = 1;
7339                 r.in.userlevel.level1   = &u1;
7340                 r.out.handle            = &handle;
7341
7342                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7343                 torture_assert_werr_ok(tctx, r.out.result, "");
7344
7345                 {
7346                         struct spoolss_EnumPrinters e;
7347                         uint32_t count;
7348                         union spoolss_PrinterInfo *info;
7349
7350                         e.in.flags = PRINTER_ENUM_LOCAL;
7351                         e.in.server = NULL;
7352                         e.in.level = 2;
7353                         e.in.buffer = NULL;
7354                         e.in.offered = 0;
7355                         e.out.count = &count;
7356                         e.out.info = &info;
7357                         e.out.needed = &needed[i];
7358
7359                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7360 #if 0
7361                         torture_comment(tctx, "needed was %d\n", needed[i]);
7362 #endif
7363                 }
7364
7365                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7366         }
7367
7368         for (i=1; i < ARRAY_SIZE(architectures); i++) {
7369                 if (needed[i-1] != needed[i]) {
7370                         torture_fail(tctx,
7371                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7372                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7373                 }
7374         }
7375
7376         return true;
7377 }
7378
7379 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7380                                           void *private_data)
7381 {
7382         struct test_spoolss_context *ctx =
7383                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7384         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7385         struct dcerpc_binding_handle *b = p->binding_handle;
7386
7387         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7388 }
7389
7390 static bool test_PrintServer_Forms(struct torture_context *tctx,
7391                                    void *private_data)
7392 {
7393         struct test_spoolss_context *ctx =
7394                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7395         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7396         struct dcerpc_binding_handle *b = p->binding_handle;
7397
7398         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7399 }
7400
7401 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7402                                        void *private_data)
7403 {
7404         struct test_spoolss_context *ctx =
7405                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7406         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7407         struct dcerpc_binding_handle *b = p->binding_handle;
7408
7409         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7410 }
7411
7412 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7413 {
7414         NTSTATUS status;
7415
7416         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7417
7418         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7419
7420         torture_assert(tctx,
7421                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7422                 "failed to open printserver");
7423         torture_assert(tctx,
7424                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7425                 "failed to get environment");
7426
7427         return true;
7428 }
7429
7430 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7431 {
7432         struct test_spoolss_context *t;
7433
7434         *data = t = talloc_zero(tctx, struct test_spoolss_context);
7435
7436         return torture_rpc_spoolss_setup_common(tctx, t);
7437 }
7438
7439 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7440 {
7441         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7442
7443         return true;
7444 }
7445
7446 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7447 {
7448         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7449         bool ret;
7450
7451         ret = torture_rpc_spoolss_teardown_common(tctx, t);
7452         talloc_free(t);
7453
7454         return ret;
7455 }
7456
7457 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7458 {
7459         struct dcerpc_pipe *p;
7460         struct dcerpc_binding_handle *b;
7461         const char *server_name_slash;
7462         const char *driver_name;
7463         const char *printer_name;
7464         const char *port_name;
7465
7466         torture_assert_ntstatus_ok(tctx,
7467                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7468                 "Error connecting to server");
7469
7470         p = t->spoolss_pipe;
7471         b = p->binding_handle;
7472         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7473
7474         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
7475         t->driver.info8.driver_name             = TORTURE_DRIVER;
7476         t->driver.info8.driver_path             = "pscript5.dll";
7477         t->driver.info8.data_file               = "cups6.ppd";
7478         t->driver.info8.config_file             = "ps5ui.dll";
7479         t->driver.info8.help_file               = "pscript.hlp";
7480         t->driver.info8.default_datatype        = "RAW";
7481         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
7482         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7483         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7484         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7485         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7486         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7487         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7488         t->driver.info8.dependent_files->string[5] = "cups6.ini";
7489         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7490         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7491
7492         t->driver.local.driver_directory= "/usr/share/cups/drivers";
7493
7494         t->info2.drivername             = "Microsoft XPS Document Writer";
7495         t->info2.portname               = "LPT1:";
7496
7497         printer_name = t->info2.printername;
7498         port_name = t->info2.portname;
7499
7500         torture_assert(tctx,
7501                 fillup_printserver_info(tctx, p, &t->driver),
7502                 "failed to fillup printserver info");
7503
7504         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7505
7506         torture_assert(tctx,
7507                 compose_local_driver_directory(tctx, t->driver.remote.environment,
7508                                                t->driver.local.driver_directory,
7509                                                &t->driver.local.driver_directory),
7510                 "failed to compose local driver directory");
7511
7512         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7513                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7514                         t->info2.drivername, t->driver.remote.environment);
7515                 t->have_driver = true;
7516                 goto try_add;
7517         }
7518
7519         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7520                 t->info2.drivername, t->driver.remote.environment);
7521         torture_comment(tctx, "trying to upload own driver\n");
7522
7523         if (!directory_exist(t->driver.local.driver_directory)) {
7524                 torture_warning(tctx, "no local driver is available!");
7525                 t->have_driver = false;
7526                 goto try_add;
7527         }
7528
7529         torture_assert(tctx,
7530                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7531                 "failed to upload printer driver");
7532
7533         torture_assert(tctx,
7534                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7535                 "failed to add driver");
7536
7537         t->added_driver = true;
7538         t->have_driver = true;
7539
7540  try_add:
7541         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7542
7543         if (t->wellknown) {
7544                 torture_assert(tctx,
7545                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7546                         "failed to add wellknown printer");
7547         } else {
7548                 torture_assert(tctx,
7549                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7550                         "failed to add printer");
7551         }
7552
7553         return true;
7554 }
7555
7556 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7557 {
7558         struct torture_printer_context *t;
7559
7560         *data = t = talloc_zero(tctx, struct torture_printer_context);
7561
7562         t->ex                   = false;
7563         t->wellknown            = false;
7564         t->info2.printername    = TORTURE_PRINTER;
7565         t->devmode              = NULL;
7566
7567         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7568 }
7569
7570 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7571 {
7572         struct torture_printer_context *t;
7573
7574         *data = t = talloc_zero(tctx, struct torture_printer_context);
7575
7576         t->ex                   = true;
7577         t->wellknown            = false;
7578         t->info2.printername    = TORTURE_PRINTER_EX;
7579         t->devmode              = NULL;
7580
7581         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7582 }
7583
7584 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7585 {
7586         struct torture_printer_context *t;
7587
7588         *data = t = talloc_zero(tctx, struct torture_printer_context);
7589
7590         t->ex                   = false;
7591         t->wellknown            = true;
7592         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
7593         t->devmode              = NULL;
7594
7595         /* FIXME */
7596         if (t->wellknown) {
7597                 torture_skip(tctx, "skipping AddPrinter level 1");
7598         }
7599
7600         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7601 }
7602
7603 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7604 {
7605         struct torture_printer_context *t;
7606
7607         *data = t = talloc_zero(tctx, struct torture_printer_context);
7608
7609         t->ex                   = true;
7610         t->wellknown            = true;
7611         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7612         t->devmode              = NULL;
7613
7614         /* FIXME */
7615         if (t->wellknown) {
7616                 torture_skip(tctx, "skipping AddPrinterEx level 1");
7617         }
7618
7619         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7620 }
7621
7622 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7623 {
7624         struct torture_printer_context *t;
7625
7626         *data = t = talloc_zero(tctx, struct torture_printer_context);
7627
7628         t->ex                   = true;
7629         t->wellknown            = false;
7630         t->info2.printername    = TORTURE_PRINTER_EX;
7631         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7632
7633         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7634 }
7635
7636 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7637 {
7638         bool found = false;
7639         struct dcerpc_pipe *p = t->spoolss_pipe;
7640         struct dcerpc_binding_handle *b;
7641         const char *printer_name = t->info2.printername;
7642
7643         if (t->added_driver) {
7644                 torture_assert(tctx,
7645                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7646                         "failed to remove printer driver");
7647         }
7648
7649         if (p && !t->wellknown) {
7650                 b = p->binding_handle;
7651
7652                 torture_assert(tctx,
7653                         test_DeletePrinter(tctx, b, &t->handle),
7654                         "failed to delete printer");
7655
7656                 torture_assert(tctx,
7657                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7658                                                    printer_name, &found),
7659                         "failed to enumerate printers");
7660
7661                 torture_assert(tctx, !found, "deleted printer still there");
7662         }
7663
7664         return true;
7665 }
7666
7667 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7668 {
7669         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7670         bool ret;
7671
7672         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7673         talloc_free(t);
7674
7675         return ret;
7676 }
7677
7678 static bool test_print_test(struct torture_context *tctx,
7679                             void *private_data)
7680 {
7681         struct torture_printer_context *t =
7682                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7683         struct dcerpc_pipe *p = t->spoolss_pipe;
7684         struct dcerpc_binding_handle *b = p->binding_handle;
7685
7686         torture_assert(tctx,
7687                 test_PausePrinter(tctx, b, &t->handle),
7688                 "failed to pause printer");
7689
7690         torture_assert(tctx,
7691                 test_DoPrintTest(tctx, b, &t->handle),
7692                 "failed to do print test");
7693
7694         torture_assert(tctx,
7695                 test_ResumePrinter(tctx, b, &t->handle),
7696                 "failed to resume printer");
7697
7698         return true;
7699 }
7700
7701 static bool test_print_test_extended(struct torture_context *tctx,
7702                                      void *private_data)
7703 {
7704         struct torture_printer_context *t =
7705                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7706         struct dcerpc_pipe *p = t->spoolss_pipe;
7707         struct dcerpc_binding_handle *b = p->binding_handle;
7708         bool ret = true;
7709
7710         torture_assert(tctx,
7711                 test_PausePrinter(tctx, b, &t->handle),
7712                 "failed to pause printer");
7713
7714         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7715         if (ret == false) {
7716                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7717                 if (torture_setting_bool(tctx, "samba3", false)) {
7718                         torture_comment(tctx, "non-critical for samba3\n");
7719                         ret = true;
7720                         tctx->last_result = TORTURE_SKIP;
7721                 }
7722         }
7723
7724         torture_assert(tctx,
7725                 test_ResumePrinter(tctx, b, &t->handle),
7726                 "failed to resume printer");
7727
7728         return ret;
7729 }
7730
7731 /* use smbd file IO to spool a print job */
7732 static bool test_print_test_smbd(struct torture_context *tctx,
7733                                  void *private_data)
7734 {
7735         struct torture_printer_context *t =
7736                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7737         struct dcerpc_pipe *p = t->spoolss_pipe;
7738         struct dcerpc_binding_handle *b = p->binding_handle;
7739         NTSTATUS status;
7740         uint32_t count;
7741         union spoolss_JobInfo *info = NULL;
7742         int i;
7743
7744         struct smb2_tree *tree;
7745         struct smb2_handle job_h;
7746         struct cli_credentials *credentials = cmdline_credentials;
7747         struct smbcli_options options;
7748         TALLOC_CTX *mem_ctx = talloc_new(tctx);
7749         /*
7750          * Do not test against the dynamically added printers, printing via
7751          * smbd means that a different spoolss process may handle the
7752          * OpenPrinter request to the one that handled the AddPrinter request.
7753          * This currently leads to an ugly race condition where one process
7754          * sees the new printer and one doesn't.
7755          */
7756         const char *share = TORTURE_PRINTER_STATIC1;
7757
7758         torture_comment(tctx, "Testing smbd job spooling\n");
7759         lpcfg_smbcli_options(tctx->lp_ctx, &options);
7760
7761         status = smb2_connect_ext(mem_ctx,
7762                                   torture_setting_string(tctx, "host", NULL),
7763                                   lpcfg_smb_ports(tctx->lp_ctx),
7764                                   share,
7765                                   lpcfg_resolve_context(tctx->lp_ctx),
7766                                   credentials,
7767                                   0,
7768                                   &tree,
7769                                   tctx->ev,
7770                                   &options,
7771                                   lpcfg_socket_options(tctx->lp_ctx),
7772                                   lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7773         if (!NT_STATUS_IS_OK(status)) {
7774                 printf("Failed to connect to SMB2 printer %s - %s\n",
7775                        share, nt_errstr(status));
7776                 return false;
7777         }
7778
7779         status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7780         torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7781
7782         status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7783                                  sizeof("exciting print job data"));
7784         torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7785
7786         /* check back end spoolss job was created */
7787         torture_assert(tctx,
7788                 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7789                 "EnumJobs level 1 failed");
7790
7791         for (i = 0; i < count; i++) {
7792                 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7793                         break;
7794                 }
7795         }
7796         torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7797
7798         status = smb2_util_close(tree, job_h);
7799         torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7800
7801         /* disconnect from printer share */
7802         talloc_free(mem_ctx);
7803
7804         return true;
7805 }
7806
7807 static bool test_printer_sd(struct torture_context *tctx,
7808                             void *private_data)
7809 {
7810         struct torture_printer_context *t =
7811                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7812         struct dcerpc_pipe *p = t->spoolss_pipe;
7813         struct dcerpc_binding_handle *b = p->binding_handle;
7814
7815         torture_assert(tctx,
7816                 test_PrinterInfo_SD(tctx, b, &t->handle),
7817                 "failed to test security descriptors");
7818
7819         return true;
7820 }
7821
7822 static bool test_printer_dm(struct torture_context *tctx,
7823                             void *private_data)
7824 {
7825         struct torture_printer_context *t =
7826                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7827         struct dcerpc_pipe *p = t->spoolss_pipe;
7828
7829         torture_assert(tctx,
7830                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7831                 "failed to test devicemodes");
7832
7833         return true;
7834 }
7835
7836 static bool test_printer_info_winreg(struct torture_context *tctx,
7837                                      void *private_data)
7838 {
7839         struct torture_printer_context *t =
7840                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7841         struct dcerpc_pipe *p = t->spoolss_pipe;
7842
7843         torture_assert(tctx,
7844                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7845                 "failed to test printer info winreg");
7846
7847         return true;
7848 }
7849
7850 static bool test_printer_change_id(struct torture_context *tctx,
7851                                    void *private_data)
7852 {
7853         struct torture_printer_context *t =
7854                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7855         struct dcerpc_pipe *p = t->spoolss_pipe;
7856
7857         torture_assert(tctx,
7858                 test_ChangeID(tctx, p, &t->handle),
7859                 "failed to test change id");
7860
7861         return true;
7862 }
7863
7864 static bool test_printer_keys(struct torture_context *tctx,
7865                               void *private_data)
7866 {
7867         struct torture_printer_context *t =
7868                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7869         struct dcerpc_pipe *p = t->spoolss_pipe;
7870         struct dcerpc_binding_handle *b = p->binding_handle;
7871
7872         torture_assert(tctx,
7873                 test_printer_all_keys(tctx, b, &t->handle),
7874                 "failed to test printer keys");
7875
7876         return true;
7877 }
7878
7879 static bool test_printer_data_consistency(struct torture_context *tctx,
7880                                           void *private_data)
7881 {
7882         struct torture_printer_context *t =
7883                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7884         struct dcerpc_pipe *p = t->spoolss_pipe;
7885
7886         torture_assert(tctx,
7887                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7888                 "failed to test printer data consistency");
7889
7890         return true;
7891 }
7892
7893 static bool test_printer_data_keys(struct torture_context *tctx,
7894                                    void *private_data)
7895 {
7896         struct torture_printer_context *t =
7897                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7898         struct dcerpc_pipe *p = t->spoolss_pipe;
7899
7900         torture_assert(tctx,
7901                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7902                 "failed to test printer data keys");
7903
7904         return true;
7905 }
7906
7907 static bool test_printer_data_values(struct torture_context *tctx,
7908                                      void *private_data)
7909 {
7910         struct torture_printer_context *t =
7911                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7912         struct dcerpc_pipe *p = t->spoolss_pipe;
7913
7914         torture_assert(tctx,
7915                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7916                 "failed to test printer data values");
7917
7918         return true;
7919 }
7920
7921 static bool test_printer_data_set(struct torture_context *tctx,
7922                                   void *private_data)
7923 {
7924         struct torture_printer_context *t =
7925                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7926         struct dcerpc_pipe *p = t->spoolss_pipe;
7927
7928         torture_assert(tctx,
7929                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7930                 "failed to test printer data set");
7931
7932         return true;
7933 }
7934
7935 static bool test_printer_data_winreg(struct torture_context *tctx,
7936                                      void *private_data)
7937 {
7938         struct torture_printer_context *t =
7939                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7940         struct dcerpc_pipe *p = t->spoolss_pipe;
7941
7942         torture_assert(tctx,
7943                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7944                 "failed to test printer data winreg");
7945
7946         return true;
7947 }
7948
7949 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7950                                         void *private_data)
7951 {
7952         struct torture_printer_context *t =
7953                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7954         struct dcerpc_pipe *p = t->spoolss_pipe;
7955
7956         torture_assert(tctx,
7957                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7958                 "failed to test printer data winreg dsspooler");
7959
7960         return true;
7961 }
7962
7963 static bool test_driver_info_winreg(struct torture_context *tctx,
7964                                     void *private_data)
7965 {
7966         struct torture_printer_context *t =
7967                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7968         struct dcerpc_pipe *p = t->spoolss_pipe;
7969         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7970
7971         if (!t->have_driver) {
7972                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7973         }
7974
7975         torture_assert(tctx,
7976                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7977                 "failed to test driver info winreg");
7978
7979         return true;
7980 }
7981
7982 void torture_tcase_printer(struct torture_tcase *tcase)
7983 {
7984         torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7985         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7986         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7987         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7988         torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7989         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7990         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7991         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7992         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7993         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7994         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7995         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7996         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7997         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7998         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7999         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8000         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8001         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8002         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8003 }
8004
8005 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8006 {
8007         struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8008         struct torture_tcase *tcase;
8009
8010         tcase = torture_suite_add_tcase(suite, "addprinter");
8011
8012         torture_tcase_set_fixture(tcase,
8013                                   torture_rpc_spoolss_printer_setup,
8014                                   torture_rpc_spoolss_printer_teardown);
8015
8016         torture_tcase_printer(tcase);
8017
8018         tcase = torture_suite_add_tcase(suite, "addprinterex");
8019
8020         torture_tcase_set_fixture(tcase,
8021                                   torture_rpc_spoolss_printerex_setup,
8022                                   torture_rpc_spoolss_printer_teardown);
8023
8024         torture_tcase_printer(tcase);
8025
8026         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8027
8028         torture_tcase_set_fixture(tcase,
8029                                   torture_rpc_spoolss_printerwkn_setup,
8030                                   torture_rpc_spoolss_printer_teardown);
8031
8032         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8033
8034         torture_tcase_set_fixture(tcase,
8035                                   torture_rpc_spoolss_printerexwkn_setup,
8036                                   torture_rpc_spoolss_printer_teardown);
8037
8038 #if 0
8039         /* test is not correct */
8040         tcase = torture_suite_add_tcase(suite, "addprinterdm");
8041
8042         torture_tcase_set_fixture(tcase,
8043                                   torture_rpc_spoolss_printerdm_setup,
8044                                   torture_rpc_spoolss_printer_teardown);
8045
8046         torture_tcase_printer(tcase);
8047 #endif
8048         return suite;
8049 }
8050
8051 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8052 {
8053         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8054         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8055
8056         torture_tcase_set_fixture(tcase,
8057                                   torture_rpc_spoolss_setup,
8058                                   torture_rpc_spoolss_teardown);
8059
8060         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8061         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8062         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8063         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8064         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8065         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8066         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8067         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8068         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8069         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8070         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8071         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8072         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8073         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8074         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8075         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8076         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8077         torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8078         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8079         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8080
8081         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8082
8083         return suite;
8084 }
8085
8086 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8087                                                   struct dcerpc_binding_handle *b,
8088                                                   const char *server,
8089                                                   const char *environment,
8090                                                   const char **dir_p)
8091 {
8092         struct spoolss_GetPrinterDriverDirectory r;
8093         uint32_t needed;
8094
8095         r.in.server             = server;
8096         r.in.environment        = environment;
8097         r.in.level              = 1;
8098         r.in.buffer             = NULL;
8099         r.in.offered            = 0;
8100         r.out.needed            = &needed;
8101
8102         torture_assert_ntstatus_ok(tctx,
8103                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8104                 "failed to query driver directory");
8105
8106         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8107                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8108                 r.in.buffer = &blob;
8109                 r.in.offered = needed;
8110
8111                 torture_assert_ntstatus_ok(tctx,
8112                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8113                         "failed to query driver directory");
8114         }
8115
8116         torture_assert_werr_ok(tctx, r.out.result,
8117                 "failed to query driver directory");
8118
8119         if (dir_p) {
8120                 *dir_p = r.out.info->info1.directory_name;
8121         }
8122
8123         return true;
8124 }
8125
8126 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8127 {
8128         if (info_ctr == NULL) {
8129                 return NULL;
8130         }
8131
8132         switch (info_ctr->level) {
8133         case 1:
8134                 return info_ctr->info.info1->driver_name;
8135         case 2:
8136                 return info_ctr->info.info2->driver_name;
8137         case 3:
8138                 return info_ctr->info.info3->driver_name;
8139         case 4:
8140                 return info_ctr->info.info4->driver_name;
8141         case 6:
8142                 return info_ctr->info.info6->driver_name;
8143         case 8:
8144                 return info_ctr->info.info8->driver_name;
8145         default:
8146                 return NULL;
8147         }
8148 }
8149
8150 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8151 {
8152         if (info_ctr == NULL) {
8153                 return NULL;
8154         }
8155
8156         switch (info_ctr->level) {
8157         case 2:
8158                 return info_ctr->info.info2->architecture;
8159         case 3:
8160                 return info_ctr->info.info3->architecture;
8161         case 4:
8162                 return info_ctr->info.info4->architecture;
8163         case 6:
8164                 return info_ctr->info.info6->architecture;
8165         case 8:
8166                 return info_ctr->info.info8->architecture;
8167         default:
8168                 return NULL;
8169         }
8170 }
8171
8172
8173 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8174                                       struct dcerpc_binding_handle *b,
8175                                       const char *servername,
8176                                       struct spoolss_AddDriverInfoCtr *info_ctr,
8177                                       WERROR expected_result)
8178 {
8179         struct spoolss_AddPrinterDriver r;
8180         const char *drivername = get_driver_from_info(info_ctr);
8181         const char *environment = get_environment_from_info(info_ctr);
8182
8183         r.in.servername = servername;
8184         r.in.info_ctr = info_ctr;
8185
8186         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8187                 drivername, info_ctr->level, environment);
8188
8189         torture_assert_ntstatus_ok(tctx,
8190                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8191                 "spoolss_AddPrinterDriver failed");
8192         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8193                 "spoolss_AddPrinterDriver failed with unexpected result");
8194
8195         return true;
8196
8197 }
8198
8199 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8200                                         struct dcerpc_binding_handle *b,
8201                                         const char *servername,
8202                                         struct spoolss_AddDriverInfoCtr *info_ctr,
8203                                         uint32_t flags,
8204                                         WERROR expected_result)
8205 {
8206         struct spoolss_AddPrinterDriverEx r;
8207         const char *drivername = get_driver_from_info(info_ctr);
8208         const char *environment = get_environment_from_info(info_ctr);
8209
8210         r.in.servername = servername;
8211         r.in.info_ctr = info_ctr;
8212         r.in.flags = flags;
8213
8214         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8215                 drivername, info_ctr->level, environment);
8216
8217         torture_assert_ntstatus_ok(tctx,
8218                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8219                 "AddPrinterDriverEx failed");
8220         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8221                 "AddPrinterDriverEx failed with unexpected result");
8222
8223         return true;
8224 }
8225
8226 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8227         if (path && strlen(path)) {\
8228                 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8229         }
8230
8231 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8232                                                struct dcerpc_binding_handle *b,
8233                                                const char *server_name,
8234                                                struct spoolss_AddDriverInfo8 *r,
8235                                                uint32_t flags,
8236                                                bool ex,
8237                                                const char *remote_driver_dir)
8238 {
8239         struct spoolss_AddDriverInfoCtr info_ctr;
8240         struct spoolss_AddDriverInfo1 info1;
8241
8242         ZERO_STRUCT(info1);
8243
8244         info_ctr.level = 1;
8245         info_ctr.info.info1 = &info1;
8246
8247         if (ex) {
8248                 torture_assert(tctx,
8249                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8250                         "failed to test AddPrinterDriverEx level 1");
8251         } else {
8252                 torture_assert(tctx,
8253                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8254                         "failed to test AddPrinterDriver level 1");
8255         }
8256
8257         info1.driver_name = r->driver_name;
8258
8259         if (ex) {
8260                 torture_assert(tctx,
8261                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8262                         "failed to test AddPrinterDriverEx level 1");
8263         } else {
8264                 torture_assert(tctx,
8265                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8266                         "failed to test AddPrinterDriver level 1");
8267         }
8268
8269         return true;
8270 }
8271
8272 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8273                                                struct dcerpc_binding_handle *b,
8274                                                const char *server_name,
8275                                                struct spoolss_AddDriverInfo8 *r,
8276                                                uint32_t flags,
8277                                                bool ex,
8278                                                const char *remote_driver_dir)
8279 {
8280         struct spoolss_AddDriverInfoCtr info_ctr;
8281         struct spoolss_AddDriverInfo2 info2;
8282         union spoolss_DriverInfo info;
8283
8284         ZERO_STRUCT(info2);
8285
8286         info_ctr.level = 2;
8287         info_ctr.info.info2 = &info2;
8288
8289         if (ex) {
8290                 torture_assert(tctx,
8291                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8292                         "failed to test AddPrinterDriverEx level 2");
8293         } else {
8294                 torture_assert(tctx,
8295                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8296                         "failed to test AddPrinterDriver level 2");
8297         }
8298
8299         info2.driver_name = r->driver_name;
8300
8301         if (ex) {
8302                 torture_assert(tctx,
8303                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8304                         "failed to test AddPrinterDriverEx level 2");
8305         } else {
8306                 torture_assert(tctx,
8307                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8308                         "failed to test AddPrinterDriver level 2");
8309         }
8310
8311         info2.version = r->version;
8312
8313         if (ex) {
8314                 torture_assert(tctx,
8315                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8316                         "failed to test AddPrinterDriverEx level 2");
8317         } else {
8318                 torture_assert(tctx,
8319                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8320                         "failed to test AddPrinterDriver level 2");
8321         }
8322
8323         info2.architecture = r->architecture;
8324
8325         if (ex) {
8326                 torture_assert(tctx,
8327                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8328                         "failed to test AddPrinterDriverEx level 2");
8329         } else {
8330                 torture_assert(tctx,
8331                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8332                         "failed to test AddPrinterDriver level 2");
8333         }
8334
8335         info2.driver_path = r->driver_path;
8336
8337         if (ex) {
8338                 torture_assert(tctx,
8339                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8340                         "failed to test AddPrinterDriverEx level 2");
8341         } else {
8342                 torture_assert(tctx,
8343                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8344                         "failed to test AddPrinterDriver level 2");
8345         }
8346
8347         info2.data_file = r->data_file;
8348
8349         if (ex) {
8350                 torture_assert(tctx,
8351                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8352                         "failed to test AddPrinterDriverEx level 2");
8353         } else {
8354                 torture_assert(tctx,
8355                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8356                         "failed to test AddPrinterDriver level 2");
8357         }
8358
8359         info2.config_file = r->config_file;
8360
8361         if (ex) {
8362                 torture_assert(tctx,
8363                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8364                         "failed to test AddPrinterDriverEx");
8365         }
8366
8367         if (ex) {
8368                 torture_assert(tctx,
8369                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8370                         "failed to test AddPrinterDriverEx level 2");
8371         } else {
8372                 torture_assert(tctx,
8373                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8374                         "failed to test AddPrinterDriver level 2");
8375         }
8376
8377         torture_assert(tctx,
8378                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8379                 "failed to find added printer driver");
8380
8381         if (remote_driver_dir) {
8382                 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8383                 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8384                 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8385         }
8386
8387         return true;
8388 }
8389
8390 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8391                                                struct dcerpc_binding_handle *b,
8392                                                const char *server_name,
8393                                                struct spoolss_AddDriverInfo8 *r,
8394                                                uint32_t flags,
8395                                                bool ex,
8396                                                const char *remote_driver_dir)
8397 {
8398         struct spoolss_AddDriverInfoCtr info_ctr;
8399         struct spoolss_AddDriverInfo3 info3;
8400         union spoolss_DriverInfo info;
8401
8402         info3.driver_name       = r->driver_name;
8403         info3.version           = r->version;
8404         info3.architecture      = r->architecture;
8405         info3.driver_path       = r->driver_path;
8406         info3.data_file         = r->data_file;
8407         info3.config_file       = r->config_file;
8408         info3.help_file         = r->help_file;
8409         info3.monitor_name      = r->monitor_name;
8410         info3.default_datatype  = r->default_datatype;
8411         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8412         info3.dependent_files   = r->dependent_files;
8413
8414         info_ctr.level = 3;
8415         info_ctr.info.info3 = &info3;
8416
8417         if (ex) {
8418                 torture_assert(tctx,
8419                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8420                         "failed to test AddPrinterDriverEx level 3");
8421         } else {
8422                 torture_assert(tctx,
8423                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8424                         "failed to test AddPrinterDriver level 3");
8425         }
8426
8427         torture_assert(tctx,
8428                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8429                 "failed to find added printer driver");
8430
8431         if (remote_driver_dir) {
8432                 int i;
8433                 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8434                 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8435                 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8436                 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8437                 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8438                         ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8439                 }
8440         }
8441
8442         return true;
8443 }
8444
8445 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8446                                                struct dcerpc_binding_handle *b,
8447                                                const char *server_name,
8448                                                struct spoolss_AddDriverInfo8 *r,
8449                                                uint32_t flags,
8450                                                bool ex,
8451                                                const char *remote_driver_dir)
8452 {
8453         struct spoolss_AddDriverInfoCtr info_ctr;
8454         struct spoolss_AddDriverInfo4 info4;
8455         union spoolss_DriverInfo info;
8456
8457         info4.version           = r->version;
8458         info4.driver_name       = r->driver_name;
8459         info4.architecture      = r->architecture;
8460         info4.driver_path       = r->driver_path;
8461         info4.data_file         = r->data_file;
8462         info4.config_file       = r->config_file;
8463         info4.help_file         = r->help_file;
8464         info4.monitor_name      = r->monitor_name;
8465         info4.default_datatype  = r->default_datatype;
8466         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8467         info4.dependent_files   = r->dependent_files;
8468         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8469         info4.previous_names = r->previous_names;
8470
8471         info_ctr.level = 4;
8472         info_ctr.info.info4 = &info4;
8473
8474         if (ex) {
8475                 torture_assert(tctx,
8476                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8477                         "failed to test AddPrinterDriverEx level 4");
8478         } else {
8479                 torture_assert(tctx,
8480                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8481                         "failed to test AddPrinterDriver level 4");
8482         }
8483
8484         torture_assert(tctx,
8485                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8486                 "failed to find added printer driver");
8487
8488         if (remote_driver_dir) {
8489                 int i;
8490                 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8491                 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8492                 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8493                 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8494                 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8495                         ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8496                 }
8497         }
8498
8499         return true;
8500 }
8501
8502 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8503                                                struct dcerpc_binding_handle *b,
8504                                                const char *server_name,
8505                                                struct spoolss_AddDriverInfo8 *r,
8506                                                uint32_t flags,
8507                                                bool ex,
8508                                                const char *remote_driver_dir)
8509 {
8510         struct spoolss_AddDriverInfoCtr info_ctr;
8511         struct spoolss_AddDriverInfo6 info6;
8512         union spoolss_DriverInfo info;
8513
8514         info6.version           = r->version;
8515         info6.driver_name       = r->driver_name;
8516         info6.architecture      = r->architecture;
8517         info6.driver_path       = r->driver_path;
8518         info6.data_file         = r->data_file;
8519         info6.config_file       = r->config_file;
8520         info6.help_file         = r->help_file;
8521         info6.monitor_name      = r->monitor_name;
8522         info6.default_datatype  = r->default_datatype;
8523         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8524         info6.dependent_files   = r->dependent_files;
8525         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8526         info6.previous_names    = r->previous_names;
8527         info6.driver_date       = r->driver_date;
8528         info6.driver_version    = r->driver_version;
8529         info6.manufacturer_name = r->manufacturer_name;
8530         info6.manufacturer_url  = r->manufacturer_url;
8531         info6.hardware_id       = r->hardware_id;
8532         info6.provider          = r->provider;
8533
8534         info_ctr.level = 6;
8535         info_ctr.info.info6 = &info6;
8536
8537         if (ex) {
8538                 torture_assert(tctx,
8539                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8540                         "failed to test AddPrinterDriverEx level 6");
8541         } else {
8542                 torture_assert(tctx,
8543                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8544                         "failed to test AddPrinterDriver level 6");
8545         }
8546
8547         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8548
8549         if (!ex) {
8550                 return true;
8551         }
8552
8553         torture_assert(tctx,
8554                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8555                 "failed to find added printer driver");
8556
8557         if (remote_driver_dir) {
8558                 int i;
8559                 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8560                 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8561                 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8562                 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8563                 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8564                         ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8565                 }
8566         }
8567
8568         torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8569         torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8570
8571         return true;
8572 }
8573
8574 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8575                                                struct dcerpc_binding_handle *b,
8576                                                const char *server_name,
8577                                                struct spoolss_AddDriverInfo8 *r,
8578                                                uint32_t flags,
8579                                                bool ex,
8580                                                const char *remote_driver_dir)
8581 {
8582         struct spoolss_AddDriverInfoCtr info_ctr;
8583         union spoolss_DriverInfo info;
8584
8585         info_ctr.level = 8;
8586         info_ctr.info.info8 = r;
8587
8588         if (ex) {
8589                 torture_assert(tctx,
8590                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8591                         "failed to test AddPrinterDriverEx level 8");
8592         } else {
8593                 torture_assert(tctx,
8594                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8595                         "failed to test AddPrinterDriver level 8");
8596         }
8597
8598         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8599
8600         if (!ex) {
8601                 return true;
8602         }
8603
8604         torture_assert(tctx,
8605                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8606                 "failed to find added printer driver");
8607
8608         if (remote_driver_dir) {
8609                 int i;
8610                 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8611                 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8612                 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8613                 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8614                 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8615                         ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8616                 }
8617         }
8618
8619         torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8620         torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8621
8622         return true;
8623 }
8624
8625 #undef ASSERT_DRIVER_PATH
8626
8627 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8628                                          struct dcerpc_binding_handle *b,
8629                                          const char *server,
8630                                          const char *driver,
8631                                          const char *environment,
8632                                          WERROR expected_result)
8633 {
8634         struct spoolss_DeletePrinterDriver r;
8635
8636         r.in.server = server;
8637         r.in.architecture = environment;
8638         r.in.driver = driver;
8639
8640         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8641
8642         torture_assert_ntstatus_ok(tctx,
8643                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8644                 "DeletePrinterDriver failed");
8645         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8646                 "DeletePrinterDriver failed with unexpected result");
8647
8648         return true;
8649 }
8650
8651 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8652                                            struct dcerpc_binding_handle *b,
8653                                            const char *server,
8654                                            const char *driver,
8655                                            const char *environment,
8656                                            uint32_t delete_flags,
8657                                            uint32_t version,
8658                                            WERROR expected_result)
8659 {
8660         struct spoolss_DeletePrinterDriverEx r;
8661
8662         r.in.server = server;
8663         r.in.architecture = environment;
8664         r.in.driver = driver;
8665         r.in.delete_flags = delete_flags;
8666         r.in.version = version;
8667
8668         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8669
8670         torture_assert_ntstatus_ok(tctx,
8671                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8672                 "DeletePrinterDriverEx failed");
8673         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8674                 "DeletePrinterDriverEx failed with unexpected result");
8675
8676         return true;
8677 }
8678
8679 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8680                                      struct dcerpc_binding_handle *b,
8681                                      const char *server_name,
8682                                      const char *driver,
8683                                      const char *environment)
8684 {
8685         torture_assert(tctx,
8686                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8687                 "failed to delete driver");
8688
8689         torture_assert(tctx,
8690                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8691                 "failed to delete driver");
8692
8693         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8694                 torture_fail(tctx, "deleted driver still enumerated");
8695         }
8696
8697         torture_assert(tctx,
8698                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8699                 "2nd delete failed");
8700
8701         return true;
8702 }
8703
8704 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8705                                        struct dcerpc_binding_handle *b,
8706                                        const char *server_name,
8707                                        const char *driver,
8708                                        const char *environment,
8709                                        uint32_t delete_flags,
8710                                        uint32_t version)
8711 {
8712         torture_assert(tctx,
8713                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8714                 "failed to delete driver");
8715
8716         torture_assert(tctx,
8717                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8718                 "failed to delete driver");
8719
8720         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8721                 torture_fail(tctx, "deleted driver still enumerated");
8722         }
8723
8724         torture_assert(tctx,
8725                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8726                 "2nd delete failed");
8727
8728         return true;
8729 }
8730
8731 static bool test_PrinterDriver_args(struct torture_context *tctx,
8732                                     struct dcerpc_binding_handle *b,
8733                                     const char *server_name,
8734                                     uint32_t level,
8735                                     struct spoolss_AddDriverInfo8 *r,
8736                                     uint32_t add_flags,
8737                                     uint32_t delete_flags,
8738                                     uint32_t delete_version,
8739                                     bool ex,
8740                                     const char *remote_driver_dir)
8741 {
8742         bool ret = true;
8743
8744         switch (level) {
8745         case 1:
8746                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8747                 break;
8748         case 2:
8749                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8750                 break;
8751         case 3:
8752                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8753                 break;
8754         case 4:
8755                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8756                 break;
8757         case 6:
8758                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8759                 break;
8760         case 8:
8761                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8762                 break;
8763         default:
8764                 return false;
8765         }
8766
8767         if (ret == false) {
8768                 return ret;
8769         }
8770
8771         if (level == 1) {
8772                 return ret;
8773         }
8774
8775         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8776
8777         if (!ex && (level == 6 || level == 8)) {
8778                 return ret;
8779         }
8780
8781         {
8782                 struct dcerpc_pipe *p2;
8783                 struct policy_handle hive_handle;
8784                 struct dcerpc_binding_handle *b2;
8785
8786                 torture_assert_ntstatus_ok(tctx,
8787                         torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8788                         "could not open winreg pipe");
8789                 b2 = p2->binding_handle;
8790
8791                 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8792
8793                 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8794
8795                 test_winreg_CloseKey(tctx, b2, &hive_handle);
8796
8797                 talloc_free(p2);
8798         }
8799
8800         if (ex) {
8801                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8802         } else {
8803                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8804         }
8805 }
8806
8807 static bool fillup_printserver_info(struct torture_context *tctx,
8808                                     struct dcerpc_pipe *p,
8809                                     struct torture_driver_context *d)
8810 {
8811         struct policy_handle server_handle;
8812         struct dcerpc_binding_handle *b = p->binding_handle;
8813         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8814
8815         torture_assert(tctx,
8816                 test_OpenPrinter_server(tctx, p, &server_handle),
8817                 "failed to open printserver");
8818         torture_assert(tctx,
8819                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8820                 "failed to get environment");
8821         torture_assert(tctx,
8822                 test_ClosePrinter(tctx, b, &server_handle),
8823                 "failed to close printserver");
8824
8825         torture_assert(tctx,
8826                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8827                         d->local.environment ? d->local.environment : d->remote.environment,
8828                         &d->remote.driver_directory),
8829                 "failed to get driver directory");
8830
8831         return true;
8832 }
8833
8834 static const char *driver_directory_dir(const char *driver_directory)
8835 {
8836         char *p;
8837
8838         p = strrchr(driver_directory, '\\');
8839         if (p) {
8840                 return p+1;
8841         }
8842
8843         return NULL;
8844 }
8845
8846 static const char *driver_directory_share(struct torture_context *tctx,
8847                                           const char *driver_directory)
8848 {
8849         const char *p;
8850         char *tok;
8851
8852         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8853                 driver_directory += 2;
8854         }
8855
8856         p = talloc_strdup(tctx, driver_directory);
8857
8858         torture_assert(tctx,
8859                 next_token_talloc(tctx, &p, &tok, "\\"),
8860                 "cannot explode uri");
8861         torture_assert(tctx,
8862                 next_token_talloc(tctx, &p, &tok, "\\"),
8863                 "cannot explode uri");
8864
8865         return tok;
8866 }
8867
8868 static bool upload_printer_driver_file(struct torture_context *tctx,
8869                                        struct smbcli_state *cli,
8870                                        struct torture_driver_context *d,
8871                                        const char *file_name)
8872 {
8873         XFILE *f;
8874         int fnum;
8875         uint8_t *buf;
8876         int maxwrite = 64512;
8877         off_t nread = 0;
8878         size_t start = 0;
8879         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8880         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8881         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8882
8883         if (!file_name || strlen(file_name) == 0) {
8884                 return true;
8885         }
8886
8887         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8888
8889         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8890         if (fnum == -1) {
8891                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8892         }
8893
8894         f = x_fopen(local_name, O_RDONLY, 0);
8895         if (f == NULL) {
8896                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8897         }
8898
8899         buf = talloc_array(tctx, uint8_t, maxwrite);
8900         if (!buf) {
8901                 return false;
8902         }
8903
8904         while (!x_feof(f)) {
8905                 int n = maxwrite;
8906                 int ret;
8907
8908                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8909                         if((n == 0) && x_feof(f))
8910                                 break; /* Empty local file. */
8911
8912                         torture_warning(tctx,
8913                                 "failed to read file: %s\n", strerror(errno));
8914                         break;
8915                 }
8916
8917                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8918
8919                 if (n != ret) {
8920                         torture_warning(tctx,
8921                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8922                         break;
8923                 }
8924
8925                 nread += n;
8926         }
8927
8928         x_fclose(f);
8929
8930         torture_assert_ntstatus_ok(tctx,
8931                 smbcli_close(cli->tree, fnum),
8932                 "failed to close file");
8933
8934         return true;
8935 }
8936
8937 static bool connect_printer_driver_share(struct torture_context *tctx,
8938                                          const char *server_name,
8939                                          const char *share_name,
8940                                          struct smbcli_state **cli)
8941 {
8942         struct smbcli_options smb_options;
8943         struct smbcli_session_options smb_session_options;
8944
8945         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8946                 share_name, server_name);
8947
8948         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8949         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8950
8951         torture_assert_ntstatus_ok(tctx,
8952                 smbcli_full_connection(tctx, cli, server_name,
8953                                         lpcfg_smb_ports(tctx->lp_ctx),
8954                                         share_name, NULL,
8955                                         lpcfg_socket_options(tctx->lp_ctx),
8956                                         cmdline_credentials,
8957                                         lpcfg_resolve_context(tctx->lp_ctx),
8958                                         tctx->ev,
8959                                         &smb_options,
8960                                         &smb_session_options,
8961                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8962                 "failed to open driver share");
8963
8964         return true;
8965 }
8966
8967 static bool upload_printer_driver(struct torture_context *tctx,
8968                                   const char *server_name,
8969                                   struct torture_driver_context *d)
8970 {
8971         struct smbcli_state *cli;
8972         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8973         int i;
8974
8975         torture_assert(tctx,
8976                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8977                 "failed to connect to driver share");
8978
8979         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8980                 server_name, share_name);
8981
8982         torture_assert(tctx,
8983                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8984                 "failed to upload driver_path");
8985         torture_assert(tctx,
8986                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8987                 "failed to upload data_file");
8988         torture_assert(tctx,
8989                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8990                 "failed to upload config_file");
8991         torture_assert(tctx,
8992                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8993                 "failed to upload help_file");
8994         if (d->info8.dependent_files) {
8995                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8996                         torture_assert(tctx,
8997                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8998                                 "failed to upload dependent_files");
8999                 }
9000         }
9001
9002         talloc_free(cli);
9003
9004         return true;
9005 }
9006
9007 static bool check_printer_driver_file(struct torture_context *tctx,
9008                                       struct smbcli_state *cli,
9009                                       struct torture_driver_context *d,
9010                                       const char *file_name)
9011 {
9012         const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9013         const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9014                                                   remote_arch_dir,
9015                                                   d->info8.version,
9016                                                   file_name);
9017         int fnum;
9018
9019         torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9020
9021         torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9022
9023         fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9024         if (fnum == -1) {
9025                 return false;
9026         }
9027
9028         torture_assert_ntstatus_ok(tctx,
9029                 smbcli_close(cli->tree, fnum),
9030                 "failed to close driver file");
9031
9032         return true;
9033 }
9034
9035 static bool check_printer_driver_files(struct torture_context *tctx,
9036                                        const char *server_name,
9037                                        struct torture_driver_context *d,
9038                                        bool expect_exist)
9039 {
9040         struct smbcli_state *cli;
9041         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9042         int i;
9043
9044         torture_assert(tctx,
9045                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9046                 "failed to connect to driver share");
9047
9048         torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9049                         (expect_exist ? "": "non-"),
9050                         server_name, share_name);
9051
9052         if (d->info8.driver_path && d->info8.driver_path[0]) {
9053                 torture_assert(tctx,
9054                         check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9055                         "failed driver_path check");
9056         }
9057         if (d->info8.data_file && d->info8.data_file[0]) {
9058                 torture_assert(tctx,
9059                         check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9060                         "failed data_file check");
9061         }
9062         if (d->info8.config_file && d->info8.config_file[0]) {
9063                 torture_assert(tctx,
9064                         check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9065                         "failed config_file check");
9066         }
9067         if (d->info8.help_file && d->info8.help_file[0]) {
9068                 torture_assert(tctx,
9069                         check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9070                         "failed help_file check");
9071         }
9072         if (d->info8.dependent_files) {
9073                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9074                         torture_assert(tctx,
9075                                 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9076                                 "failed dependent_files check");
9077                 }
9078         }
9079
9080         talloc_free(cli);
9081
9082         return true;
9083 }
9084
9085 static bool remove_printer_driver_file(struct torture_context *tctx,
9086                                        struct smbcli_state *cli,
9087                                        struct torture_driver_context *d,
9088                                        const char *file_name)
9089 {
9090         const char *remote_name;
9091         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
9092
9093         if (!file_name || strlen(file_name) == 0) {
9094                 return true;
9095         }
9096
9097         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9098
9099         torture_comment(tctx, "Removing %s\n", remote_name);
9100
9101         torture_assert_ntstatus_ok(tctx,
9102                 smbcli_unlink(cli->tree, remote_name),
9103                 "failed to unlink");
9104
9105         return true;
9106 }
9107
9108 static bool remove_printer_driver(struct torture_context *tctx,
9109                                   const char *server_name,
9110                                   struct torture_driver_context *d)
9111 {
9112         struct smbcli_state *cli;
9113         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9114         int i;
9115
9116         torture_assert(tctx,
9117                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9118                 "failed to connect to driver share");
9119
9120         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9121                 server_name, share_name);
9122
9123         torture_assert(tctx,
9124                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9125                 "failed to remove driver_path");
9126         torture_assert(tctx,
9127                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9128                 "failed to remove data_file");
9129         if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9130                 torture_assert(tctx,
9131                         remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9132                         "failed to remove config_file");
9133         }
9134         torture_assert(tctx,
9135                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9136                 "failed to remove help_file");
9137         if (d->info8.dependent_files) {
9138                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9139                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9140                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9141                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9142                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9143                                 continue;
9144                         }
9145                         torture_assert(tctx,
9146                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9147                                 "failed to remove dependent_files");
9148                 }
9149         }
9150
9151         talloc_free(cli);
9152
9153         return true;
9154
9155 }
9156
9157 static bool test_add_driver_arg(struct torture_context *tctx,
9158                                 struct dcerpc_pipe *p,
9159                                 struct torture_driver_context *d)
9160 {
9161         bool ret = true;
9162         struct dcerpc_binding_handle *b = p->binding_handle;
9163         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9164         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9165         int i;
9166         struct spoolss_AddDriverInfo8 info8;
9167         uint32_t add_flags = APD_COPY_NEW_FILES;
9168         uint32_t delete_flags = 0;
9169
9170         ZERO_STRUCT(info8);
9171
9172         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9173                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9174
9175         torture_assert(tctx,
9176                 fillup_printserver_info(tctx, p, d),
9177                 "failed to fillup printserver info");
9178
9179         if (!directory_exist(d->local.driver_directory)) {
9180                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9181         }
9182
9183         torture_assert(tctx,
9184                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9185                 "failed to upload printer driver");
9186
9187         info8 = d->info8;
9188         if (d->info8.dependent_files) {
9189                 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9190                 if (d->info8.dependent_files->string) {
9191                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9192                         }
9193                         info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9194                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9195                                 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9196                         }
9197                 }
9198         }
9199         info8.architecture      = d->local.environment;
9200
9201         for (i=0; i < ARRAY_SIZE(levels); i++) {
9202
9203                 if (torture_setting_bool(tctx, "samba3", false)) {
9204                         switch (levels[i]) {
9205                         case 2:
9206                         case 4:
9207                         case 8:
9208                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9209                                 continue;
9210                         default:
9211                                 break;
9212                         }
9213                 }
9214                 if (torture_setting_bool(tctx, "w2k3", false)) {
9215                         switch (levels[i]) {
9216                         case 8:
9217                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9218                                 continue;
9219                         default:
9220                                 break;
9221                         }
9222                 }
9223
9224                 torture_comment(tctx,
9225                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
9226                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9227
9228                 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);
9229         }
9230
9231         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9232         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9233         if (d->info8.config_file) {
9234                 info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9235         }
9236         if (d->info8.help_file) {
9237                 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9238         }
9239         if (d->info8.dependent_files && d->info8.dependent_files->string) {
9240                 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9241                         info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9242                 }
9243         }
9244
9245         for (i=0; i < ARRAY_SIZE(levels); i++) {
9246
9247                 if (torture_setting_bool(tctx, "samba3", false)) {
9248                         switch (levels[i]) {
9249                         case 2:
9250                         case 4:
9251                         case 8:
9252                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9253                                 continue;
9254                         default:
9255                                 break;
9256                         }
9257                 }
9258                 if (torture_setting_bool(tctx, "w2k3", false)) {
9259                         switch (levels[i]) {
9260                         case 8:
9261                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9262                                 continue;
9263                         default:
9264                                 break;
9265                         }
9266                 }
9267
9268                 torture_comment(tctx,
9269                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9270                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9271
9272                 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);
9273         }
9274
9275         torture_assert(tctx,
9276                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9277                 "failed to remove printer driver");
9278
9279         torture_comment(tctx, "\n");
9280
9281         return ret;
9282 }
9283
9284 static bool test_add_driver_ex_64(struct torture_context *tctx,
9285                                   struct dcerpc_pipe *p)
9286 {
9287         struct torture_driver_context *d;
9288
9289         d = talloc_zero(tctx, struct torture_driver_context);
9290
9291         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9292         d->info8.driver_name            = TORTURE_DRIVER_EX;
9293         d->info8.architecture           = NULL;
9294         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9295         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9296         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9297         d->local.environment            = talloc_strdup(d, "Windows x64");
9298         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9299         d->ex                           = true;
9300
9301         return test_add_driver_arg(tctx, p, d);
9302 }
9303
9304 static bool test_add_driver_ex_32(struct torture_context *tctx,
9305                                   struct dcerpc_pipe *p)
9306 {
9307         struct torture_driver_context *d;
9308
9309         d = talloc_zero(tctx, struct torture_driver_context);
9310
9311         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9312         d->info8.driver_name            = TORTURE_DRIVER_EX;
9313         d->info8.architecture           = NULL;
9314         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9315         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9316         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9317         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9318         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9319         d->ex                           = true;
9320
9321         return test_add_driver_arg(tctx, p, d);
9322 }
9323
9324 static bool test_add_driver_64(struct torture_context *tctx,
9325                                struct dcerpc_pipe *p)
9326 {
9327         struct torture_driver_context *d;
9328
9329         d = talloc_zero(tctx, struct torture_driver_context);
9330
9331         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9332         d->info8.driver_name            = TORTURE_DRIVER;
9333         d->info8.architecture           = NULL;
9334         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9335         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9336         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9337         d->local.environment            = talloc_strdup(d, "Windows x64");
9338         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9339         d->ex                           = false;
9340
9341         return test_add_driver_arg(tctx, p, d);
9342 }
9343
9344 static bool test_add_driver_32(struct torture_context *tctx,
9345                                struct dcerpc_pipe *p)
9346 {
9347         struct torture_driver_context *d;
9348
9349         d = talloc_zero(tctx, struct torture_driver_context);
9350
9351         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9352         d->info8.driver_name            = TORTURE_DRIVER;
9353         d->info8.architecture           = NULL;
9354         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9355         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9356         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9357         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9358         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9359         d->ex                           = false;
9360
9361         return test_add_driver_arg(tctx, p, d);
9362 }
9363
9364 static bool test_add_driver_adobe(struct torture_context *tctx,
9365                                   struct dcerpc_pipe *p)
9366 {
9367         struct torture_driver_context *d;
9368
9369         if (!torture_setting_bool(tctx, "samba3", false)) {
9370                 torture_skip(tctx, "skipping adobe test which only works against samba3");
9371         }
9372
9373         d = talloc_zero(tctx, struct torture_driver_context);
9374
9375         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
9376         d->info8.driver_name            = TORTURE_DRIVER_ADOBE;
9377         d->info8.architecture           = NULL;
9378         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
9379         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
9380         d->info8.config_file            = talloc_strdup(d, "ADOBEPS4.DRV");
9381 #if 0
9382         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
9383         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
9384 #endif
9385         d->local.environment            = talloc_strdup(d, "Windows 4.0");
9386         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9387         d->ex                           = false;
9388
9389         return test_add_driver_arg(tctx, p, d);
9390 }
9391
9392 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9393                                              struct dcerpc_pipe *p)
9394 {
9395         struct torture_driver_context *d;
9396         struct spoolss_StringArray *a;
9397
9398         if (!torture_setting_bool(tctx, "samba3", false)) {
9399                 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9400         }
9401
9402         d = talloc_zero(tctx, struct torture_driver_context);
9403
9404         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
9405         d->info8.driver_name            = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9406         d->info8.architecture           = NULL;
9407         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
9408         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
9409         d->info8.config_file            = NULL;
9410         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
9411         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
9412         d->info8.default_datatype       = talloc_strdup(d, "RAW");
9413
9414         a                               = talloc_zero(d, struct spoolss_StringArray);
9415         a->string                       = talloc_zero_array(a, const char *, 7);
9416         a->string[0]                    = talloc_strdup(a->string, "ADOBEPS4.DRV");
9417         a->string[1]                    = talloc_strdup(a->string, "DEFPRTR2.PPD");
9418         a->string[2]                    = talloc_strdup(a->string, "ADOBEPS4.HLP");
9419         a->string[3]                    = talloc_strdup(a->string, "PSMON.DLL");
9420         a->string[4]                    = talloc_strdup(a->string, "ADFONTS.MFM");
9421         a->string[5]                    = talloc_strdup(a->string, "ICONLIB.DLL");
9422
9423         d->info8.dependent_files        = a;
9424         d->local.environment            = talloc_strdup(d, "Windows 4.0");
9425         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9426         d->ex                           = false;
9427
9428         return test_add_driver_arg(tctx, p, d);
9429 }
9430
9431 static bool test_add_driver_timestamps(struct torture_context *tctx,
9432                                        struct dcerpc_pipe *p)
9433 {
9434         struct torture_driver_context *d;
9435         struct timeval t = timeval_current();
9436
9437         d = talloc_zero(tctx, struct torture_driver_context);
9438
9439         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9440         d->info8.driver_name            = TORTURE_DRIVER_TIMESTAMPS;
9441         d->info8.architecture           = NULL;
9442         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9443         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9444         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9445         d->info8.driver_date            = timeval_to_nttime(&t);
9446         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9447         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9448         d->ex                           = true;
9449
9450         torture_assert(tctx,
9451                 test_add_driver_arg(tctx, p, d),
9452                 "");
9453
9454         unix_to_nt_time(&d->info8.driver_date, 1);
9455
9456         torture_assert(tctx,
9457                 test_add_driver_arg(tctx, p, d),
9458                 "");
9459
9460         return true;
9461 }
9462
9463 static bool test_multiple_drivers(struct torture_context *tctx,
9464                                   struct dcerpc_pipe *p)
9465 {
9466         struct torture_driver_context *d;
9467         struct dcerpc_binding_handle *b = p->binding_handle;
9468         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9469         int i;
9470         struct spoolss_AddDriverInfo8 info8;
9471         uint32_t add_flags = APD_COPY_NEW_FILES;
9472         uint32_t delete_flags = 0;
9473
9474         d = talloc_zero(tctx, struct torture_driver_context);
9475
9476         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9477         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9478         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9479         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9480         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9481         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9482         d->ex                           = true;
9483
9484         torture_assert(tctx,
9485                 fillup_printserver_info(tctx, p, d),
9486                 "failed to fillup printserver info");
9487
9488         if (!directory_exist(d->local.driver_directory)) {
9489                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9490         }
9491
9492         torture_assert(tctx,
9493                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9494                 "failed to upload printer driver");
9495
9496         info8 = d->info8;
9497         info8.architecture      = d->local.environment;
9498
9499         for (i=0; i < 3; i++) {
9500                 info8.driver_name               = talloc_asprintf(d, "torture_test_driver_%d", i);
9501
9502                 torture_assert(tctx,
9503                         test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9504                         "failed to add driver");
9505         }
9506
9507         torture_assert(tctx,
9508                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9509                 "failed to delete driver");
9510
9511         torture_assert(tctx,
9512                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9513                 "torture_test_driver_1 no longer on the server");
9514
9515         torture_assert(tctx,
9516                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9517                 "torture_test_driver_2 no longer on the server");
9518
9519         torture_assert(tctx,
9520                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9521                 "failed to delete driver");
9522
9523         torture_assert(tctx,
9524                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9525                 "torture_test_driver_2 no longer on the server");
9526
9527         torture_assert(tctx,
9528                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9529                 "failed to delete driver");
9530
9531         torture_assert(tctx,
9532                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9533                 "failed to remove printer driver");
9534
9535         return true;
9536 }
9537
9538 static bool test_del_driver_all_files(struct torture_context *tctx,
9539                                       struct dcerpc_pipe *p)
9540 {
9541         struct torture_driver_context *d;
9542         struct spoolss_StringArray *a;
9543         uint32_t add_flags = APD_COPY_NEW_FILES;
9544         uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9545         struct dcerpc_binding_handle *b = p->binding_handle;
9546         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9547
9548         d = talloc_zero(tctx, struct torture_driver_context);
9549
9550         d->ex                           = true;
9551         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9552         d->info8.driver_name            = TORTURE_DRIVER_DELETER;
9553         d->info8.architecture           = NULL;
9554         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9555         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9556         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9557         d->info8.help_file              = talloc_strdup(d, "pscript.hlp");
9558         d->local.environment            = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9559         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9560
9561         a                               = talloc_zero(d, struct spoolss_StringArray);
9562         a->string                       = talloc_zero_array(a, const char *, 3);
9563         a->string[0]                    = talloc_strdup(a->string, "cups6.inf");
9564         a->string[1]                    = talloc_strdup(a->string, "cups6.ini");
9565
9566         d->info8.dependent_files        = a;
9567         d->info8.architecture           = d->local.environment;
9568
9569         torture_assert(tctx,
9570                 fillup_printserver_info(tctx, p, d),
9571                 "failed to fillup printserver info");
9572
9573         if (!directory_exist(d->local.driver_directory)) {
9574                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9575         }
9576
9577         torture_assert(tctx,
9578                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9579                 "failed to upload printer driver");
9580
9581         torture_assert(tctx,
9582                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9583                 "failed to add driver");
9584
9585         torture_assert(tctx,
9586                 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9587                                            d->info8.driver_name,
9588                                            d->local.environment,
9589                                            delete_flags,
9590                                            d->info8.version),
9591                 "failed to delete driver");
9592
9593         torture_assert(tctx,
9594                 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9595                 "printer driver file check failed");
9596
9597         talloc_free(d);
9598         return true;
9599 }
9600
9601 static bool test_del_driver_unused_files(struct torture_context *tctx,
9602                                          struct dcerpc_pipe *p)
9603 {
9604         struct torture_driver_context *d1;
9605         struct torture_driver_context *d2;
9606         uint32_t add_flags = APD_COPY_NEW_FILES;
9607         struct dcerpc_binding_handle *b = p->binding_handle;
9608         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9609
9610         d1 = talloc_zero(tctx, struct torture_driver_context);
9611         d1->ex                          = true;
9612         d1->info8.version               = SPOOLSS_DRIVER_VERSION_200X;
9613         d1->info8.driver_name           = TORTURE_DRIVER_DELETER;
9614         d1->info8.architecture          = NULL;
9615         d1->info8.driver_path           = talloc_strdup(d1, "pscript5.dll");
9616         d1->info8.data_file             = talloc_strdup(d1, "cups6.ppd");
9617         d1->info8.config_file           = talloc_strdup(d1, "cupsui6.dll");
9618         d1->info8.help_file             = talloc_strdup(d1, "pscript.hlp");
9619         d1->local.environment           = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9620         d1->local.driver_directory      = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9621         d1->info8.architecture          = d1->local.environment;
9622
9623         d2 = talloc_zero(tctx, struct torture_driver_context);
9624         d2->ex                          = true;
9625         d2->info8.version               = SPOOLSS_DRIVER_VERSION_200X;
9626         d2->info8.driver_name           = TORTURE_DRIVER_DELETERIN;
9627         d2->info8.architecture          = NULL;
9628         d2->info8.driver_path           = talloc_strdup(d2, "pscript5.dll");    /* overlapping */
9629         d2->info8.data_file             = talloc_strdup(d2, "cupsps6.dll");
9630         d2->info8.config_file           = talloc_strdup(d2, "cups6.ini");
9631         d2->info8.help_file             = talloc_strdup(d2, "pscript.hlp");     /* overlapping */
9632         d2->local.environment           = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9633         d2->local.driver_directory      = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9634         d2->info8.architecture          = d2->local.environment;
9635
9636         torture_assert(tctx,
9637                 fillup_printserver_info(tctx, p, d1),
9638                 "failed to fillup printserver info");
9639         torture_assert(tctx,
9640                 fillup_printserver_info(tctx, p, d2),
9641                 "failed to fillup printserver info");
9642
9643         if (!directory_exist(d1->local.driver_directory)) {
9644                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9645         }
9646
9647         torture_assert(tctx,
9648                 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9649                 "failed to upload printer driver");
9650         torture_assert(tctx,
9651                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9652                 "failed to add driver");
9653
9654         torture_assert(tctx,
9655                 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9656                 "failed to upload printer driver");
9657         torture_assert(tctx,
9658                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9659                 "failed to add driver");
9660
9661         /* some files are in use by a separate driver, should fail */
9662         torture_assert(tctx,
9663                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9664                                                d1->info8.driver_name,
9665                                                d1->local.environment,
9666                                                DPD_DELETE_ALL_FILES,
9667                                                d1->info8.version,
9668                                                WERR_PRINTER_DRIVER_IN_USE),
9669                 "invalid delete driver response");
9670
9671         /* should only delete files not in use by other driver */
9672         torture_assert(tctx,
9673                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9674                                                d1->info8.driver_name,
9675                                                d1->local.environment,
9676                                                DPD_DELETE_UNUSED_FILES,
9677                                                d1->info8.version,
9678                                                WERR_OK),
9679                 "failed to delete driver (unused files)");
9680
9681         /* check non-overlapping were deleted */
9682         d1->info8.driver_path = NULL;
9683         d1->info8.help_file = NULL;
9684         torture_assert(tctx,
9685                 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9686                 "printer driver file check failed");
9687         /* d2 files should be uneffected */
9688         torture_assert(tctx,
9689                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9690                 "printer driver file check failed");
9691
9692         torture_assert(tctx,
9693                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9694                                                d2->info8.driver_name,
9695                                                d2->local.environment,
9696                                                DPD_DELETE_ALL_FILES,
9697                                                d2->info8.version,
9698                                                WERR_OK),
9699                 "failed to delete driver");
9700
9701         torture_assert(tctx,
9702                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9703                 "printer driver file check failed");
9704
9705         talloc_free(d1);
9706         talloc_free(d2);
9707         return true;
9708 }
9709
9710 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9711 {
9712         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9713
9714         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9715                                                         "driver", &ndr_table_spoolss);
9716         torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9717         torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9718
9719         torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9720         torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9721
9722         torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9723
9724         torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9725
9726         torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9727
9728         torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9729
9730         torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9731
9732         torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9733
9734         return suite;
9735 }