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