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