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