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