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