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