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