s4-smbtorture: when comparing PrinterData from DsSpooler and PrinterInfo also
[obnox/samba/samba-obnox.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-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, ic, needed, align) do { \
178         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
179         uint32_t size = ndr_size_##fn##_info(tctx, ic, 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, ic, needed, align) do { \
189         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
190         uint32_t size = ndr_size_##fn##_info(tctx, ic, 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, ic, needed, align) do { \
200         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201         uint32_t size = ndr_size_##fn(info, level, ic, 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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, lp_iconv_convenience(tctx->lp_ctx), 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         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3262
3263         for (i=0; i < num_jobs; i++) {
3264                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3265         }
3266
3267         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
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         return ret;
3274 }
3275
3276 static bool test_PausePrinter(struct torture_context *tctx,
3277                               struct dcerpc_binding_handle *b,
3278                               struct policy_handle *handle)
3279 {
3280         NTSTATUS status;
3281         struct spoolss_SetPrinter r;
3282         struct spoolss_SetPrinterInfoCtr info_ctr;
3283         struct spoolss_DevmodeContainer devmode_ctr;
3284         struct sec_desc_buf secdesc_ctr;
3285
3286         info_ctr.level = 0;
3287         info_ctr.info.info0 = NULL;
3288
3289         ZERO_STRUCT(devmode_ctr);
3290         ZERO_STRUCT(secdesc_ctr);
3291
3292         r.in.handle             = handle;
3293         r.in.info_ctr           = &info_ctr;
3294         r.in.devmode_ctr        = &devmode_ctr;
3295         r.in.secdesc_ctr        = &secdesc_ctr;
3296         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3297
3298         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3299
3300         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3301
3302         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3303
3304         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3305
3306         return true;
3307 }
3308
3309 static bool test_ResumePrinter(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_RESUME;
3330
3331         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\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_GetPrinterData(struct torture_context *tctx,
3343                                 struct dcerpc_binding_handle *b,
3344                                 struct policy_handle *handle,
3345                                 const char *value_name,
3346                                 enum winreg_Type *type_p,
3347                                 uint8_t **data_p,
3348                                 uint32_t *needed_p)
3349 {
3350         NTSTATUS status;
3351         struct spoolss_GetPrinterData r;
3352         uint32_t needed;
3353         enum winreg_Type type;
3354         union spoolss_PrinterData data;
3355
3356         r.in.handle = handle;
3357         r.in.value_name = value_name;
3358         r.in.offered = 0;
3359         r.out.needed = &needed;
3360         r.out.type = &type;
3361         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3362
3363         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3364
3365         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3366         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3367
3368         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3369                 r.in.offered = needed;
3370                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3371                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3372                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3373         }
3374
3375         torture_assert_werr_ok(tctx, r.out.result,
3376                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3377
3378         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3379
3380         if (type_p) {
3381                 *type_p = type;
3382         }
3383
3384         if (data_p) {
3385                 *data_p = r.out.data;
3386         }
3387
3388         if (needed_p) {
3389                 *needed_p = needed;
3390         }
3391
3392         return true;
3393 }
3394
3395 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3396                                   struct dcerpc_pipe *p,
3397                                   struct policy_handle *handle,
3398                                   const char *key_name,
3399                                   const char *value_name,
3400                                   enum winreg_Type *type_p,
3401                                   uint8_t **data_p,
3402                                   uint32_t *needed_p)
3403 {
3404         NTSTATUS status;
3405         struct spoolss_GetPrinterDataEx r;
3406         enum winreg_Type type;
3407         uint32_t needed;
3408         union spoolss_PrinterData data;
3409         struct dcerpc_binding_handle *b = p->binding_handle;
3410
3411         r.in.handle = handle;
3412         r.in.key_name = key_name;
3413         r.in.value_name = value_name;
3414         r.in.offered = 0;
3415         r.out.type = &type;
3416         r.out.needed = &needed;
3417         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3418
3419         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3420                 r.in.key_name, r.in.value_name);
3421
3422         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3423         if (!NT_STATUS_IS_OK(status)) {
3424                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3425                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3426                 }
3427                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3428         }
3429
3430         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3431                 r.in.offered = needed;
3432                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3433                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3434                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3435         }
3436
3437         torture_assert_werr_ok(tctx, r.out.result,
3438                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3439
3440         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3441
3442         if (type_p) {
3443                 *type_p = type;
3444         }
3445
3446         if (data_p) {
3447                 *data_p = r.out.data;
3448         }
3449
3450         if (needed_p) {
3451                 *needed_p = needed;
3452         }
3453
3454         return true;
3455 }
3456
3457 static bool test_get_environment(struct torture_context *tctx,
3458                                  struct dcerpc_binding_handle *b,
3459                                  struct policy_handle *handle,
3460                                  const char **architecture)
3461 {
3462         DATA_BLOB blob;
3463         enum winreg_Type type;
3464         uint8_t *data;
3465         uint32_t needed;
3466
3467         torture_assert(tctx,
3468                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3469                 "failed to get Architecture");
3470
3471         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3472
3473         blob = data_blob_const(data, needed);
3474         *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3475
3476         return true;
3477 }
3478
3479 static bool test_GetPrinterData_list(struct torture_context *tctx,
3480                                      struct dcerpc_pipe *p,
3481                                      struct policy_handle *handle,
3482                                      const char **architecture)
3483 {
3484         struct dcerpc_binding_handle *b = p->binding_handle;
3485         const char *list[] = {
3486                 "W3SvcInstalled",
3487                 "BeepEnabled",
3488                 "EventLog",
3489                 /* "NetPopup", not on w2k8 */
3490                 /* "NetPopupToComputer", not on w2k8 */
3491                 "MajorVersion",
3492                 "MinorVersion",
3493                 "DefaultSpoolDirectory",
3494                 "Architecture",
3495                 "DsPresent",
3496                 "OSVersion",
3497                 /* "OSVersionEx", not on s3 */
3498                 "DNSMachineName"
3499         };
3500         int i;
3501
3502         for (i=0; i < ARRAY_SIZE(list); i++) {
3503                 enum winreg_Type type, type_ex;
3504                 uint8_t *data, *data_ex;
3505                 uint32_t needed, needed_ex;
3506
3507                 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3508                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3509                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3510                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3511                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3512                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3513                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3514
3515                 if (strequal(list[i], "Architecture")) {
3516                         if (architecture) {
3517                                 DATA_BLOB blob = data_blob_const(data, needed);
3518                                 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3519                         }
3520                 }
3521         }
3522
3523         return true;
3524 }
3525
3526 static bool test_EnumPrinterData(struct torture_context *tctx,
3527                                  struct dcerpc_pipe *p,
3528                                  struct policy_handle *handle,
3529                                  uint32_t enum_index,
3530                                  uint32_t value_offered,
3531                                  uint32_t data_offered,
3532                                  enum winreg_Type *type_p,
3533                                  uint32_t *value_needed_p,
3534                                  uint32_t *data_needed_p,
3535                                  const char **value_name_p,
3536                                  uint8_t **data_p,
3537                                  WERROR *result_p)
3538 {
3539         struct spoolss_EnumPrinterData r;
3540         uint32_t data_needed;
3541         uint32_t value_needed;
3542         enum winreg_Type type;
3543         struct dcerpc_binding_handle *b = p->binding_handle;
3544
3545         r.in.handle = handle;
3546         r.in.enum_index = enum_index;
3547         r.in.value_offered = value_offered;
3548         r.in.data_offered = data_offered;
3549         r.out.data_needed = &data_needed;
3550         r.out.value_needed = &value_needed;
3551         r.out.type = &type;
3552         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3553         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3554
3555         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3556
3557         torture_assert_ntstatus_ok(tctx,
3558                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3559                 "EnumPrinterData failed");
3560
3561         if (type_p) {
3562                 *type_p = type;
3563         }
3564         if (value_needed_p) {
3565                 *value_needed_p = value_needed;
3566         }
3567         if (data_needed_p) {
3568                 *data_needed_p = data_needed;
3569         }
3570         if (value_name_p) {
3571                 *value_name_p = r.out.value_name;
3572         }
3573         if (data_p) {
3574                 *data_p = r.out.data;
3575         }
3576         if (result_p) {
3577                 *result_p = r.out.result;
3578         }
3579
3580         return true;
3581 }
3582
3583
3584 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3585                                      struct dcerpc_pipe *p,
3586                                      struct policy_handle *handle)
3587 {
3588         uint32_t enum_index = 0;
3589         enum winreg_Type type;
3590         uint32_t value_needed;
3591         uint32_t data_needed;
3592         uint8_t *data;
3593         const char *value_name;
3594         WERROR result;
3595
3596         torture_comment(tctx, "Testing EnumPrinterData\n");
3597
3598         do {
3599                 torture_assert(tctx,
3600                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3601                                              &type, &value_needed, &data_needed,
3602                                              &value_name, &data, &result),
3603                         "EnumPrinterData failed");
3604
3605                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3606                         break;
3607                 }
3608
3609                 torture_assert(tctx,
3610                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3611                                              &type, &value_needed, &data_needed,
3612                                              &value_name, &data, &result),
3613                         "EnumPrinterData failed");
3614
3615                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3616                         break;
3617                 }
3618
3619                 enum_index++;
3620
3621         } while (W_ERROR_IS_OK(result));
3622
3623         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3624
3625         return true;
3626 }
3627
3628 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3629                                    struct dcerpc_binding_handle *b,
3630                                    struct policy_handle *handle,
3631                                    const char *key_name,
3632                                    uint32_t *count_p,
3633                                    struct spoolss_PrinterEnumValues **info_p)
3634 {
3635         struct spoolss_EnumPrinterDataEx r;
3636         struct spoolss_PrinterEnumValues *info;
3637         uint32_t needed;
3638         uint32_t count;
3639
3640         r.in.handle = handle;
3641         r.in.key_name = key_name;
3642         r.in.offered = 0;
3643         r.out.needed = &needed;
3644         r.out.count = &count;
3645         r.out.info = &info;
3646
3647         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3648
3649         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3650                 "EnumPrinterDataEx failed");
3651         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3652                 r.in.offered = needed;
3653                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3654                         "EnumPrinterDataEx failed");
3655         }
3656
3657         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3658
3659         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3660
3661         if (count_p) {
3662                 *count_p = count;
3663         }
3664         if (info_p) {
3665                 *info_p = info;
3666         }
3667
3668         return true;
3669 }
3670
3671 static bool test_SetPrinterData(struct torture_context *tctx,
3672                                 struct dcerpc_binding_handle *b,
3673                                 struct policy_handle *handle,
3674                                 const char *value_name,
3675                                 enum winreg_Type type,
3676                                 uint8_t *data,
3677                                 uint32_t offered);
3678 static bool test_DeletePrinterData(struct torture_context *tctx,
3679                                    struct dcerpc_binding_handle *b,
3680                                    struct policy_handle *handle,
3681                                    const char *value_name);
3682
3683 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3684                                              struct dcerpc_pipe *p,
3685                                              struct policy_handle *handle)
3686 {
3687         uint32_t count;
3688         struct spoolss_PrinterEnumValues *info;
3689         int i;
3690         uint32_t value_needed, data_needed;
3691         uint32_t value_offered, data_offered;
3692         WERROR result;
3693         struct dcerpc_binding_handle *b = p->binding_handle;
3694
3695         enum winreg_Type type;
3696         DATA_BLOB blob;
3697
3698         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3699
3700         torture_assert(tctx,
3701                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3702                                   "REG_SZ", "torture_data1", &type, &blob), "");
3703
3704         torture_assert(tctx,
3705                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3706                 "SetPrinterData failed");
3707
3708         blob = data_blob_string_const("torture_data2");
3709
3710         torture_assert(tctx,
3711                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3712                 "SetPrinterData failed");
3713
3714         blob = data_blob_talloc(tctx, NULL, 4);
3715         SIVAL(blob.data, 0, 0x11223344);
3716
3717         torture_assert(tctx,
3718                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3719                 "SetPrinterData failed");
3720
3721         torture_assert(tctx,
3722                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3723                 "failed to call EnumPrinterDataEx");
3724
3725         /* get the max sizes for value and data */
3726
3727         torture_assert(tctx,
3728                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3729                                      NULL, &value_needed, &data_needed,
3730                                      NULL, NULL, &result),
3731                 "EnumPrinterData failed");
3732         torture_assert_werr_ok(tctx, result, "unexpected result");
3733
3734         /* check if the reply from the EnumPrinterData really matches max values */
3735
3736         for (i=0; i < count; i++) {
3737                 if (info[i].value_name_len > value_needed) {
3738                         torture_fail(tctx,
3739                                 talloc_asprintf(tctx,
3740                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3741                                 info[i].value_name_len, value_needed));
3742                 }
3743                 if (info[i].data_length > data_needed) {
3744                         torture_fail(tctx,
3745                                 talloc_asprintf(tctx,
3746                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3747                                 info[i].data_length, data_needed));
3748                 }
3749         }
3750
3751         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3752          * sort or not sort the replies by value name, we should be able to do
3753          * the following entry comparison */
3754
3755         data_offered = data_needed;
3756         value_offered = value_needed;
3757
3758         for (i=0; i < count; i++) {
3759
3760                 const char *value_name;
3761                 uint8_t *data;
3762
3763                 torture_assert(tctx,
3764                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3765                                              &type, &value_needed, &data_needed,
3766                                              &value_name, &data, &result),
3767                         "EnumPrinterData failed");
3768
3769                 if (i -1 == count) {
3770                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3771                                 "unexpected result");
3772                         break;
3773                 } else {
3774                         torture_assert_werr_ok(tctx, result, "unexpected result");
3775                 }
3776
3777                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3778                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3779                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3780                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3781                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3782         }
3783
3784         torture_assert(tctx,
3785                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3786                 "DeletePrinterData failed");
3787         torture_assert(tctx,
3788                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3789                 "DeletePrinterData failed");
3790         torture_assert(tctx,
3791                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3792                 "DeletePrinterData failed");
3793
3794         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3795
3796         return true;
3797 }
3798
3799 static bool test_DeletePrinterData(struct torture_context *tctx,
3800                                    struct dcerpc_binding_handle *b,
3801                                    struct policy_handle *handle,
3802                                    const char *value_name)
3803 {
3804         NTSTATUS status;
3805         struct spoolss_DeletePrinterData r;
3806
3807         r.in.handle = handle;
3808         r.in.value_name = value_name;
3809
3810         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3811                 r.in.value_name);
3812
3813         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3814
3815         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3816         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3817
3818         return true;
3819 }
3820
3821 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3822                                      struct dcerpc_binding_handle *b,
3823                                      struct policy_handle *handle,
3824                                      const char *key_name,
3825                                      const char *value_name)
3826 {
3827         struct spoolss_DeletePrinterDataEx r;
3828
3829         r.in.handle = handle;
3830         r.in.key_name = key_name;
3831         r.in.value_name = value_name;
3832
3833         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3834                 r.in.key_name, r.in.value_name);
3835
3836         torture_assert_ntstatus_ok(tctx,
3837                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3838                 "DeletePrinterDataEx failed");
3839         torture_assert_werr_ok(tctx, r.out.result,
3840                 "DeletePrinterDataEx failed");
3841
3842         return true;
3843 }
3844
3845 static bool test_DeletePrinterKey(struct torture_context *tctx,
3846                                   struct dcerpc_binding_handle *b,
3847                                   struct policy_handle *handle,
3848                                   const char *key_name)
3849 {
3850         struct spoolss_DeletePrinterKey r;
3851
3852         r.in.handle = handle;
3853         r.in.key_name = key_name;
3854
3855         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3856
3857         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3858                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3859                 return true;
3860         }
3861
3862         torture_assert_ntstatus_ok(tctx,
3863                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3864                 "DeletePrinterKey failed");
3865         torture_assert_werr_ok(tctx, r.out.result,
3866                 "DeletePrinterKey failed");
3867
3868         return true;
3869 }
3870
3871 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3872                                  struct dcerpc_binding_handle *b,
3873                                  struct policy_handle *handle)
3874 {
3875         struct winreg_OpenHKLM r;
3876
3877         r.in.system_name = NULL;
3878         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3879         r.out.handle = handle;
3880
3881         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3882
3883         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3884         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3885
3886         return true;
3887 }
3888
3889 static void init_winreg_String(struct winreg_String *name, const char *s)
3890 {
3891         name->name = s;
3892         if (s) {
3893                 name->name_len = 2 * (strlen_m(s) + 1);
3894                 name->name_size = name->name_len;
3895         } else {
3896                 name->name_len = 0;
3897                 name->name_size = 0;
3898         }
3899 }
3900
3901 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3902                                      struct dcerpc_binding_handle *b,
3903                                      struct policy_handle *hive_handle,
3904                                      const char *keyname,
3905                                      uint32_t options,
3906                                      struct policy_handle *key_handle)
3907 {
3908         struct winreg_OpenKey r;
3909
3910         r.in.parent_handle = hive_handle;
3911         init_winreg_String(&r.in.keyname, keyname);
3912         r.in.options = options;
3913         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3914         r.out.handle = key_handle;
3915
3916         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3917
3918         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3919         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3920
3921         return true;
3922 }
3923
3924 static bool test_winreg_OpenKey(struct torture_context *tctx,
3925                                 struct dcerpc_binding_handle *b,
3926                                 struct policy_handle *hive_handle,
3927                                 const char *keyname,
3928                                 struct policy_handle *key_handle)
3929 {
3930         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
3931                                         REG_OPTION_NON_VOLATILE, key_handle);
3932 }
3933
3934 static bool test_winreg_CloseKey(struct torture_context *tctx,
3935                                  struct dcerpc_binding_handle *b,
3936                                  struct policy_handle *handle)
3937 {
3938         struct winreg_CloseKey r;
3939
3940         r.in.handle = handle;
3941         r.out.handle = handle;
3942
3943         torture_comment(tctx, "Testing winreg_CloseKey\n");
3944
3945         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3946         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3947
3948         return true;
3949 }
3950
3951 bool test_winreg_QueryValue(struct torture_context *tctx,
3952                             struct dcerpc_binding_handle *b,
3953                             struct policy_handle *handle,
3954                             const char *value_name,
3955                             enum winreg_Type *type_p,
3956                             uint32_t *data_size_p,
3957                             uint32_t *data_length_p,
3958                             uint8_t **data_p)
3959 {
3960         struct winreg_QueryValue r;
3961         enum winreg_Type type = REG_NONE;
3962         uint32_t data_size = 0;
3963         uint32_t data_length = 0;
3964         struct winreg_String valuename;
3965         uint8_t *data = NULL;
3966
3967         init_winreg_String(&valuename, value_name);
3968
3969         data = talloc_zero_array(tctx, uint8_t, 0);
3970
3971         r.in.handle = handle;
3972         r.in.value_name = &valuename;
3973         r.in.type = &type;
3974         r.in.data_size = &data_size;
3975         r.in.data_length = &data_length;
3976         r.in.data = data;
3977         r.out.type = &type;
3978         r.out.data = data;
3979         r.out.data_size = &data_size;
3980         r.out.data_length = &data_length;
3981
3982         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3983
3984         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3985         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3986                 *r.in.data_size = *r.out.data_size;
3987                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3988                 r.in.data = data;
3989                 r.out.data = data;
3990                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3991         }
3992         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3993
3994         if (type_p) {
3995                 *type_p = *r.out.type;
3996         }
3997         if (data_size_p) {
3998                 *data_size_p = *r.out.data_size;
3999         }
4000         if (data_length_p) {
4001                 *data_length_p = *r.out.data_length;
4002         }
4003         if (data_p) {
4004                 *data_p = r.out.data;
4005         }
4006
4007         return true;
4008 }
4009
4010 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4011                                           struct dcerpc_binding_handle *b,
4012                                           struct policy_handle *handle,
4013                                           const char *printer_name,
4014                                           const char *key_name,
4015                                           const char *value_name,
4016                                           enum winreg_Type *w_type,
4017                                           uint32_t *w_size,
4018                                           uint32_t *w_length,
4019                                           uint8_t **w_data)
4020 {
4021         const char *printer_key;
4022         struct policy_handle key_handle;
4023
4024         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4025                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4026
4027         torture_assert(tctx,
4028                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4029
4030         torture_assert(tctx,
4031                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4032
4033         torture_assert(tctx,
4034                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4035
4036         return true;
4037 }
4038
4039 static bool test_GetForm_winreg(struct torture_context *tctx,
4040                                 struct dcerpc_binding_handle *b,
4041                                 struct policy_handle *handle,
4042                                 const char *key_name,
4043                                 const char *form_name,
4044                                 enum winreg_Type *w_type,
4045                                 uint32_t *w_size,
4046                                 uint32_t *w_length,
4047                                 uint8_t **w_data)
4048 {
4049         struct policy_handle key_handle;
4050
4051         torture_assert(tctx,
4052                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4053
4054         torture_assert(tctx,
4055                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4056
4057         torture_assert(tctx,
4058                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4059
4060         return true;
4061 }
4062
4063 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4064                                       struct dcerpc_binding_handle *b,
4065                                       struct policy_handle *handle,
4066                                       const char *symlink_keyname,
4067                                       const char *symlink_destination)
4068 {
4069         /* check if the first key is a symlink to the second key */
4070
4071         enum winreg_Type w_type;
4072         uint32_t w_size;
4073         uint32_t w_length;
4074         uint8_t *w_data;
4075         struct policy_handle key_handle;
4076         DATA_BLOB blob;
4077         const char *str;
4078
4079         if (torture_setting_bool(tctx, "samba3", false)) {
4080                 torture_skip(tctx, "skip winreg symlink test against samba");
4081         }
4082
4083         torture_assert(tctx,
4084                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4085                         "failed to open key link");
4086
4087         torture_assert(tctx,
4088                 test_winreg_QueryValue(tctx, b, &key_handle,
4089                                        "SymbolicLinkValue",
4090                                        &w_type, &w_size, &w_length, &w_data),
4091                 "failed to query for 'SymbolicLinkValue' attribute");
4092
4093         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4094
4095         blob = data_blob(w_data, w_size);
4096         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
4097
4098         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4099
4100         torture_assert(tctx,
4101                 test_winreg_CloseKey(tctx, b, &key_handle),
4102                 "failed to close key link");
4103
4104         return true;
4105 }
4106
4107 static const char *strip_unc(const char *unc)
4108 {
4109         char *name;
4110
4111         if (!unc) {
4112                 return NULL;
4113         }
4114
4115         if (unc[0] == '\\' && unc[1] == '\\') {
4116                 unc +=2;
4117         }
4118
4119         name = strchr(unc, '\\');
4120         if (name) {
4121                 return name+1;
4122         }
4123
4124         return unc;
4125 }
4126
4127 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4128                                        struct dcerpc_binding_handle *b,
4129                                        struct policy_handle *handle,
4130                                        const char *printer_name,
4131                                        struct dcerpc_binding_handle *winreg_handle,
4132                                        struct policy_handle *hive_handle)
4133 {
4134         union spoolss_PrinterInfo info;
4135         const char *keys[] = {
4136                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4137                 TOP_LEVEL_PRINT_PRINTERS_KEY
4138         };
4139         int i;
4140         const char *printername, *sharename;
4141
4142         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4143
4144         torture_assert(tctx,
4145                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4146                 "failed to get printer info level 2");
4147
4148         printername = strip_unc(info.info2.printername);
4149         sharename = strip_unc(info.info2.sharename);
4150
4151 #define test_sz(wname, iname) \
4152 do {\
4153         DATA_BLOB blob;\
4154         const char *str;\
4155         enum winreg_Type w_type;\
4156         uint32_t w_size;\
4157         uint32_t w_length;\
4158         uint8_t *w_data;\
4159         torture_assert(tctx,\
4160                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4161                                        &w_type, &w_size, &w_length, &w_data),\
4162                 "failed to query winreg");\
4163         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4164         blob = data_blob(w_data, w_size);\
4165         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);\
4166         if (w_size == 2 && iname == NULL) {\
4167                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4168         } else {\
4169                 torture_assert_str_equal(tctx, str, iname,\
4170                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4171         }\
4172 } while(0);
4173
4174 #define test_dword(wname, iname) \
4175 do {\
4176         uint32_t value;\
4177         enum winreg_Type w_type;\
4178         uint32_t w_size;\
4179         uint32_t w_length;\
4180         uint8_t *w_data;\
4181         torture_assert(tctx,\
4182                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4183                                        &w_type, &w_size, &w_length, &w_data),\
4184                 "failed to query winreg");\
4185         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4186         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4187         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4188         value = IVAL(w_data, 0);\
4189         torture_assert_int_equal(tctx, value, iname,\
4190                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4191 } while(0);
4192
4193 #define test_dm(wname, iname) \
4194 do {\
4195         DATA_BLOB blob;\
4196         struct spoolss_DeviceMode dm;\
4197         enum ndr_err_code ndr_err;\
4198         enum winreg_Type w_type;\
4199         uint32_t w_size;\
4200         uint32_t w_length;\
4201         uint8_t *w_data;\
4202         torture_assert(tctx,\
4203                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4204                                        &w_type, &w_size, &w_length, &w_data),\
4205                 "failed to query winreg");\
4206         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4207         blob = data_blob(w_data, w_size);\
4208         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &dm,\
4209                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4210         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4211         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4212                 "dm unequal");\
4213 } while(0);
4214
4215 #define test_sd(wname, iname) \
4216 do {\
4217         DATA_BLOB blob;\
4218         struct security_descriptor sd;\
4219         enum ndr_err_code ndr_err;\
4220         enum winreg_Type w_type;\
4221         uint32_t w_size;\
4222         uint32_t w_length;\
4223         uint8_t *w_data;\
4224         torture_assert(tctx,\
4225                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4226                                        &w_type, &w_size, &w_length, &w_data),\
4227                 "failed to query winreg");\
4228         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4229         blob = data_blob(w_data, w_size);\
4230         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &sd,\
4231                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4232         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4233         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4234                 "sd unequal");\
4235 } while(0);
4236
4237 #define test_multi_sz(wname, iname) \
4238 do {\
4239         DATA_BLOB blob;\
4240         const char **array;\
4241         enum winreg_Type w_type;\
4242         uint32_t w_size;\
4243         uint32_t w_length;\
4244         uint8_t *w_data;\
4245         int i;\
4246         torture_assert(tctx,\
4247                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4248                                        &w_type, &w_size, &w_length, &w_data),\
4249                 "failed to query winreg");\
4250         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4251         blob = data_blob(w_data, w_size);\
4252         torture_assert(tctx, \
4253                 pull_reg_multi_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &array),\
4254                 "failed to pull multi sz");\
4255         for (i=0; array[i] != NULL; i++) {\
4256                 torture_assert_str_equal(tctx, array[i], iname[i],\
4257                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4258         }\
4259 } while(0);
4260
4261
4262         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4263                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4264                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4265         {
4266                 torture_warning(tctx, "failed to check for winreg symlink");
4267         }
4268
4269
4270         for (i=0; i < ARRAY_SIZE(keys); i++) {
4271
4272                 const char *printer_key;
4273                 struct policy_handle key_handle;
4274
4275                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4276                         keys[i], printer_name);
4277
4278                 torture_assert(tctx,
4279                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4280
4281                 test_sz("Name", printername);
4282                 test_sz("Share Name", sharename);
4283                 test_sz("Port", info.info2.portname);
4284                 test_sz("Printer Driver", info.info2.drivername);
4285                 test_sz("Description", info.info2.comment);
4286                 test_sz("Location", info.info2.location);
4287                 test_sz("Separator File", info.info2.sepfile);
4288                 test_sz("Print Processor", info.info2.printprocessor);
4289                 test_sz("Datatype", info.info2.datatype);
4290                 test_sz("Parameters", info.info2.parameters);
4291                 /* winreg: 0, spoolss not */
4292 /*              test_dword("Attributes", info.info2.attributes); */
4293                 test_dword("Priority", info.info2.priority);
4294                 test_dword("Default Priority", info.info2.defaultpriority);
4295                 /* winreg: 60, spoolss: 0 */
4296 /*              test_dword("StartTime", info.info2.starttime); */
4297 /*              test_dword("UntilTime", info.info2.untiltime); */
4298                 /* winreg != spoolss */
4299 /*              test_dword("Status", info.info2.status); */
4300                 test_dm("Default DevMode", info.info2.devmode);
4301                 test_sd("Security", info.info2.secdesc);
4302
4303                 torture_assert(tctx,
4304                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4305         }
4306
4307 #undef test_dm
4308 #undef test_sd
4309
4310         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4311
4312         return true;
4313 }
4314
4315 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4316                                          struct dcerpc_binding_handle *b,
4317                                          struct policy_handle *handle,
4318                                          const char *driver_name,
4319                                          const char *architecture,
4320                                          uint32_t level,
4321                                          uint32_t client_major_version,
4322                                          uint32_t client_minor_version,
4323                                          union spoolss_DriverInfo *info_p,
4324                                          WERROR *result);
4325
4326 static const char *strip_path(const char *path)
4327 {
4328         char *p;
4329
4330         if (path == NULL) {
4331                 return NULL;
4332         }
4333
4334         p = strrchr(path, '\\');
4335         if (p) {
4336                 return p+1;
4337         }
4338
4339         return path;
4340 }
4341
4342 static const char **strip_paths(const char **path_array)
4343 {
4344         int i;
4345
4346         if (path_array == NULL) {
4347                 return NULL;
4348         }
4349
4350         for (i=0; path_array[i] != NULL; i++) {
4351                 path_array[i] = strip_path(path_array[i]);
4352         }
4353
4354         return path_array;
4355 }
4356
4357 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4358 {
4359         time_t t;
4360         struct tm *tm;
4361         t = nt_time_to_unix(nt);
4362         tm = localtime(&t);
4363
4364         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4365                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4366 }
4367
4368 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4369 {
4370         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4371                 (unsigned)((v >> 48) & 0xFFFF),
4372                 (unsigned)((v >> 32) & 0xFFFF),
4373                 (unsigned)((v >> 16) & 0xFFFF),
4374                 (unsigned)(v & 0xFFFF));
4375 }
4376
4377 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4378                                       struct dcerpc_binding_handle *b,
4379                                       struct policy_handle *handle,
4380                                       const char *printer_name,
4381                                       const char *driver_name,
4382                                       const char *environment,
4383                                       struct dcerpc_binding_handle *winreg_handle,
4384                                       struct policy_handle *hive_handle)
4385 {
4386         WERROR result;
4387         union spoolss_DriverInfo info;
4388         const char *driver_key;
4389         struct policy_handle key_handle;
4390
4391         const char *driver_path;
4392         const char *data_file;
4393         const char *config_file;
4394         const char *help_file;
4395         const char **dependent_files;
4396
4397         const char *driver_date;
4398         const char *inbox_driver_date;
4399
4400         const char *driver_version;
4401         const char *inbox_driver_version;
4402
4403         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4404
4405         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4406                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4407                                      environment,
4408                                      3,
4409                                      driver_name);
4410
4411         torture_assert(tctx,
4412                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4413                 "failed to open driver key");
4414
4415         if (torture_setting_bool(tctx, "samba3", false)) {
4416                 goto try_level3;
4417         }
4418
4419         torture_assert(tctx,
4420                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4421                 "failed to get driver info level 8");
4422
4423         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4424                 goto try_level6;
4425         }
4426
4427         driver_path     = strip_path(info.info8.driver_path);
4428         data_file       = strip_path(info.info8.data_file);
4429         config_file     = strip_path(info.info8.config_file);
4430         help_file       = strip_path(info.info8.help_file);
4431         dependent_files = strip_paths(info.info8.dependent_files);
4432
4433         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4434         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4435
4436         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4437         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4438
4439         test_sz("Configuration File",           config_file);
4440         test_sz("Data File",                    data_file);
4441         test_sz("Datatype",                     info.info8.default_datatype);
4442         test_sz("Driver",                       driver_path);
4443         test_sz("DriverDate",                   driver_date);
4444         test_sz("DriverVersion",                driver_version);
4445         test_sz("HardwareID",                   info.info8.hardware_id);
4446         test_sz("Help File",                    help_file);
4447         test_sz("InfPath",                      info.info8.inf_path);
4448         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4449         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4450         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4451         test_sz("Monitor",                      info.info8.monitor_name);
4452         test_sz("OEM URL",                      info.info8.manufacturer_url);
4453         test_sz("Print Processor",              info.info8.print_processor);
4454         test_sz("Provider",                     info.info8.provider);
4455         test_sz("VendorSetup",                  info.info8.vendor_setup);
4456         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4457         test_multi_sz("Dependent Files",        dependent_files);
4458         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4459         test_multi_sz("Previous Names",         info.info8.previous_names);
4460 /*      test_dword("Attributes",                ?); */
4461         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4462         test_dword("Version",                   info.info8.version);
4463 /*      test_dword("TempDir",                   ?); */
4464
4465  try_level6:
4466
4467         torture_assert(tctx,
4468                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4469                 "failed to get driver info level 6");
4470
4471         driver_path     = strip_path(info.info6.driver_path);
4472         data_file       = strip_path(info.info6.data_file);
4473         config_file     = strip_path(info.info6.config_file);
4474         help_file       = strip_path(info.info6.help_file);
4475         dependent_files = strip_paths(info.info6.dependent_files);
4476
4477         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4478
4479         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4480
4481         test_sz("Configuration File",           config_file);
4482         test_sz("Data File",                    data_file);
4483         test_sz("Datatype",                     info.info6.default_datatype);
4484         test_sz("Driver",                       driver_path);
4485         test_sz("DriverDate",                   driver_date);
4486         test_sz("DriverVersion",                driver_version);
4487         test_sz("HardwareID",                   info.info6.hardware_id);
4488         test_sz("Help File",                    help_file);
4489         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4490         test_sz("Monitor",                      info.info6.monitor_name);
4491         test_sz("OEM URL",                      info.info6.manufacturer_url);
4492         test_sz("Provider",                     info.info6.provider);
4493         test_multi_sz("Dependent Files",        dependent_files);
4494         test_multi_sz("Previous Names",         info.info6.previous_names);
4495 /*      test_dword("Attributes",                ?); */
4496         test_dword("Version",                   info.info6.version);
4497 /*      test_dword("TempDir",                   ?); */
4498
4499  try_level3:
4500
4501         torture_assert(tctx,
4502                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4503                 "failed to get driver info level 3");
4504
4505         driver_path     = strip_path(info.info3.driver_path);
4506         data_file       = strip_path(info.info3.data_file);
4507         config_file     = strip_path(info.info3.config_file);
4508         help_file       = strip_path(info.info3.help_file);
4509         dependent_files = strip_paths(info.info3.dependent_files);
4510
4511         test_sz("Configuration File",           config_file);
4512         test_sz("Data File",                    data_file);
4513         test_sz("Datatype",                     info.info3.default_datatype);
4514         test_sz("Driver",                       driver_path);
4515         test_sz("Help File",                    help_file);
4516         test_sz("Monitor",                      info.info3.monitor_name);
4517         test_multi_sz("Dependent Files",        dependent_files);
4518 /*      test_dword("Attributes",                ?); */
4519         test_dword("Version",                   info.info3.version);
4520 /*      test_dword("TempDir",                   ?); */
4521
4522
4523         torture_assert(tctx,
4524                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4525
4526         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4527
4528         return true;
4529 }
4530
4531 #undef test_sz
4532 #undef test_dword
4533
4534 static bool test_SetPrinterData(struct torture_context *tctx,
4535                                 struct dcerpc_binding_handle *b,
4536                                 struct policy_handle *handle,
4537                                 const char *value_name,
4538                                 enum winreg_Type type,
4539                                 uint8_t *data,
4540                                 uint32_t offered)
4541 {
4542         struct spoolss_SetPrinterData r;
4543
4544         r.in.handle = handle;
4545         r.in.value_name = value_name;
4546         r.in.type = type;
4547         r.in.data = data;
4548         r.in.offered = offered;
4549
4550         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4551                 r.in.value_name);
4552
4553         torture_assert_ntstatus_ok(tctx,
4554                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4555                 "SetPrinterData failed");
4556         torture_assert_werr_ok(tctx, r.out.result,
4557                 "SetPrinterData failed");
4558
4559         return true;
4560 }
4561
4562 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4563                                        struct dcerpc_binding_handle *b,
4564                                        struct policy_handle *handle,
4565                                        const char *printer_name,
4566                                        struct dcerpc_binding_handle *winreg_handle,
4567                                        struct policy_handle *hive_handle)
4568 {
4569         const char *values[] = {
4570                 "spootyfoot",
4571                 "spooty\\foot",
4572 #if 0
4573         /* FIXME: not working with s3 atm. */
4574                 "spooty,foot",
4575                 "spooty,fo,ot",
4576 #endif
4577                 "spooty foot",
4578 #if 0
4579         /* FIXME: not working with s3 atm. */
4580                 "spooty\\fo,ot",
4581                 "spooty,fo\\ot"
4582 #endif
4583         };
4584         int i;
4585
4586         for (i=0; i < ARRAY_SIZE(values); i++) {
4587
4588                 enum winreg_Type type;
4589                 DATA_BLOB blob;
4590                 uint8_t *data;
4591                 uint32_t needed;
4592
4593                 torture_assert(tctx,
4594                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4595                                           "REG_SZ", "dog", &type, &blob), "");
4596
4597                 torture_assert(tctx,
4598                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4599                         "SetPrinterData failed");
4600
4601                 torture_assert(tctx,
4602                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4603                         "GetPrinterData failed");
4604
4605                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4606                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4607                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4608
4609                 if (winreg_handle && hive_handle) {
4610
4611                         enum winreg_Type w_type;
4612                         uint32_t w_size;
4613                         uint32_t w_length;
4614                         uint8_t *w_data;
4615
4616                         torture_assert(tctx,
4617                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4618                                         printer_name, "PrinterDriverData", values[i],
4619                                         &w_type, &w_size, &w_length, &w_data), "");
4620
4621                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4622                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4623                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4624                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4625                 }
4626
4627                 torture_assert(tctx,
4628                         test_DeletePrinterData(tctx, b, handle, values[i]),
4629                         "DeletePrinterData failed");
4630         }
4631
4632         return true;
4633 }
4634
4635
4636 static bool test_EnumPrinterKey(struct torture_context *tctx,
4637                                 struct dcerpc_binding_handle *b,
4638                                 struct policy_handle *handle,
4639                                 const char *key_name,
4640                                 const char ***array);
4641
4642 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4643                                   struct dcerpc_binding_handle *b,
4644                                   struct policy_handle *handle,
4645                                   const char *key_name,
4646                                   const char *value_name,
4647                                   enum winreg_Type type,
4648                                   uint8_t *data,
4649                                   uint32_t offered)
4650 {
4651         NTSTATUS status;
4652         struct spoolss_SetPrinterDataEx r;
4653
4654         r.in.handle = handle;
4655         r.in.key_name = key_name;
4656         r.in.value_name = value_name;
4657         r.in.type = type;
4658         r.in.data = data;
4659         r.in.offered = offered;
4660
4661         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4662                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4663
4664         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4665
4666         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4667         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4668
4669         return true;
4670 }
4671
4672 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4673                                          struct dcerpc_pipe *p,
4674                                          struct policy_handle *handle,
4675                                          const char *printername,
4676                                          struct dcerpc_binding_handle *winreg_handle,
4677                                          struct policy_handle *hive_handle)
4678 {
4679         struct dcerpc_binding_handle *b = p->binding_handle;
4680         const char *value_name = "dog";
4681         const char *keys[] = {
4682                 "torturedataex",
4683                 "torture data ex",
4684 #if 0
4685         /* FIXME: not working with s3 atm. */
4686                 "torturedataex_with_subkey\\subkey",
4687                 "torturedataex_with_subkey\\subkey:0",
4688                 "torturedataex_with_subkey\\subkey:1",
4689                 "torturedataex_with_subkey\\subkey\\subsubkey",
4690                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4691                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4692 #endif
4693                 "torture,data",
4694 #if 0
4695         /* FIXME: not working with s3 atm. */
4696
4697                 "torture,data,ex",
4698                 "torture,data\\ex",
4699                 "torture\\data,ex"
4700 #endif
4701         };
4702         enum winreg_Type types[] = {
4703                 REG_SZ,
4704                 REG_MULTI_SZ,
4705                 REG_DWORD,
4706                 REG_BINARY
4707         };
4708         const char *str = "abcdefghijklmnopqrstuvwxzy";
4709         int i, t, s;
4710
4711
4712         for (i=0; i < ARRAY_SIZE(keys); i++) {
4713         for (t=0; t < ARRAY_SIZE(types); t++) {
4714         for (s=0; s < strlen(str); s++) {
4715
4716                 char *c;
4717                 const char *key;
4718                 enum winreg_Type type;
4719                 const char *string = talloc_strndup(tctx, str, s);
4720                 DATA_BLOB blob = data_blob_string_const(string);
4721                 const char **subkeys;
4722                 DATA_BLOB data;
4723                 uint8_t *data_out;
4724                 uint32_t needed, offered = 0;
4725                 uint32_t ecount;
4726                 struct spoolss_PrinterEnumValues *einfo;
4727
4728                 if (types[t] == REG_DWORD) {
4729                         s = 0xffff;
4730                 }
4731
4732                 if (torture_setting_bool(tctx, "samba3", false)) {
4733                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
4734                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4735                                 continue;
4736                         }
4737                 }
4738
4739                 switch (types[t]) {
4740                 case REG_BINARY:
4741                         data = blob;
4742                         offered = blob.length;
4743                         break;
4744                 case REG_DWORD:
4745                         data = data_blob_talloc(tctx, NULL, 4);
4746                         SIVAL(data.data, 0, 0x12345678);
4747                         offered = 4;
4748                         break;
4749                 case REG_SZ:
4750                         torture_assert(tctx,
4751                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4752                                                   "REG_SZ", string, &type, &data), "");
4753                         offered = data.length;
4754                         /*strlen_m_term(data.string)*2;*/
4755                         break;
4756                 case REG_MULTI_SZ:
4757                         torture_assert(tctx,
4758                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4759                                                   "REG_SZ", string, &type, &data), "");
4760                         torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
4761                         memset(&data.data[data.length - 2], '\0', 2);
4762                         offered = data.length;
4763                         break;
4764                 default:
4765                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4766                 }
4767
4768                 torture_assert(tctx,
4769                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4770                         "failed to call SetPrinterDataEx");
4771
4772                 torture_assert(tctx,
4773                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4774                         "failed to call GetPrinterDataEx");
4775
4776                 torture_assert(tctx,
4777                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4778                         "failed to call EnumPrinterDataEx");
4779
4780                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4781                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4782                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4783
4784                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4785                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4786                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4787                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4788                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4789                 if (einfo[0].data_length > 0) {
4790                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4791                 }
4792
4793                 if (winreg_handle && hive_handle) {
4794                         enum winreg_Type w_type;
4795                         uint32_t w_size;
4796                         uint32_t w_length;
4797                         uint8_t *w_data;
4798
4799                         torture_assert(tctx,
4800                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4801                                         printername, keys[i], value_name,
4802                                         &w_type, &w_size, &w_length, &w_data), "");
4803
4804                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4805                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4806                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4807                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4808                 }
4809
4810                 key = talloc_strdup(tctx, keys[i]);
4811
4812                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4813                         return false;
4814                 }
4815
4816                 c = strchr(key, '\\');
4817                 if (c) {
4818                         int k;
4819
4820                         /* we have subkeys */
4821
4822                         *c = 0;
4823
4824                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4825                                 return false;
4826                         }
4827
4828                         for (k=0; subkeys && subkeys[k]; k++) {
4829
4830                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4831
4832                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4833                                         return false;
4834                                 }
4835                         }
4836
4837                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4838                                 return false;
4839                         }
4840
4841                 } else {
4842                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4843                                 return false;
4844                         }
4845                 }
4846         }
4847         }
4848         }
4849
4850         return true;
4851 }
4852
4853 static bool test_PrinterData_winreg(struct torture_context *tctx,
4854                                     struct dcerpc_pipe *p,
4855                                     struct policy_handle *handle,
4856                                     const char *printer_name)
4857 {
4858         struct dcerpc_binding_handle *b = p->binding_handle;
4859         struct dcerpc_pipe *p2;
4860         bool ret = true;
4861         struct policy_handle hive_handle;
4862         struct dcerpc_binding_handle *b2;
4863
4864         torture_assert_ntstatus_ok(tctx,
4865                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4866                 "could not open winreg pipe");
4867         b2 = p2->binding_handle;
4868
4869         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4870
4871         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4872         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4873
4874         test_winreg_CloseKey(tctx, b2, &hive_handle);
4875
4876         talloc_free(p2);
4877
4878         return ret;
4879 }
4880
4881 static bool test_Forms_winreg(struct torture_context *tctx,
4882                               struct dcerpc_binding_handle *b,
4883                               struct policy_handle *handle,
4884                               bool print_server,
4885                               const char *printer_name)
4886 {
4887         struct dcerpc_pipe *p2;
4888         bool ret = true;
4889         struct policy_handle hive_handle;
4890         struct dcerpc_binding_handle *b2;
4891
4892         torture_assert_ntstatus_ok(tctx,
4893                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4894                 "could not open winreg pipe");
4895         b2 = p2->binding_handle;
4896
4897         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4898
4899         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4900
4901         test_winreg_CloseKey(tctx, b2, &hive_handle);
4902
4903         talloc_free(p2);
4904
4905         return ret;
4906 }
4907
4908 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
4909                                     struct dcerpc_pipe *p,
4910                                     struct policy_handle *handle,
4911                                     const char *printer_name)
4912 {
4913         struct dcerpc_binding_handle *b = p->binding_handle;
4914         struct dcerpc_pipe *p2;
4915         bool ret = true;
4916         struct policy_handle hive_handle;
4917         struct dcerpc_binding_handle *b2;
4918
4919         torture_assert_ntstatus_ok(tctx,
4920                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4921                 "could not open winreg pipe");
4922         b2 = p2->binding_handle;
4923
4924         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4925
4926         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
4927
4928         test_winreg_CloseKey(tctx, b2, &hive_handle);
4929
4930         talloc_free(p2);
4931
4932         return ret;
4933 }
4934
4935 static bool test_DriverInfo_winreg(struct torture_context *tctx,
4936                                    struct dcerpc_pipe *p,
4937                                    struct policy_handle *handle,
4938                                    const char *printer_name,
4939                                    const char *driver_name,
4940                                    const char *environment)
4941 {
4942         struct dcerpc_binding_handle *b = p->binding_handle;
4943         struct dcerpc_pipe *p2;
4944         bool ret = true;
4945         struct policy_handle hive_handle;
4946         struct dcerpc_binding_handle *b2;
4947
4948         torture_assert_ntstatus_ok(tctx,
4949                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4950                 "could not open winreg pipe");
4951         b2 = p2->binding_handle;
4952
4953         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4954
4955         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
4956
4957         test_winreg_CloseKey(tctx, b2, &hive_handle);
4958
4959         talloc_free(p2);
4960
4961         return ret;
4962 }
4963
4964 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
4965                                        struct dcerpc_pipe *p,
4966                                        struct policy_handle *handle,
4967                                        const char *printer_name)
4968 {
4969         struct spoolss_SetPrinterInfoCtr info_ctr;
4970         struct spoolss_DevmodeContainer devmode_ctr;
4971         struct sec_desc_buf secdesc_ctr;
4972         union spoolss_SetPrinterInfo sinfo;
4973         union spoolss_PrinterInfo info;
4974         struct dcerpc_binding_handle *b = p->binding_handle;
4975
4976         ZERO_STRUCT(info_ctr);
4977         ZERO_STRUCT(devmode_ctr);
4978         ZERO_STRUCT(secdesc_ctr);
4979
4980         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
4981
4982         torture_assert(tctx,
4983                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4984                 "failed to query Printer level 2");
4985
4986         torture_assert(tctx,
4987                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
4988                 "failed to convert");
4989
4990         info_ctr.level = 2;
4991         info_ctr.info = sinfo;
4992
4993 #define TEST_SZ(wname, iname) \
4994 do {\
4995         enum winreg_Type type;\
4996         uint8_t *data;\
4997         uint32_t needed;\
4998         DATA_BLOB blob;\
4999         const char *str;\
5000         torture_assert(tctx,\
5001                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5002                 "failed to query");\
5003         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5004         blob = data_blob_const(data, needed);\
5005         torture_assert(tctx,\
5006                 pull_reg_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &str),\
5007                 "failed to pull REG_SZ");\
5008         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5009 } while(0);
5010
5011
5012 #define TEST_SET_SZ(wname, iname, val) \
5013 do {\
5014         enum winreg_Type type;\
5015         uint8_t *data;\
5016         uint32_t needed;\
5017         DATA_BLOB blob;\
5018         const char *str;\
5019         sinfo.info2->iname = val;\
5020         torture_assert(tctx,\
5021                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5022                 "failed to call SetPrinter");\
5023         torture_assert(tctx,\
5024                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5025                 "failed to query");\
5026         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5027         blob = data_blob_const(data, needed);\
5028         torture_assert(tctx,\
5029                 pull_reg_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &str),\
5030                 "failed to pull REG_SZ");\
5031         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5032 } while(0);
5033
5034 #define TEST_SET_DWORD(wname, iname, val) \
5035 do {\
5036         enum winreg_Type type;\
5037         uint8_t *data;\
5038         uint32_t needed;\
5039         uint32_t value;\
5040         sinfo.info2->iname = val;\
5041         torture_assert(tctx,\
5042                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5043                 "failed to call SetPrinter");\
5044         torture_assert(tctx,\
5045                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5046                 "failed to query");\
5047         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5048         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5049         value = IVAL(data, 0); \
5050         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5051 } while(0);
5052
5053         TEST_SET_SZ("description", comment, "newval");
5054         TEST_SET_SZ("location", location, "newval");
5055 /*      TEST_SET_DWORD("priority", priority, 25); */
5056
5057         torture_assert(tctx,
5058                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5059                 "failed to query Printer level 2");
5060
5061         TEST_SZ("description", info.info2.comment);
5062         TEST_SZ("driverName", info.info2.drivername);
5063         TEST_SZ("location", info.info2.location);
5064         TEST_SZ("printerName", info.info2.printername);
5065         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5066         /* TEST_SZ("printShareName", info.info2.sharename); */
5067
5068         /* FIXME gd: complete the list */
5069
5070 #undef TEST_SZ
5071 #undef TEST_SET_SZ
5072 #undef TEST_DWORD
5073
5074         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5075
5076         return true;
5077 }
5078
5079 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5080                                          struct dcerpc_binding_handle *b,
5081                                          struct policy_handle *handle,
5082                                          uint32_t *change_id)
5083 {
5084         enum winreg_Type type;
5085         uint8_t *data;
5086         uint32_t needed;
5087
5088         torture_assert(tctx,
5089                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5090                 "failed to call GetPrinterData");
5091
5092         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5093         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5094
5095         *change_id = IVAL(data, 0);
5096
5097         return true;
5098 }
5099
5100 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5101                                            struct dcerpc_pipe *p,
5102                                            struct policy_handle *handle,
5103                                            uint32_t *change_id)
5104 {
5105         enum winreg_Type type;
5106         uint8_t *data;
5107         uint32_t needed;
5108
5109         torture_assert(tctx,
5110                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5111                 "failed to call GetPrinterData");
5112
5113         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5114         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5115
5116         *change_id = IVAL(data, 0);
5117
5118         return true;
5119 }
5120
5121 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5122                                          struct dcerpc_binding_handle *b,
5123                                          struct policy_handle *handle,
5124                                          uint32_t *change_id)
5125 {
5126         union spoolss_PrinterInfo info;
5127
5128         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5129                 "failed to query Printer level 0");
5130
5131         *change_id = info.info0.change_id;
5132
5133         return true;
5134 }
5135
5136 static bool test_ChangeID(struct torture_context *tctx,
5137                           struct dcerpc_pipe *p,
5138                           struct policy_handle *handle)
5139 {
5140         uint32_t change_id, change_id_ex, change_id_info;
5141         uint32_t change_id2, change_id_ex2, change_id_info2;
5142         union spoolss_PrinterInfo info;
5143         const char *comment;
5144         struct dcerpc_binding_handle *b = p->binding_handle;
5145
5146         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5147
5148         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5149                 "failed to query for ChangeID");
5150         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5151                 "failed to query for ChangeID");
5152         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5153                 "failed to query for ChangeID");
5154
5155         torture_assert_int_equal(tctx, change_id, change_id_ex,
5156                 "change_ids should all be equal");
5157         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5158                 "change_ids should all be equal");
5159
5160
5161         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5162
5163         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5164                 "failed to query for ChangeID");
5165         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5166                 "failed to query Printer level 2");
5167         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5168                 "failed to query for ChangeID");
5169         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5170                 "failed to query for ChangeID");
5171         torture_assert_int_equal(tctx, change_id, change_id_ex,
5172                 "change_id should not have changed");
5173         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5174                 "change_id should not have changed");
5175
5176
5177         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5178
5179         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5180                 "failed to query for ChangeID");
5181         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5182                 "failed to query for ChangeID");
5183         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5184                 "failed to query for ChangeID");
5185         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5186                 "failed to query Printer level 2");
5187         comment = talloc_strdup(tctx, info.info2.comment);
5188
5189         {
5190                 struct spoolss_SetPrinterInfoCtr info_ctr;
5191                 struct spoolss_DevmodeContainer devmode_ctr;
5192                 struct sec_desc_buf secdesc_ctr;
5193                 union spoolss_SetPrinterInfo sinfo;
5194
5195                 ZERO_STRUCT(info_ctr);
5196                 ZERO_STRUCT(devmode_ctr);
5197                 ZERO_STRUCT(secdesc_ctr);
5198
5199
5200                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5201                 sinfo.info2->comment    = "torture_comment";
5202
5203                 info_ctr.level = 2;
5204                 info_ctr.info = sinfo;
5205
5206                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5207                         "failed to call SetPrinter");
5208
5209                 sinfo.info2->comment    = comment;
5210
5211                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5212                         "failed to call SetPrinter");
5213
5214         }
5215
5216         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5217                 "failed to query for ChangeID");
5218         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5219                 "failed to query for ChangeID");
5220         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5221                 "failed to query for ChangeID");
5222
5223         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5224                 "change_ids should all be equal");
5225         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5226                 "change_ids should all be equal");
5227
5228         torture_assert(tctx, (change_id < change_id2),
5229                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5230                 change_id2, change_id));
5231         torture_assert(tctx, (change_id_ex < change_id_ex2),
5232                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5233                 change_id_ex2, change_id_ex));
5234         torture_assert(tctx, (change_id_info < change_id_info2),
5235                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5236                 change_id_info2, change_id_info));
5237
5238         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5239
5240         return true;
5241 }
5242
5243 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5244                                        struct dcerpc_pipe *p,
5245                                        struct policy_handle *handle)
5246 {
5247         NTSTATUS status;
5248         struct dcerpc_binding *b;
5249         struct dcerpc_pipe *p2;
5250         struct spoolss_ClosePrinter cp;
5251
5252         /* only makes sense on SMB */
5253         if (p->conn->transport.transport != NCACN_NP) {
5254                 return true;
5255         }
5256
5257         torture_comment(tctx, "Testing close on secondary pipe\n");
5258
5259         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5260         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5261
5262         status = dcerpc_secondary_connection(p, &p2, b);
5263         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5264
5265         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5266         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5267
5268         cp.in.handle = handle;
5269         cp.out.handle = handle;
5270
5271         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5272         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5273                         "ERROR: Allowed close on secondary connection");
5274
5275         talloc_free(p2);
5276
5277         return true;
5278 }
5279
5280 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5281                                      struct dcerpc_binding_handle *b, const char *name)
5282 {
5283         NTSTATUS status;
5284         struct spoolss_OpenPrinter op;
5285         struct spoolss_OpenPrinterEx opEx;
5286         struct policy_handle handle;
5287         bool ret = true;
5288
5289         op.in.printername       = name;
5290         op.in.datatype          = NULL;
5291         op.in.devmode_ctr.devmode= NULL;
5292         op.in.access_mask       = 0;
5293         op.out.handle           = &handle;
5294
5295         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5296
5297         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5298         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5299         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5300                 "unexpected result");
5301
5302         if (W_ERROR_IS_OK(op.out.result)) {
5303                 ret &=test_ClosePrinter(tctx, b, &handle);
5304         }
5305
5306         opEx.in.printername             = name;
5307         opEx.in.datatype                = NULL;
5308         opEx.in.devmode_ctr.devmode     = NULL;
5309         opEx.in.access_mask             = 0;
5310         opEx.in.level                   = 1;
5311         opEx.in.userlevel.level1        = NULL;
5312         opEx.out.handle                 = &handle;
5313
5314         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5315
5316         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5317         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5318         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5319                 "unexpected result");
5320
5321         if (W_ERROR_IS_OK(opEx.out.result)) {
5322                 ret &=test_ClosePrinter(tctx, b, &handle);
5323         }
5324
5325         return ret;
5326 }
5327
5328 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5329                                           struct dcerpc_binding_handle *b,
5330                                           const char *server_name)
5331 {
5332         const char *badnames[] = {
5333                 "__INVALID_PRINTER__",
5334                 "\\\\__INVALID_HOST__",
5335                 "",
5336                 "\\\\\\",
5337                 "\\\\\\__INVALID_PRINTER__"
5338         };
5339         const char *badname;
5340         int i;
5341
5342         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5343                 torture_assert(tctx,
5344                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5345                         "");
5346         }
5347
5348         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5349         torture_assert(tctx,
5350                 test_OpenPrinter_badname(tctx, b, badname),
5351                 "");
5352
5353         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5354         torture_assert(tctx,
5355                 test_OpenPrinter_badname(tctx, b, badname),
5356                 "");
5357
5358         return true;
5359 }
5360
5361 static bool test_OpenPrinter(struct torture_context *tctx,
5362                              struct dcerpc_pipe *p,
5363                              const char *name,
5364                              const char *environment)
5365 {
5366         NTSTATUS status;
5367         struct spoolss_OpenPrinter r;
5368         struct policy_handle handle;
5369         bool ret = true;
5370         struct dcerpc_binding_handle *b = p->binding_handle;
5371
5372         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5373         r.in.datatype           = NULL;
5374         r.in.devmode_ctr.devmode= NULL;
5375         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5376         r.out.handle            = &handle;
5377
5378         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5379
5380         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5381
5382         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5383
5384         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5385
5386         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5387                 ret = false;
5388         }
5389
5390         if (!torture_setting_bool(tctx, "samba3", false)) {
5391                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5392                         ret = false;
5393                 }
5394         }
5395
5396         if (!test_ClosePrinter(tctx, b, &handle)) {
5397                 ret = false;
5398         }
5399
5400         return ret;
5401 }
5402
5403 static bool call_OpenPrinterEx(struct torture_context *tctx,
5404                                struct dcerpc_pipe *p,
5405                                const char *name,
5406                                struct spoolss_DeviceMode *devmode,
5407                                struct policy_handle *handle)
5408 {
5409         struct spoolss_OpenPrinterEx r;
5410         struct spoolss_UserLevel1 userlevel1;
5411         NTSTATUS status;
5412         struct dcerpc_binding_handle *b = p->binding_handle;
5413
5414         if (name && name[0]) {
5415                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5416                                                    dcerpc_server_name(p), name);
5417         } else {
5418                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5419                                                    dcerpc_server_name(p));
5420         }
5421
5422         r.in.datatype           = NULL;
5423         r.in.devmode_ctr.devmode= devmode;
5424         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5425         r.in.level              = 1;
5426         r.in.userlevel.level1   = &userlevel1;
5427         r.out.handle = handle;
5428
5429         userlevel1.size = 1234;
5430         userlevel1.client = "hello";
5431         userlevel1.user = "spottyfoot!";
5432         userlevel1.build = 1;
5433         userlevel1.major = 2;
5434         userlevel1.minor = 3;
5435         userlevel1.processor = 4;
5436
5437         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5438
5439         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5440
5441         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5442
5443         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5444
5445         return true;
5446 }
5447
5448 static bool test_printer_rename(struct torture_context *tctx,
5449                                 struct dcerpc_pipe *p,
5450                                 struct policy_handle *handle,
5451                                 const char *name)
5452 {
5453         bool ret = true;
5454         union spoolss_PrinterInfo info;
5455         union spoolss_SetPrinterInfo sinfo;
5456         struct spoolss_SetPrinterInfoCtr info_ctr;
5457         struct spoolss_DevmodeContainer devmode_ctr;
5458         struct sec_desc_buf secdesc_ctr;
5459         const char *printer_name;
5460         const char *printer_name_orig;
5461         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5462         struct policy_handle new_handle;
5463         const char *q;
5464         struct dcerpc_binding_handle *b = p->binding_handle;
5465
5466         ZERO_STRUCT(devmode_ctr);
5467         ZERO_STRUCT(secdesc_ctr);
5468
5469         torture_comment(tctx, "Testing Printer rename operations\n");
5470
5471         torture_assert(tctx,
5472                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5473                 "failed to call GetPrinter level 2");
5474
5475         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5476
5477         q = strrchr(info.info2.printername, '\\');
5478         if (q) {
5479                 torture_warning(tctx,
5480                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5481         }
5482
5483         torture_assert(tctx,
5484                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5485
5486         sinfo.info2->printername = printer_name_new;
5487
5488         info_ctr.level = 2;
5489         info_ctr.info = sinfo;
5490
5491         torture_assert(tctx,
5492                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5493                 "failed to call SetPrinter level 2");
5494
5495         torture_assert(tctx,
5496                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5497                 "failed to call GetPrinter level 2");
5498
5499         printer_name = talloc_strdup(tctx, info.info2.printername);
5500
5501         q = strrchr(info.info2.printername, '\\');
5502         if (q) {
5503                 torture_warning(tctx,
5504                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5505                 q++;
5506                 printer_name = q;
5507         }
5508
5509         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5510                 "new printer name was not set");
5511
5512         /* samba currently cannot fully rename printers */
5513         if (!torture_setting_bool(tctx, "samba3", false)) {
5514                 torture_assert(tctx,
5515                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5516                         "still can open printer with oldname after rename");
5517         } else {
5518                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5519         }
5520
5521         torture_assert(tctx,
5522                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5523                 "failed to open printer with new name");
5524
5525         torture_assert(tctx,
5526                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5527                 "failed to call GetPrinter level 2");
5528
5529         /* FIXME: we openend with servername! */
5530         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5531                 dcerpc_server_name(p), printer_name_new);
5532
5533         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5534                 "new printer name was not set");
5535
5536         torture_assert(tctx,
5537                 test_ClosePrinter(tctx, b, &new_handle),
5538                 "failed to close printer");
5539
5540         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5541
5542         return ret;
5543 }
5544
5545
5546 static bool test_OpenPrinterEx(struct torture_context *tctx,
5547                                struct dcerpc_pipe *p,
5548                                const char *name,
5549                                const char *environment)
5550 {
5551         struct policy_handle handle;
5552         bool ret = true;
5553         struct dcerpc_binding_handle *b = p->binding_handle;
5554
5555         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5556                 return false;
5557         }
5558
5559         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5560                 ret = false;
5561         }
5562
5563         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5564                 ret = false;
5565         }
5566
5567         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5568                 ret = false;
5569         }
5570
5571         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5572                 ret = false;
5573         }
5574
5575         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5576                 ret = false;
5577         }
5578
5579         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5580                 ret = false;
5581         }
5582
5583         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5584                 ret = false;
5585         }
5586
5587         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5588                 ret = false;
5589         }
5590
5591         if (!test_printer_keys(tctx, b, &handle)) {
5592                 ret = false;
5593         }
5594
5595         if (!test_PausePrinter(tctx, b, &handle)) {
5596                 ret = false;
5597         }
5598
5599         if (!test_DoPrintTest(tctx, b, &handle)) {
5600                 ret = false;
5601         }
5602
5603         if (!test_ResumePrinter(tctx, b, &handle)) {
5604                 ret = false;
5605         }
5606
5607         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5608                 ret = false;
5609         }
5610
5611         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5612                 ret = false;
5613         }
5614
5615         if (!torture_setting_bool(tctx, "samba3", false)) {
5616                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5617                         ret = false;
5618                 }
5619         }
5620
5621         if (!test_ClosePrinter(tctx, b, &handle)) {
5622                 ret = false;
5623         }
5624
5625         return ret;
5626 }
5627
5628 static bool test_EnumPrinters_old(struct torture_context *tctx,
5629                                   struct dcerpc_pipe *p,
5630                                   const char *environment)
5631 {
5632         struct spoolss_EnumPrinters r;
5633         NTSTATUS status;
5634         uint16_t levels[] = {1, 2, 4, 5};
5635         int i;
5636         bool ret = true;
5637         struct dcerpc_binding_handle *b = p->binding_handle;
5638
5639         for (i=0;i<ARRAY_SIZE(levels);i++) {
5640                 union spoolss_PrinterInfo *info;
5641                 int j;
5642                 uint32_t needed;
5643                 uint32_t count;
5644
5645                 r.in.flags      = PRINTER_ENUM_LOCAL;
5646                 r.in.server     = "";
5647                 r.in.level      = levels[i];
5648                 r.in.buffer     = NULL;
5649                 r.in.offered    = 0;
5650                 r.out.needed    = &needed;
5651                 r.out.count     = &count;
5652                 r.out.info      = &info;
5653
5654                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5655
5656                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5657                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5658
5659                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5660                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5661                         r.in.buffer = &blob;
5662                         r.in.offered = needed;
5663                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5664                 }
5665
5666                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5667
5668                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5669
5670                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5671
5672                 if (!info) {
5673                         torture_comment(tctx, "No printers returned\n");
5674                         return true;
5675                 }
5676
5677                 for (j=0;j<count;j++) {
5678                         if (r.in.level == 1) {
5679                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5680                                 char *slash, *name;
5681                                 name = unc;
5682                                 if (unc[0] == '\\' && unc[1] == '\\') {
5683                                         unc +=2;
5684                                 }
5685                                 slash = strchr(unc, '\\');
5686                                 if (slash) {
5687                                         slash++;
5688                                         name = slash;
5689                                 }
5690                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
5691                                         ret = false;
5692                                 }
5693                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
5694                                         ret = false;
5695                                 }
5696                         }
5697                 }
5698         }
5699
5700         return ret;
5701 }
5702
5703 static bool test_GetPrinterDriver(struct torture_context *tctx,
5704                                   struct dcerpc_binding_handle *b,
5705                                   struct policy_handle *handle,
5706                                   const char *driver_name)
5707 {
5708         struct spoolss_GetPrinterDriver r;
5709         uint32_t needed;
5710
5711         r.in.handle = handle;
5712         r.in.architecture = "W32X86";
5713         r.in.level = 1;
5714         r.in.buffer = NULL;
5715         r.in.offered = 0;
5716         r.out.needed = &needed;
5717
5718         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5719
5720         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5721                 "failed to call GetPrinterDriver");
5722         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5723                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5724                 r.in.buffer = &blob;
5725                 r.in.offered = needed;
5726                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5727                         "failed to call GetPrinterDriver");
5728         }
5729
5730         torture_assert_werr_ok(tctx, r.out.result,
5731                 "failed to call GetPrinterDriver");
5732
5733         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5734
5735         return true;
5736 }
5737
5738 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5739                                          struct dcerpc_binding_handle *b,
5740                                          struct policy_handle *handle,
5741                                          const char *driver_name,
5742                                          const char *architecture,
5743                                          uint32_t level,
5744                                          uint32_t client_major_version,
5745                                          uint32_t client_minor_version,
5746                                          union spoolss_DriverInfo *info_p,
5747                                          WERROR *result_p)
5748
5749 {
5750         struct spoolss_GetPrinterDriver2 r;
5751         uint32_t needed;
5752         uint32_t server_major_version;
5753         uint32_t server_minor_version;
5754
5755         r.in.handle = handle;
5756         r.in.architecture = architecture;
5757         r.in.client_major_version = client_major_version;
5758         r.in.client_minor_version = client_minor_version;
5759         r.in.buffer = NULL;
5760         r.in.offered = 0;
5761         r.in.level = level;
5762         r.out.needed = &needed;
5763         r.out.server_major_version = &server_major_version;
5764         r.out.server_minor_version = &server_minor_version;
5765
5766         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5767                 driver_name, r.in.level);
5768
5769         torture_assert_ntstatus_ok(tctx,
5770                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5771                 "failed to call GetPrinterDriver2");
5772         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5773                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5774                 r.in.buffer = &blob;
5775                 r.in.offered = needed;
5776                 torture_assert_ntstatus_ok(tctx,
5777                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5778                         "failed to call GetPrinterDriver2");
5779         }
5780
5781         if (result_p) {
5782                 *result_p = r.out.result;
5783         }
5784
5785         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5786                 switch (r.in.level) {
5787                 case 101:
5788                 case 8:
5789                         torture_comment(tctx,
5790                                 "level %d not implemented, not considering as an error\n",
5791                                 r.in.level);
5792                         return true;
5793                 default:
5794                         break;
5795                 }
5796         }
5797
5798         torture_assert_werr_ok(tctx, r.out.result,
5799                 "failed to call GetPrinterDriver2");
5800
5801         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5802
5803         if (info_p) {
5804                 *info_p = *r.out.info;
5805         }
5806
5807         return true;
5808 }
5809
5810 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5811                                    struct dcerpc_binding_handle *b,
5812                                    struct policy_handle *handle,
5813                                    const char *driver_name,
5814                                    const char *architecture)
5815 {
5816         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5817         int i;
5818
5819
5820         for (i=0;i<ARRAY_SIZE(levels);i++) {
5821
5822                 torture_assert(tctx,
5823                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
5824                         "");
5825         }
5826
5827         return true;
5828 }
5829
5830 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
5831                                         struct dcerpc_pipe *p,
5832                                         const char *environment)
5833 {
5834         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
5835         int i;
5836         struct dcerpc_binding_handle *b = p->binding_handle;
5837         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5838
5839         for (i=0;i<ARRAY_SIZE(levels);i++) {
5840
5841                 uint32_t count;
5842                 union spoolss_DriverInfo *info;
5843
5844                 torture_assert(tctx,
5845                         test_EnumPrinterDrivers_args(tctx, b, server_name, environment, levels[i], &count, &info),
5846                         "failed to enumerate drivers");
5847
5848                 if (!info) {
5849                         torture_comment(tctx, "No printer drivers returned\n");
5850                         break;
5851                 }
5852         }
5853
5854         return true;
5855 }
5856
5857 static bool test_DeletePrinter(struct torture_context *tctx,
5858                                struct dcerpc_binding_handle *b,
5859                                struct policy_handle *handle)
5860 {
5861         struct spoolss_DeletePrinter r;
5862
5863         torture_comment(tctx, "Testing DeletePrinter\n");
5864
5865         r.in.handle = handle;
5866
5867         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
5868                 "failed to delete printer");
5869         torture_assert_werr_ok(tctx, r.out.result,
5870                 "failed to delete printer");
5871
5872         return true;
5873 }
5874
5875 static bool test_EnumPrinters_findname(struct torture_context *tctx,
5876                                        struct dcerpc_binding_handle *b,
5877                                        uint32_t flags,
5878                                        uint32_t level,
5879                                        const char *name,
5880                                        bool *found)
5881 {
5882         struct spoolss_EnumPrinters e;
5883         uint32_t count;
5884         union spoolss_PrinterInfo *info;
5885         uint32_t needed;
5886         int i;
5887
5888         *found = false;
5889
5890         e.in.flags = flags;
5891         e.in.server = NULL;
5892         e.in.level = level;
5893         e.in.buffer = NULL;
5894         e.in.offered = 0;
5895         e.out.count = &count;
5896         e.out.info = &info;
5897         e.out.needed = &needed;
5898
5899         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5900                 "failed to enum printers");
5901
5902         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
5903                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5904                 e.in.buffer = &blob;
5905                 e.in.offered = needed;
5906
5907                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5908                         "failed to enum printers");
5909         }
5910
5911         torture_assert_werr_ok(tctx, e.out.result,
5912                 "failed to enum printers");
5913
5914         for (i=0; i < count; i++) {
5915
5916                 const char *current = NULL;
5917                 const char *q;
5918
5919                 switch (level) {
5920                 case 1:
5921                         current = info[i].info1.name;
5922                         break;
5923                 }
5924
5925                 if (strequal(current, name)) {
5926                         *found = true;
5927                         break;
5928                 }
5929
5930                 q = strrchr(current, '\\');
5931                 if (q) {
5932                         if (!e.in.server) {
5933                                 torture_warning(tctx,
5934                                         "server returns printername %s incl. servername although we did not set servername", current);
5935                         }
5936                         q++;
5937                         if (strequal(q, name)) {
5938                                 *found = true;
5939                                 break;
5940                         }
5941                 }
5942         }
5943
5944         return true;
5945 }
5946
5947 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5948                                       struct dcerpc_pipe *p,
5949                                       const char *printername,
5950                                       bool ex)
5951 {
5952         WERROR result;
5953         struct spoolss_AddPrinter r;
5954         struct spoolss_AddPrinterEx rex;
5955         struct spoolss_SetPrinterInfoCtr info_ctr;
5956         struct spoolss_SetPrinterInfo1 info1;
5957         struct spoolss_DevmodeContainer devmode_ctr;
5958         struct sec_desc_buf secdesc_ctr;
5959         struct spoolss_UserLevelCtr userlevel_ctr;
5960         struct policy_handle handle;
5961         bool found = false;
5962         struct dcerpc_binding_handle *b = p->binding_handle;
5963
5964         ZERO_STRUCT(devmode_ctr);
5965         ZERO_STRUCT(secdesc_ctr);
5966         ZERO_STRUCT(userlevel_ctr);
5967         ZERO_STRUCT(info1);
5968
5969         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5970
5971         /* try to add printer to wellknown printer list (level 1) */
5972
5973         userlevel_ctr.level = 1;
5974
5975         info_ctr.info.info1 = &info1;
5976         info_ctr.level = 1;
5977
5978         rex.in.server = NULL;
5979         rex.in.info_ctr = &info_ctr;
5980         rex.in.devmode_ctr = &devmode_ctr;
5981         rex.in.secdesc_ctr = &secdesc_ctr;
5982         rex.in.userlevel_ctr = &userlevel_ctr;
5983         rex.out.handle = &handle;
5984
5985         r.in.server = NULL;
5986         r.in.info_ctr = &info_ctr;
5987         r.in.devmode_ctr = &devmode_ctr;
5988         r.in.secdesc_ctr = &secdesc_ctr;
5989         r.out.handle = &handle;
5990
5991         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5992                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5993                 "failed to add printer");
5994         result = ex ? rex.out.result : r.out.result;
5995         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5996                 "unexpected result code");
5997
5998         info1.name = printername;
5999         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6000
6001         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6002                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6003                 "failed to add printer");
6004         result = ex ? rex.out.result : r.out.result;
6005         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6006                 "unexpected result code");
6007
6008         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6009            better do a real check to see the printer is really there */
6010
6011         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6012                                                         PRINTER_ENUM_NETWORK, 1,
6013                                                         printername,
6014                                                         &found),
6015                         "failed to enum printers");
6016
6017         torture_assert(tctx, found, "failed to find newly added printer");
6018
6019         info1.flags = 0;
6020
6021         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6022                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6023                 "failed to add printer");
6024         result = ex ? rex.out.result : r.out.result;
6025         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6026                 "unexpected result code");
6027
6028         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6029            better do a real check to see the printer has really been removed
6030            from the well known printer list */
6031
6032         found = false;
6033
6034         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6035                                                         PRINTER_ENUM_NETWORK, 1,
6036                                                         printername,
6037                                                         &found),
6038                         "failed to enum printers");
6039 #if 0
6040         torture_assert(tctx, !found, "printer still in well known printer list");
6041 #endif
6042         return true;
6043 }
6044
6045 static bool test_AddPrinter_normal(struct torture_context *tctx,
6046                                    struct dcerpc_pipe *p,
6047                                    struct policy_handle *handle_p,
6048                                    const char *printername,
6049                                    const char *drivername,
6050                                    const char *portname,
6051                                    struct spoolss_DeviceMode *devmode,
6052                                    bool ex)
6053 {
6054         WERROR result;
6055         struct spoolss_AddPrinter r;
6056         struct spoolss_AddPrinterEx rex;
6057         struct spoolss_SetPrinterInfoCtr info_ctr;
6058         struct spoolss_SetPrinterInfo2 info2;
6059         struct spoolss_DevmodeContainer devmode_ctr;
6060         struct sec_desc_buf secdesc_ctr;
6061         struct spoolss_UserLevelCtr userlevel_ctr;
6062         struct policy_handle handle;
6063         bool found = false;
6064         bool existing_printer_deleted = false;
6065         struct dcerpc_binding_handle *b = p->binding_handle;
6066
6067         ZERO_STRUCT(devmode_ctr);
6068         ZERO_STRUCT(secdesc_ctr);
6069         ZERO_STRUCT(userlevel_ctr);
6070
6071         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
6072
6073         devmode_ctr.devmode = devmode;
6074
6075         userlevel_ctr.level = 1;
6076
6077         rex.in.server = NULL;
6078         rex.in.info_ctr = &info_ctr;
6079         rex.in.devmode_ctr = &devmode_ctr;
6080         rex.in.secdesc_ctr = &secdesc_ctr;
6081         rex.in.userlevel_ctr = &userlevel_ctr;
6082         rex.out.handle = &handle;
6083
6084         r.in.server = NULL;
6085         r.in.info_ctr = &info_ctr;
6086         r.in.devmode_ctr = &devmode_ctr;
6087         r.in.secdesc_ctr = &secdesc_ctr;
6088         r.out.handle = &handle;
6089
6090  again:
6091
6092         /* try to add printer to printer list (level 2) */
6093
6094         ZERO_STRUCT(info2);
6095
6096         info_ctr.info.info2 = &info2;
6097         info_ctr.level = 2;
6098
6099         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6100                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6101                 "failed to add printer");
6102         result = ex ? rex.out.result : r.out.result;
6103         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6104                 "unexpected result code");
6105
6106         info2.printername = printername;
6107
6108         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6109                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6110                 "failed to add printer");
6111         result = ex ? rex.out.result : r.out.result;
6112
6113         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6114                 struct policy_handle printer_handle;
6115
6116                 if (existing_printer_deleted) {
6117                         torture_fail(tctx, "already deleted printer still existing?");
6118                 }
6119
6120                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6121                         "failed to open printer handle");
6122
6123                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6124                         "failed to delete printer");
6125
6126                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6127                         "failed to close server handle");
6128
6129                 existing_printer_deleted = true;
6130
6131                 goto again;
6132         }
6133
6134         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6135                 "unexpected result code");
6136
6137         info2.portname = portname;
6138
6139         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6140                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6141                 "failed to add printer");
6142         result = ex ? rex.out.result : r.out.result;
6143         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6144                 "unexpected result code");
6145
6146         info2.drivername = drivername;
6147
6148         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6149                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6150                 "failed to add printer");
6151         result = ex ? rex.out.result : r.out.result;
6152
6153         /* w2k8r2 allows to add printer w/o defining printprocessor */
6154
6155         if (!W_ERROR_IS_OK(result)) {
6156                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6157                         "unexpected result code");
6158
6159                 info2.printprocessor = "winprint";
6160
6161                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6162                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6163                         "failed to add printer");
6164                 result = ex ? rex.out.result : r.out.result;
6165                 torture_assert_werr_ok(tctx, result,
6166                         "failed to add printer");
6167         }
6168
6169         *handle_p = handle;
6170
6171         /* we are paranoid, really check if the printer is there now */
6172
6173         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6174                                                         PRINTER_ENUM_LOCAL, 1,
6175                                                         printername,
6176                                                         &found),
6177                         "failed to enum printers");
6178         torture_assert(tctx, found, "failed to find newly added printer");
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_PRINTER_ALREADY_EXISTS,
6185                 "unexpected result code");
6186
6187         return true;
6188 }
6189
6190 static bool test_printer_info(struct torture_context *tctx,
6191                               struct dcerpc_binding_handle *b,
6192                               struct policy_handle *handle)
6193 {
6194         bool ret = true;
6195
6196         if (torture_setting_bool(tctx, "samba3", false)) {
6197                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6198         }
6199
6200         if (!test_PrinterInfo(tctx, b, handle)) {
6201                 ret = false;
6202         }
6203
6204         if (!test_SetPrinter_errors(tctx, b, handle)) {
6205                 ret = false;
6206         }
6207
6208         return ret;
6209 }
6210
6211 static bool test_EnumPrinterKey(struct torture_context *tctx,
6212                                 struct dcerpc_binding_handle *b,
6213                                 struct policy_handle *handle,
6214                                 const char *key_name,
6215                                 const char ***array)
6216 {
6217         struct spoolss_EnumPrinterKey r;
6218         uint32_t needed = 0;
6219         union spoolss_KeyNames key_buffer;
6220         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6221         uint32_t _ndr_size;
6222         int i;
6223
6224         r.in.handle = handle;
6225         r.in.key_name = key_name;
6226         r.out.key_buffer = &key_buffer;
6227         r.out.needed = &needed;
6228         r.out._ndr_size = &_ndr_size;
6229
6230         for (i=0; i < ARRAY_SIZE(offered); i++) {
6231
6232                 if (offered[i] < 0 && needed) {
6233                         if (needed <= 4) {
6234                                 continue;
6235                         }
6236                         r.in.offered = needed + offered[i];
6237                 } else {
6238                         r.in.offered = offered[i];
6239                 }
6240
6241                 ZERO_STRUCT(key_buffer);
6242
6243                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6244
6245                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6246                         "failed to call EnumPrinterKey");
6247                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6248
6249                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6250                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6251                                         _ndr_size, r.in.offered/2));
6252
6253                         r.in.offered = needed;
6254                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6255                                 "failed to call EnumPrinterKey");
6256                 }
6257
6258                 if (offered[i] > 0) {
6259                         torture_assert_werr_ok(tctx, r.out.result,
6260                                 "failed to call EnumPrinterKey");
6261                 }
6262
6263                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6264                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6265                                 _ndr_size, r.in.offered/2));
6266
6267                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6268                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6269
6270                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6271                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6272
6273                 if (key_buffer.string_array) {
6274                         uint32_t calc_needed = 0;
6275                         int s;
6276                         for (s=0; key_buffer.string_array[s]; s++) {
6277                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6278                         }
6279                         if (!key_buffer.string_array[0]) {
6280                                 calc_needed += 2;
6281                         }
6282                         calc_needed += 2;
6283
6284                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6285                                 "EnumPrinterKey unexpected size");
6286                 }
6287         }
6288
6289         if (array) {
6290                 *array = key_buffer.string_array;
6291         }
6292
6293         return true;
6294 }
6295
6296 bool test_printer_keys(struct torture_context *tctx,
6297                        struct dcerpc_binding_handle *b,
6298                        struct policy_handle *handle)
6299 {
6300         const char **key_array = NULL;
6301         int i;
6302
6303         torture_comment(tctx, "Testing Printer Keys\n");
6304
6305         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6306                 "failed to call test_EnumPrinterKey");
6307
6308         for (i=0; key_array && key_array[i]; i++) {
6309                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6310                         "failed to call test_EnumPrinterKey");
6311         }
6312         for (i=0; key_array && key_array[i]; i++) {
6313                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6314                         "failed to call test_EnumPrinterDataEx");
6315         }
6316
6317         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6318
6319         return true;
6320 }
6321
6322 static bool test_one_printer(struct torture_context *tctx,
6323                              struct dcerpc_pipe *p,
6324                              struct policy_handle *handle,
6325                              const char *name,
6326                              const char *drivername,
6327                              const char *environment,
6328                              bool have_driver,
6329                              struct spoolss_DeviceMode *devmode)
6330 {
6331         bool ret = true;
6332         struct dcerpc_binding_handle *b = p->binding_handle;
6333
6334         if (!test_PausePrinter(tctx, b, handle)) {
6335                 ret = false;
6336         }
6337
6338         if (!test_DoPrintTest(tctx, b, handle)) {
6339                 ret = false;
6340         }
6341
6342         if (!test_ResumePrinter(tctx, b, handle)) {
6343                 ret = false;
6344         }
6345
6346         if (!test_printer_info(tctx, b, handle)) {
6347                 ret = false;
6348         }
6349
6350         if (!test_PrinterInfo_SD(tctx, b, handle)) {
6351                 ret = false;
6352         }
6353
6354         if (!test_PrinterInfo_DevMode(tctx, p, handle, name, devmode)) {
6355                 ret = false;
6356         }
6357
6358         if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
6359                 ret = false;
6360         }
6361
6362         if (!test_ChangeID(tctx, p, handle)) {
6363                 ret = false;
6364         }
6365
6366         if (!test_printer_keys(tctx, b, handle)) {
6367                 ret = false;
6368         }
6369
6370         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
6371                 ret = false;
6372         }
6373
6374         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
6375                 ret = false;
6376         }
6377
6378         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
6379                 ret = false;
6380         }
6381
6382         if (!test_PrinterData_DsSpooler(tctx, p, handle, name)) {
6383                 ret = false;
6384         }
6385
6386         if (have_driver) {
6387                 if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
6388                         ret = false;
6389                 }
6390         }
6391
6392         if (!test_printer_rename(tctx, p, handle, name)) {
6393                 ret = false;
6394         }
6395
6396         return ret;
6397 }
6398
6399 static bool test_csetprinter(struct torture_context *tctx,
6400                              struct dcerpc_pipe *p,
6401                              struct policy_handle *handle,
6402                              const char *printername,
6403                              const char *drivername,
6404                              const char *portname)
6405 {
6406         union spoolss_PrinterInfo info;
6407         struct policy_handle new_handle, new_handle2;
6408         struct dcerpc_binding_handle *b = p->binding_handle;
6409
6410         torture_comment(tctx, "Testing c_setprinter\n");
6411
6412         torture_assert(tctx,
6413                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6414                 "failed to get level 0 printer info");
6415         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6416                 info.info0.c_setprinter);
6417
6418         /* check if c_setprinter on 1st handle increases after a printer has
6419          * been added */
6420
6421         torture_assert(tctx,
6422                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6423                 "failed to add new printer");
6424         torture_assert(tctx,
6425                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6426                 "failed to get level 0 printer info");
6427         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6428                 info.info0.c_setprinter);
6429
6430         /* check if c_setprinter on new handle increases after a printer has
6431          * been added */
6432
6433         torture_assert(tctx,
6434                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6435                 "failed to get level 0 printer info");
6436         torture_comment(tctx, "csetprinter on created handle: %d\n",
6437                 info.info0.c_setprinter);
6438
6439         /* open the new printer and check if c_setprinter increases */
6440
6441         torture_assert(tctx,
6442                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6443                 "failed to open created printer");
6444         torture_assert(tctx,
6445                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6446                 "failed to get level 0 printer info");
6447         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6448                 info.info0.c_setprinter);
6449
6450         /* cleanup */
6451
6452         torture_assert(tctx,
6453                 test_ClosePrinter(tctx, b, &new_handle2),
6454                 "failed to close printer");
6455         torture_assert(tctx,
6456                 test_DeletePrinter(tctx, b, &new_handle),
6457                 "failed to delete new printer");
6458
6459         return true;
6460 }
6461
6462 static bool test_add_printer_args_with_driver(struct torture_context *tctx,
6463                                               struct dcerpc_pipe *p,
6464                                               struct torture_printer_context *t)
6465 {
6466         bool ret = true;
6467         struct policy_handle handle;
6468         bool found = false;
6469         struct dcerpc_binding_handle *b = p->binding_handle;
6470         const char *printer_name = t->info2.printername;
6471         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6472         const char *port_name = t->info2.portname;
6473         const char *printer_name2 = talloc_asprintf(tctx, "%s2", printer_name);
6474
6475         if (t->wellknown) {
6476                 torture_assert(tctx,
6477                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6478                         "failed to add wellknown printer");
6479         } else {
6480                 torture_assert(tctx,
6481                         test_AddPrinter_normal(tctx, p, &handle, printer_name, driver_name, port_name, t->devmode, t->ex),
6482                         "failed to add printer");
6483         }
6484
6485         if (!test_csetprinter(tctx, p, &handle, printer_name2, driver_name, port_name)) {
6486                 ret = false;
6487         }
6488
6489         if (!test_one_printer(tctx, p, &handle, printer_name, driver_name, t->driver.remote.environment, t->have_driver, t->devmode)) {
6490                 ret = false;
6491         }
6492
6493         if (!test_DeletePrinter(tctx, b, &handle)) {
6494                 ret = false;
6495         }
6496
6497         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6498                                         printer_name, &found)) {
6499                 ret = false;
6500         }
6501
6502         torture_assert(tctx, !found, "deleted printer still there");
6503
6504         return ret;
6505 }
6506
6507 static bool compose_local_driver_directory(struct torture_context *tctx,
6508                                            const char *environment,
6509                                            const char *local_dir,
6510                                            const char **path)
6511 {
6512         char *p;
6513
6514         p = strrchr(local_dir, '/');
6515         if (!p) {
6516                 return NULL;
6517         }
6518         p++;
6519
6520         if (strequal(environment, "Windows x64")) {
6521                 if (!strequal(p, "x64")) {
6522                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6523                 }
6524         } else if (strequal(environment, "Windows NT x86")) {
6525                 if (!strequal(p, "i386")) {
6526                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6527                 }
6528         } else {
6529                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6530         }
6531
6532         return true;
6533 }
6534
6535 static bool test_add_printer_args(struct torture_context *tctx,
6536                                   struct dcerpc_pipe *p,
6537                                   struct torture_printer_context *t)
6538 {
6539         bool ret = true;
6540         struct dcerpc_binding_handle *b = p->binding_handle;
6541         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6542
6543         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6544                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6545         }
6546
6547         torture_assert(tctx,
6548                 fillup_printserver_info(tctx, p, &t->driver),
6549                 "failed to fillup printserver info");
6550
6551         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6552
6553         torture_assert(tctx,
6554                 compose_local_driver_directory(tctx, t->driver.remote.environment,
6555                                                t->driver.local.driver_directory,
6556                                                &t->driver.local.driver_directory),
6557                 "failed to compose local driver directory");
6558
6559         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6560                 t->have_driver = true;
6561                 goto try_run;
6562         }
6563
6564         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6565                 t->info2.drivername, t->driver.remote.environment);
6566         torture_comment(tctx, "trying to upload own driver\n");
6567
6568         if (!directory_exist(t->driver.local.driver_directory)) {
6569                 torture_warning(tctx, "no local driver is available!");
6570                 t->have_driver = false;
6571                 goto try_run;
6572         }
6573
6574         torture_assert(tctx,
6575                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6576                 "failed to upload printer driver");
6577
6578         torture_assert(tctx,
6579                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6580                 "failed to add driver");
6581
6582         t->added_driver = true;
6583         t->have_driver = true;
6584
6585  try_run:
6586         ret = test_add_printer_args_with_driver(tctx, p, t);
6587
6588         if (t->added_driver) {
6589                 torture_assert(tctx,
6590                         remove_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6591                         "failed to remove printer driver");
6592         }
6593
6594         return ret;
6595 }
6596
6597 static bool test_add_printer(struct torture_context *tctx,
6598                              struct dcerpc_pipe *p,
6599                              void *private_data)
6600 {
6601         struct torture_printer_context *t =
6602                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6603
6604         t->ex                   = false;
6605         t->wellknown            = false;
6606         t->info2.printername    = TORTURE_PRINTER;
6607
6608         return test_add_printer_args(tctx, p, t);
6609 }
6610
6611 static bool test_add_printer_wellknown(struct torture_context *tctx,
6612                                        struct dcerpc_pipe *p,
6613                                        void *private_data)
6614 {
6615         struct torture_printer_context *t =
6616                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6617
6618         t->ex                   = false;
6619         t->wellknown            = true;
6620         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
6621         t->devmode              = NULL;
6622
6623         return test_add_printer_args(tctx, p, t);
6624 }
6625
6626 static bool test_add_printer_ex(struct torture_context *tctx,
6627                                 struct dcerpc_pipe *p,
6628                                 void *private_data)
6629 {
6630         struct torture_printer_context *t =
6631                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6632
6633         t->ex                   = true;
6634         t->wellknown            = false;
6635         t->info2.printername    = TORTURE_PRINTER_EX;
6636         t->devmode              = NULL;
6637
6638         return test_add_printer_args(tctx, p, t);
6639 }
6640
6641 static bool test_add_printer_ex_wellknown(struct torture_context *tctx,
6642                                           struct dcerpc_pipe *p,
6643                                           void *private_data)
6644 {
6645         struct torture_printer_context *t =
6646                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6647
6648         t->ex                   = true;
6649         t->wellknown            = true;
6650         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
6651         t->devmode              = NULL;
6652
6653         return test_add_printer_args(tctx, p, t);
6654 }
6655
6656 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6657                                                      const char *devicename)
6658 {
6659         struct spoolss_DeviceMode *r;
6660
6661         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6662         if (r == NULL) {
6663                 return NULL;
6664         }
6665
6666         r->devicename           = talloc_strdup(r, devicename);
6667         r->specversion          = DMSPEC_NT4_AND_ABOVE;
6668         r->driverversion        = 0x0600;
6669         r->size                 = 0x00dc;
6670         r->__driverextra_length = 0;
6671         r->fields               = DEVMODE_FORMNAME |
6672                                   DEVMODE_TTOPTION |
6673                                   DEVMODE_PRINTQUALITY |
6674                                   DEVMODE_DEFAULTSOURCE |
6675                                   DEVMODE_COPIES |
6676                                   DEVMODE_SCALE |
6677                                   DEVMODE_PAPERSIZE |
6678                                   DEVMODE_ORIENTATION;
6679         r->orientation          = DMORIENT_PORTRAIT;
6680         r->papersize            = DMPAPER_LETTER;
6681         r->paperlength          = 0;
6682         r->paperwidth           = 0;
6683         r->scale                = 100;
6684         r->copies               = 55;
6685         r->defaultsource        = DMBIN_FORMSOURCE;
6686         r->printquality         = DMRES_HIGH;
6687         r->color                = DMRES_MONOCHROME;
6688         r->duplex               = DMDUP_SIMPLEX;
6689         r->yresolution          = 0;
6690         r->ttoption             = DMTT_SUBDEV;
6691         r->collate              = DMCOLLATE_FALSE;
6692         r->formname             = talloc_strdup(r, "Letter");
6693
6694         return r;
6695 }
6696
6697 static bool test_add_printer_with_devmode(struct torture_context *tctx,
6698                                           struct dcerpc_pipe *p,
6699                                           void *private_data)
6700 {
6701         struct torture_printer_context *t =
6702                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6703
6704         t->ex                   = true;
6705         t->wellknown            = false;
6706         t->info2.printername    = TORTURE_PRINTER_EX;
6707         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
6708
6709         return test_add_printer_args(tctx, p, t);
6710 }
6711
6712 static bool test_architecture_buffer(struct torture_context *tctx,
6713                                      struct dcerpc_pipe *p)
6714 {
6715         struct spoolss_OpenPrinterEx r;
6716         struct spoolss_UserLevel1 u1;
6717         struct policy_handle handle;
6718         uint32_t architectures[] = {
6719                 PROCESSOR_ARCHITECTURE_INTEL,
6720                 PROCESSOR_ARCHITECTURE_IA64,
6721                 PROCESSOR_ARCHITECTURE_AMD64
6722         };
6723         uint32_t needed[3];
6724         int i;
6725         struct dcerpc_binding_handle *b = p->binding_handle;
6726
6727         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6728
6729                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6730
6731                 u1.size = 0;
6732                 u1.client = NULL;
6733                 u1.user = NULL;
6734                 u1.build = 0;
6735                 u1.major = 3;
6736                 u1.minor = 0;
6737                 u1.processor = architectures[i];
6738
6739                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6740                 r.in.datatype           = NULL;
6741                 r.in.devmode_ctr.devmode= NULL;
6742                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6743                 r.in.level               = 1;
6744                 r.in.userlevel.level1   = &u1;
6745                 r.out.handle            = &handle;
6746
6747                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6748                 torture_assert_werr_ok(tctx, r.out.result, "");
6749
6750                 {
6751                         struct spoolss_EnumPrinters e;
6752                         uint32_t count;
6753                         union spoolss_PrinterInfo *info;
6754
6755                         e.in.flags = PRINTER_ENUM_LOCAL;
6756                         e.in.server = NULL;
6757                         e.in.level = 2;
6758                         e.in.buffer = NULL;
6759                         e.in.offered = 0;
6760                         e.out.count = &count;
6761                         e.out.info = &info;
6762                         e.out.needed = &needed[i];
6763
6764                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6765 #if 0
6766                         torture_comment(tctx, "needed was %d\n", needed[i]);
6767 #endif
6768                 }
6769
6770                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6771         }
6772
6773         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6774                 if (needed[i-1] != needed[i]) {
6775                         torture_fail(tctx,
6776                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6777                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6778                 }
6779         }
6780
6781         return true;
6782 }
6783
6784 bool torture_rpc_spoolss(struct torture_context *torture)
6785 {
6786         NTSTATUS status;
6787         struct dcerpc_pipe *p;
6788         struct dcerpc_binding_handle *b;
6789         bool ret = true;
6790         struct test_spoolss_context *ctx;
6791         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
6792
6793         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
6794         if (!NT_STATUS_IS_OK(status)) {
6795                 return false;
6796         }
6797         b = p->binding_handle;
6798
6799         ctx = talloc_zero(torture, struct test_spoolss_context);
6800
6801         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
6802         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
6803         ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
6804         ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
6805         ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
6806         ret &= test_EnumPorts(torture, b, ctx);
6807         ret &= test_GetPrinterDriverDirectory(torture, p, environment);
6808         ret &= test_GetPrintProcessorDirectory(torture, p, environment);
6809         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
6810         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
6811         ret &= test_EnumMonitors(torture, b, ctx);
6812         ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
6813         ret &= test_EnumPrintProcDataTypes(torture, b);
6814         ret &= test_EnumPrinters(torture, b, ctx);
6815         ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
6816
6817         ret &= test_AddPort(torture, p);
6818         ret &= test_EnumPorts_old(torture, p);
6819         ret &= test_EnumPrinters_old(torture, p, environment);
6820         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
6821         ret &= test_architecture_buffer(torture, p);
6822
6823         return ret;
6824 }
6825
6826 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
6827 {
6828         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
6829
6830         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
6831                                                         "printer", &ndr_table_spoolss);
6832
6833         struct torture_printer_context *t;
6834
6835         t = talloc_zero(mem_ctx, struct torture_printer_context);
6836
6837         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
6838         t->driver.info8.driver_name             = TORTURE_DRIVER;
6839         t->driver.info8.driver_path             = "pscript5.dll";
6840         t->driver.info8.data_file               = "cups6.ppd";
6841         t->driver.info8.config_file             = "ps5ui.dll";
6842         t->driver.info8.help_file               = "pscript.hlp";
6843         t->driver.info8.default_datatype        = "RAW";
6844         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
6845         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6846         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6847         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6848         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6849         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6850         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6851         t->driver.info8.dependent_files->string[5] = "cups6.ini";
6852         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6853         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6854
6855         t->driver.local.driver_directory= "/usr/share/cups/drivers";
6856
6857         t->info2.drivername             = "Microsoft XPS Document Writer";
6858         t->info2.portname               = "LPT1:";
6859
6860         torture_rpc_tcase_add_test_ex(tcase, "add_printer", test_add_printer, t);
6861         torture_rpc_tcase_add_test_ex(tcase, "add_printer_wellknown", test_add_printer_wellknown, t);
6862         torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex", test_add_printer_ex, t);
6863         torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex_wellknown", test_add_printer_ex_wellknown, t);
6864
6865         torture_rpc_tcase_add_test_ex(tcase, "add_printer_with_devmode", test_add_printer_with_devmode, t);
6866
6867         return suite;
6868 }
6869
6870 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
6871                                                   struct dcerpc_binding_handle *b,
6872                                                   const char *server,
6873                                                   const char *environment,
6874                                                   const char **dir_p)
6875 {
6876         struct spoolss_GetPrinterDriverDirectory r;
6877         uint32_t needed;
6878
6879         r.in.server             = server;
6880         r.in.environment        = environment;
6881         r.in.level              = 1;
6882         r.in.buffer             = NULL;
6883         r.in.offered            = 0;
6884         r.out.needed            = &needed;
6885
6886         torture_assert_ntstatus_ok(tctx,
6887                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6888                 "failed to query driver directory");
6889
6890         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6891                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6892                 r.in.buffer = &blob;
6893                 r.in.offered = needed;
6894
6895                 torture_assert_ntstatus_ok(tctx,
6896                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6897                         "failed to query driver directory");
6898         }
6899
6900         torture_assert_werr_ok(tctx, r.out.result,
6901                 "failed to query driver directory");
6902
6903         if (dir_p) {
6904                 *dir_p = r.out.info->info1.directory_name;
6905         }
6906
6907         return true;
6908 }
6909
6910 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6911 {
6912         if (info_ctr == NULL) {
6913                 return NULL;
6914         }
6915
6916         switch (info_ctr->level) {
6917         case 1:
6918                 return info_ctr->info.info1->driver_name;
6919         case 2:
6920                 return info_ctr->info.info2->driver_name;
6921         case 3:
6922                 return info_ctr->info.info3->driver_name;
6923         case 4:
6924                 return info_ctr->info.info4->driver_name;
6925         case 6:
6926                 return info_ctr->info.info6->driver_name;
6927         case 8:
6928                 return info_ctr->info.info8->driver_name;
6929         default:
6930                 return NULL;
6931         }
6932 }
6933
6934 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6935 {
6936         if (info_ctr == NULL) {
6937                 return NULL;
6938         }
6939
6940         switch (info_ctr->level) {
6941         case 2:
6942                 return info_ctr->info.info2->architecture;
6943         case 3:
6944                 return info_ctr->info.info3->architecture;
6945         case 4:
6946                 return info_ctr->info.info4->architecture;
6947         case 6:
6948                 return info_ctr->info.info6->architecture;
6949         case 8:
6950                 return info_ctr->info.info8->architecture;
6951         default:
6952                 return NULL;
6953         }
6954 }
6955
6956
6957 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
6958                                       struct dcerpc_binding_handle *b,
6959                                       const char *servername,
6960                                       struct spoolss_AddDriverInfoCtr *info_ctr,
6961                                       WERROR expected_result)
6962 {
6963         struct spoolss_AddPrinterDriver r;
6964         const char *drivername = get_driver_from_info(info_ctr);
6965         const char *environment = get_environment_from_info(info_ctr);
6966
6967         r.in.servername = servername;
6968         r.in.info_ctr = info_ctr;
6969
6970         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
6971                 drivername, info_ctr->level, environment);
6972
6973         torture_assert_ntstatus_ok(tctx,
6974                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
6975                 "spoolss_AddPrinterDriver failed");
6976         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6977                 "spoolss_AddPrinterDriver failed with unexpected result");
6978
6979         return true;
6980
6981 }
6982
6983 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
6984                                         struct dcerpc_binding_handle *b,
6985                                         const char *servername,
6986                                         struct spoolss_AddDriverInfoCtr *info_ctr,
6987                                         uint32_t flags,
6988                                         WERROR expected_result)
6989 {
6990         struct spoolss_AddPrinterDriverEx r;
6991         const char *drivername = get_driver_from_info(info_ctr);
6992         const char *environment = get_environment_from_info(info_ctr);
6993
6994         r.in.servername = servername;
6995         r.in.info_ctr = info_ctr;
6996         r.in.flags = flags;
6997
6998         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
6999                 drivername, info_ctr->level, environment);
7000
7001         torture_assert_ntstatus_ok(tctx,
7002                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7003                 "AddPrinterDriverEx failed");
7004         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7005                 "AddPrinterDriverEx failed with unexpected result");
7006
7007         return true;
7008 }
7009
7010 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7011                                                struct dcerpc_binding_handle *b,
7012                                                const char *server_name,
7013                                                struct spoolss_AddDriverInfo8 *r,
7014                                                uint32_t flags,
7015                                                bool ex)
7016 {
7017         struct spoolss_AddDriverInfoCtr info_ctr;
7018         struct spoolss_AddDriverInfo1 info1;
7019
7020         ZERO_STRUCT(info1);
7021
7022         info_ctr.level = 1;
7023         info_ctr.info.info1 = &info1;
7024
7025         if (ex) {
7026                 torture_assert(tctx,
7027                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7028                         "failed to test AddPrinterDriverEx level 1");
7029         } else {
7030                 torture_assert(tctx,
7031                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7032                         "failed to test AddPrinterDriver level 1");
7033         }
7034
7035         info1.driver_name = r->driver_name;
7036
7037         if (ex) {
7038                 torture_assert(tctx,
7039                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7040                         "failed to test AddPrinterDriverEx level 1");
7041         } else {
7042                 torture_assert(tctx,
7043                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7044                         "failed to test AddPrinterDriver level 1");
7045         }
7046
7047         return true;
7048 }
7049
7050 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7051                                                struct dcerpc_binding_handle *b,
7052                                                const char *server_name,
7053                                                struct spoolss_AddDriverInfo8 *r,
7054                                                uint32_t flags,
7055                                                bool ex)
7056 {
7057         struct spoolss_AddDriverInfoCtr info_ctr;
7058         struct spoolss_AddDriverInfo2 info2;
7059
7060         ZERO_STRUCT(info2);
7061
7062         info_ctr.level = 2;
7063         info_ctr.info.info2 = &info2;
7064
7065         if (ex) {
7066                 torture_assert(tctx,
7067                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7068                         "failed to test AddPrinterDriverEx level 2");
7069         } else {
7070                 torture_assert(tctx,
7071                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7072                         "failed to test AddPrinterDriver level 2");
7073         }
7074
7075         info2.driver_name = r->driver_name;
7076
7077         if (ex) {
7078                 torture_assert(tctx,
7079                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7080                         "failed to test AddPrinterDriverEx level 2");
7081         } else {
7082                 torture_assert(tctx,
7083                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7084                         "failed to test AddPrinterDriver level 2");
7085         }
7086
7087         info2.version = r->version;
7088
7089         if (ex) {
7090                 torture_assert(tctx,
7091                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7092                         "failed to test AddPrinterDriverEx level 2");
7093         } else {
7094                 torture_assert(tctx,
7095                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7096                         "failed to test AddPrinterDriver level 2");
7097         }
7098
7099         info2.architecture = r->architecture;
7100
7101         if (ex) {
7102                 torture_assert(tctx,
7103                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7104                         "failed to test AddPrinterDriverEx level 2");
7105         } else {
7106                 torture_assert(tctx,
7107                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7108                         "failed to test AddPrinterDriver level 2");
7109         }
7110
7111         info2.driver_path = r->driver_path;
7112
7113         if (ex) {
7114                 torture_assert(tctx,
7115                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7116                         "failed to test AddPrinterDriverEx level 2");
7117         } else {
7118                 torture_assert(tctx,
7119                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7120                         "failed to test AddPrinterDriver level 2");
7121         }
7122
7123         info2.data_file = r->data_file;
7124
7125         if (ex) {
7126                 torture_assert(tctx,
7127                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7128                         "failed to test AddPrinterDriverEx level 2");
7129         } else {
7130                 torture_assert(tctx,
7131                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7132                         "failed to test AddPrinterDriver level 2");
7133         }
7134
7135         info2.config_file = r->config_file;
7136
7137         if (ex) {
7138                 torture_assert(tctx,
7139                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7140                         "failed to test AddPrinterDriverEx");
7141         }
7142
7143         if (ex) {
7144                 torture_assert(tctx,
7145                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7146                         "failed to test AddPrinterDriverEx level 2");
7147         } else {
7148                 torture_assert(tctx,
7149                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7150                         "failed to test AddPrinterDriver level 2");
7151         }
7152
7153         torture_assert(tctx,
7154                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7155                 "failed to find added printer driver");
7156
7157         return true;
7158 }
7159
7160 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7161                                                struct dcerpc_binding_handle *b,
7162                                                const char *server_name,
7163                                                struct spoolss_AddDriverInfo8 *r,
7164                                                uint32_t flags,
7165                                                bool ex)
7166 {
7167         struct spoolss_AddDriverInfoCtr info_ctr;
7168         struct spoolss_AddDriverInfo3 info3;
7169
7170         info3.driver_name       = r->driver_name;
7171         info3.version           = r->version;
7172         info3.architecture      = r->architecture;
7173         info3.driver_path       = r->driver_path;
7174         info3.data_file         = r->data_file;
7175         info3.config_file       = r->config_file;
7176         info3.help_file         = r->help_file;
7177         info3.monitor_name      = r->monitor_name;
7178         info3.default_datatype  = r->default_datatype;
7179         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7180         info3.dependent_files   = r->dependent_files;
7181
7182         info_ctr.level = 3;
7183         info_ctr.info.info3 = &info3;
7184
7185         if (ex) {
7186                 torture_assert(tctx,
7187                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7188                         "failed to test AddPrinterDriverEx level 3");
7189         } else {
7190                 torture_assert(tctx,
7191                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7192                         "failed to test AddPrinterDriver level 3");
7193         }
7194
7195         torture_assert(tctx,
7196                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7197                 "failed to find added printer driver");
7198
7199         return true;
7200 }
7201
7202 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7203                                                struct dcerpc_binding_handle *b,
7204                                                const char *server_name,
7205                                                struct spoolss_AddDriverInfo8 *r,
7206                                                uint32_t flags,
7207                                                bool ex)
7208 {
7209         struct spoolss_AddDriverInfoCtr info_ctr;
7210         struct spoolss_AddDriverInfo4 info4;
7211
7212         info4.version           = r->version;
7213         info4.driver_name       = r->driver_name;
7214         info4.architecture      = r->architecture;
7215         info4.driver_path       = r->driver_path;
7216         info4.data_file         = r->data_file;
7217         info4.config_file       = r->config_file;
7218         info4.help_file         = r->help_file;
7219         info4.monitor_name      = r->monitor_name;
7220         info4.default_datatype  = r->default_datatype;
7221         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7222         info4.dependent_files   = r->dependent_files;
7223         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7224         info4.previous_names = r->previous_names;
7225
7226         info_ctr.level = 4;
7227         info_ctr.info.info4 = &info4;
7228
7229         if (ex) {
7230                 torture_assert(tctx,
7231                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7232                         "failed to test AddPrinterDriverEx level 4");
7233         } else {
7234                 torture_assert(tctx,
7235                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7236                         "failed to test AddPrinterDriver level 4");
7237         }
7238
7239         torture_assert(tctx,
7240                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7241                 "failed to find added printer driver");
7242
7243         return true;
7244 }
7245
7246 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7247                                                struct dcerpc_binding_handle *b,
7248                                                const char *server_name,
7249                                                struct spoolss_AddDriverInfo8 *r,
7250                                                uint32_t flags,
7251                                                bool ex)
7252 {
7253         struct spoolss_AddDriverInfoCtr info_ctr;
7254         struct spoolss_AddDriverInfo6 info6;
7255
7256         info6.version           = r->version;
7257         info6.driver_name       = r->driver_name;
7258         info6.architecture      = r->architecture;
7259         info6.driver_path       = r->driver_path;
7260         info6.data_file         = r->data_file;
7261         info6.config_file       = r->config_file;
7262         info6.help_file         = r->help_file;
7263         info6.monitor_name      = r->monitor_name;
7264         info6.default_datatype  = r->default_datatype;
7265         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7266         info6.dependent_files   = r->dependent_files;
7267         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7268         info6.previous_names    = r->previous_names;
7269         info6.driver_date       = r->driver_date;
7270         info6.driver_version    = r->driver_version;
7271         info6.manufacturer_name = r->manufacturer_name;
7272         info6.manufacturer_url  = r->manufacturer_url;
7273         info6.hardware_id       = r->hardware_id;
7274         info6.provider          = r->provider;
7275
7276         info_ctr.level = 6;
7277         info_ctr.info.info6 = &info6;
7278
7279         if (ex) {
7280                 torture_assert(tctx,
7281                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7282                         "failed to test AddPrinterDriverEx level 6");
7283         } else {
7284                 torture_assert(tctx,
7285                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7286                         "failed to test AddPrinterDriver level 6");
7287         }
7288
7289         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7290
7291         if (!ex) {
7292                 return true;
7293         }
7294
7295         torture_assert(tctx,
7296                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7297                 "failed to find added printer driver");
7298
7299         return true;
7300 }
7301
7302 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7303                                                struct dcerpc_binding_handle *b,
7304                                                const char *server_name,
7305                                                struct spoolss_AddDriverInfo8 *r,
7306                                                uint32_t flags,
7307                                                bool ex)
7308 {
7309         struct spoolss_AddDriverInfoCtr info_ctr;
7310
7311         info_ctr.level = 8;
7312         info_ctr.info.info8 = r;
7313
7314         if (ex) {
7315                 torture_assert(tctx,
7316                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7317                         "failed to test AddPrinterDriverEx level 8");
7318         } else {
7319                 torture_assert(tctx,
7320                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7321                         "failed to test AddPrinterDriver level 8");
7322         }
7323
7324         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7325
7326         if (!ex) {
7327                 return true;
7328         }
7329
7330         torture_assert(tctx,
7331                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7332                 "failed to find added printer driver");
7333
7334         return true;
7335 }
7336
7337 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7338                                          struct dcerpc_binding_handle *b,
7339                                          const char *server,
7340                                          const char *driver,
7341                                          const char *environment,
7342                                          WERROR expected_result)
7343 {
7344         struct spoolss_DeletePrinterDriver r;
7345
7346         r.in.server = server;
7347         r.in.architecture = environment;
7348         r.in.driver = driver;
7349
7350         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7351
7352         torture_assert_ntstatus_ok(tctx,
7353                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7354                 "DeletePrinterDriver failed");
7355         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7356                 "DeletePrinterDriver failed with unexpected result");
7357
7358         return true;
7359 }
7360
7361 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7362                                            struct dcerpc_binding_handle *b,
7363                                            const char *server,
7364                                            const char *driver,
7365                                            const char *environment,
7366                                            uint32_t delete_flags,
7367                                            uint32_t version,
7368                                            WERROR expected_result)
7369 {
7370         struct spoolss_DeletePrinterDriverEx r;
7371
7372         r.in.server = server;
7373         r.in.architecture = environment;
7374         r.in.driver = driver;
7375         r.in.delete_flags = delete_flags;
7376         r.in.version = version;
7377
7378         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7379
7380         torture_assert_ntstatus_ok(tctx,
7381                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7382                 "DeletePrinterDriverEx failed");
7383         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7384                 "DeletePrinterDriverEx failed with unexpected result");
7385
7386         return true;
7387 }
7388
7389 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7390                                      struct dcerpc_binding_handle *b,
7391                                      const char *server_name,
7392                                      const char *driver,
7393                                      const char *environment)
7394 {
7395         torture_assert(tctx,
7396                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7397                 "failed to delete driver");
7398
7399         torture_assert(tctx,
7400                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7401                 "failed to delete driver");
7402
7403         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7404                 torture_fail(tctx, "deleted driver still enumerated");
7405         }
7406
7407         torture_assert(tctx,
7408                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7409                 "2nd delete failed");
7410
7411         return true;
7412 }
7413
7414 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7415                                        struct dcerpc_binding_handle *b,
7416                                        const char *server_name,
7417                                        const char *driver,
7418                                        const char *environment,
7419                                        uint32_t delete_flags,
7420                                        uint32_t version)
7421 {
7422         torture_assert(tctx,
7423                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7424                 "failed to delete driver");
7425
7426         torture_assert(tctx,
7427                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7428                 "failed to delete driver");
7429
7430         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7431                 torture_fail(tctx, "deleted driver still enumerated");
7432         }
7433
7434         torture_assert(tctx,
7435                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7436                 "2nd delete failed");
7437
7438         return true;
7439 }
7440
7441 static bool test_PrinterDriver_args(struct torture_context *tctx,
7442                                     struct dcerpc_binding_handle *b,
7443                                     const char *server_name,
7444                                     uint32_t level,
7445                                     struct spoolss_AddDriverInfo8 *r,
7446                                     uint32_t add_flags,
7447                                     uint32_t delete_flags,
7448                                     uint32_t delete_version,
7449                                     bool ex)
7450 {
7451         bool ret = true;
7452
7453         switch (level) {
7454         case 1:
7455                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7456                 break;
7457         case 2:
7458                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7459                 break;
7460         case 3:
7461                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7462                 break;
7463         case 4:
7464                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7465                 break;
7466         case 6:
7467                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7468                 break;
7469         case 8:
7470                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7471                 break;
7472         default:
7473                 return false;
7474         }
7475
7476         if (ret == false) {
7477                 return ret;
7478         }
7479
7480         if (level == 1) {
7481                 return ret;
7482         }
7483
7484         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7485
7486         if (!ex && (level == 6 || level == 8)) {
7487                 return ret;
7488         }
7489
7490         if (ex) {
7491                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
7492         } else {
7493                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
7494         }
7495 }
7496
7497 static bool fillup_printserver_info(struct torture_context *tctx,
7498                                     struct dcerpc_pipe *p,
7499                                     struct torture_driver_context *d)
7500 {
7501         struct policy_handle server_handle;
7502         struct dcerpc_binding_handle *b = p->binding_handle;
7503         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7504
7505         torture_assert(tctx,
7506                 test_OpenPrinter_server(tctx, p, &server_handle),
7507                 "failed to open printserver");
7508         torture_assert(tctx,
7509                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
7510                 "failed to get environment");
7511         torture_assert(tctx,
7512                 test_ClosePrinter(tctx, b, &server_handle),
7513                 "failed to close printserver");
7514
7515         torture_assert(tctx,
7516                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
7517                         d->local.environment ? d->local.environment : d->remote.environment,
7518                         &d->remote.driver_directory),
7519                 "failed to get driver directory");
7520
7521         return true;
7522 }
7523
7524 static const char *driver_directory_dir(const char *driver_directory)
7525 {
7526         char *p;
7527
7528         p = strrchr(driver_directory, '\\');
7529         if (p) {
7530                 return p+1;
7531         }
7532
7533         return NULL;
7534 }
7535
7536 static const char *driver_directory_share(struct torture_context *tctx,
7537                                           const char *driver_directory)
7538 {
7539         const char *p;
7540         char *tok;
7541
7542         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
7543                 driver_directory += 2;
7544         }
7545
7546         p = talloc_strdup(tctx, driver_directory);
7547
7548         torture_assert(tctx,
7549                 next_token_talloc(tctx, &p, &tok, "\\"),
7550                 "cannot explode uri");
7551         torture_assert(tctx,
7552                 next_token_talloc(tctx, &p, &tok, "\\"),
7553                 "cannot explode uri");
7554
7555         return tok;
7556 }
7557
7558 static bool upload_printer_driver_file(struct torture_context *tctx,
7559                                        struct smbcli_state *cli,
7560                                        struct torture_driver_context *d,
7561                                        const char *file_name)
7562 {
7563         XFILE *f;
7564         int fnum;
7565         uint8_t *buf;
7566         int maxwrite = 64512;
7567         off_t nread = 0;
7568         size_t start = 0;
7569         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7570         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
7571         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7572
7573         if (!file_name) {
7574                 return true;
7575         }
7576
7577         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
7578
7579         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
7580         if (fnum == -1) {
7581                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
7582         }
7583
7584         f = x_fopen(local_name, O_RDONLY, 0);
7585         if (f == NULL) {
7586                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
7587         }
7588
7589         buf = talloc_array(tctx, uint8_t, maxwrite);
7590         if (!buf) {
7591                 return false;
7592         }
7593
7594         while (!x_feof(f)) {
7595                 int n = maxwrite;
7596                 int ret;
7597
7598                 if ((n = x_fread(buf, 1, n, f)) < 1) {
7599                         if((n == 0) && x_feof(f))
7600                                 break; /* Empty local file. */
7601
7602                         torture_warning(tctx,
7603                                 "failed to read file: %s\n", strerror(errno));
7604                         break;
7605                 }
7606
7607                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
7608
7609                 if (n != ret) {
7610                         torture_warning(tctx,
7611                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
7612                         break;
7613                 }
7614
7615                 nread += n;
7616         }
7617
7618         x_fclose(f);
7619
7620         torture_assert_ntstatus_ok(tctx,
7621                 smbcli_close(cli->tree, fnum),
7622                 "failed to close file");
7623
7624         return true;
7625 }
7626
7627 static bool connect_printer_driver_share(struct torture_context *tctx,
7628                                          const char *server_name,
7629                                          const char *share_name,
7630                                          struct smbcli_state **cli)
7631 {
7632         struct smbcli_options smb_options;
7633         struct smbcli_session_options smb_session_options;
7634
7635         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
7636                 share_name, server_name);
7637
7638         lp_smbcli_options(tctx->lp_ctx, &smb_options);
7639         lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
7640
7641         torture_assert_ntstatus_ok(tctx,
7642                 smbcli_full_connection(tctx, cli, server_name,
7643                                         lp_smb_ports(tctx->lp_ctx),
7644                                         share_name, NULL,
7645                                         lp_socket_options(tctx->lp_ctx),
7646                                         cmdline_credentials,
7647                                         lp_resolve_context(tctx->lp_ctx),
7648                                         tctx->ev,
7649                                         &smb_options,
7650                                         &smb_session_options,
7651                                         lp_iconv_convenience(tctx->lp_ctx),
7652                                         lp_gensec_settings(tctx, tctx->lp_ctx)),
7653                 "failed to open driver share");
7654
7655         return true;
7656 }
7657
7658 static bool upload_printer_driver(struct torture_context *tctx,
7659                                   const char *server_name,
7660                                   struct torture_driver_context *d)
7661 {
7662         struct smbcli_state *cli;
7663         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7664         int i;
7665
7666         torture_assert(tctx,
7667                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7668                 "failed to connect to driver share");
7669
7670         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
7671                 server_name, share_name);
7672
7673         torture_assert(tctx,
7674                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7675                 "failed to upload driver_path");
7676         torture_assert(tctx,
7677                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
7678                 "failed to upload data_file");
7679         torture_assert(tctx,
7680                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
7681                 "failed to upload config_file");
7682         torture_assert(tctx,
7683                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
7684                 "failed to upload help_file");
7685         if (d->info8.dependent_files) {
7686                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7687                         torture_assert(tctx,
7688                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7689                                 "failed to upload dependent_files");
7690                 }
7691         }
7692
7693         talloc_free(cli);
7694
7695         return true;
7696 }
7697
7698 static bool remove_printer_driver_file(struct torture_context *tctx,
7699                                        struct smbcli_state *cli,
7700                                        struct torture_driver_context *d,
7701                                        const char *file_name)
7702 {
7703         const char *remote_name;
7704         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
7705
7706         if (!file_name) {
7707                 return true;
7708         }
7709
7710         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7711
7712         torture_comment(tctx, "Removing %s\n", remote_name);
7713
7714         torture_assert_ntstatus_ok(tctx,
7715                 smbcli_unlink(cli->tree, remote_name),
7716                 "failed to unlink");
7717
7718         return true;
7719 }
7720
7721 static bool remove_printer_driver(struct torture_context *tctx,
7722                                   const char *server_name,
7723                                   struct torture_driver_context *d)
7724 {
7725         struct smbcli_state *cli;
7726         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7727         int i;
7728
7729         torture_assert(tctx,
7730                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7731                 "failed to connect to driver share");
7732
7733         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
7734                 server_name, share_name);
7735
7736         torture_assert(tctx,
7737                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7738                 "failed to remove driver_path");
7739         torture_assert(tctx,
7740                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
7741                 "failed to remove data_file");
7742         torture_assert(tctx,
7743                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
7744                 "failed to remove config_file");
7745         torture_assert(tctx,
7746                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
7747                 "failed to remove help_file");
7748         if (d->info8.dependent_files) {
7749                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7750                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
7751                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
7752                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
7753                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
7754                                 continue;
7755                         }
7756                         torture_assert(tctx,
7757                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7758                                 "failed to remove dependent_files");
7759                 }
7760         }
7761
7762         talloc_free(cli);
7763
7764         return true;
7765
7766 }
7767
7768 static bool test_add_driver_arg(struct torture_context *tctx,
7769                                 struct dcerpc_pipe *p,
7770                                 struct torture_driver_context *d)
7771 {
7772         bool ret = true;
7773         struct dcerpc_binding_handle *b = p->binding_handle;
7774         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7775         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
7776         int i;
7777         struct spoolss_AddDriverInfo8 info8;
7778         uint32_t add_flags = APD_COPY_NEW_FILES;
7779         uint32_t delete_flags = 0;
7780
7781         ZERO_STRUCT(info8);
7782
7783         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
7784                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
7785
7786         torture_assert(tctx,
7787                 fillup_printserver_info(tctx, p, d),
7788                 "failed to fillup printserver info");
7789
7790         if (!directory_exist(d->local.driver_directory)) {
7791                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
7792         }
7793
7794         torture_assert(tctx,
7795                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
7796                 "failed to upload printer driver");
7797
7798         info8.version           = d->info8.version;
7799         info8.driver_name       = d->info8.driver_name;
7800         info8.architecture      = d->local.environment;
7801         info8.driver_path       = d->info8.driver_path;
7802         info8.data_file         = d->info8.data_file;
7803         info8.config_file       = d->info8.config_file;
7804
7805         for (i=0; i < ARRAY_SIZE(levels); i++) {
7806
7807                 if (torture_setting_bool(tctx, "samba3", false)) {
7808                         switch (levels[i]) {
7809                         case 2:
7810                         case 4:
7811                         case 8:
7812                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7813                                 continue;
7814                         default:
7815                                 break;
7816                         }
7817                 }
7818
7819                 torture_comment(tctx,
7820                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
7821                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7822
7823                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7824         }
7825
7826         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
7827         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
7828         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
7829
7830         for (i=0; i < ARRAY_SIZE(levels); i++) {
7831
7832                 if (torture_setting_bool(tctx, "samba3", false)) {
7833                         switch (levels[i]) {
7834                         case 2:
7835                         case 4:
7836                         case 8:
7837                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7838                                 continue;
7839                         default:
7840                                 break;
7841                         }
7842                 }
7843
7844
7845                 torture_comment(tctx,
7846                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
7847                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7848
7849                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7850         }
7851
7852         torture_assert(tctx,
7853                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
7854                 "failed to remove printer driver");
7855
7856         torture_comment(tctx, "\n");
7857
7858         return ret;
7859 }
7860
7861 static bool test_add_driver_ex_64(struct torture_context *tctx,
7862                                   struct dcerpc_pipe *p,
7863                                   void *private_data)
7864 {
7865         struct torture_driver_context *d =
7866                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7867
7868         d->local.environment            = talloc_strdup(d, "Windows x64");
7869         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7870         d->info8.driver_name            = TORTURE_DRIVER_EX;
7871         d->ex                           = true;
7872
7873         return test_add_driver_arg(tctx, p, d);
7874 }
7875
7876 static bool test_add_driver_ex_32(struct torture_context *tctx,
7877                                   struct dcerpc_pipe *p,
7878                                   void *private_data)
7879 {
7880         struct torture_driver_context *d =
7881                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7882
7883         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7884         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7885         d->info8.driver_name            = TORTURE_DRIVER_EX;
7886         d->ex                           = true;
7887
7888         return test_add_driver_arg(tctx, p, d);
7889 }
7890
7891 static bool test_add_driver_64(struct torture_context *tctx,
7892                                struct dcerpc_pipe *p,
7893                                void *private_data)
7894 {
7895         struct torture_driver_context *d =
7896                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7897
7898         d->local.environment            = talloc_strdup(d, "Windows x64");
7899         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7900         d->info8.driver_name            = TORTURE_DRIVER;
7901         d->ex                           = false;
7902
7903         return test_add_driver_arg(tctx, p, d);
7904 }
7905
7906 static bool test_add_driver_32(struct torture_context *tctx,
7907                                struct dcerpc_pipe *p,
7908                                void *private_data)
7909 {
7910         struct torture_driver_context *d =
7911                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7912
7913         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7914         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7915         d->info8.driver_name            = TORTURE_DRIVER;
7916         d->ex                           = false;
7917
7918         return test_add_driver_arg(tctx, p, d);
7919 }
7920
7921 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
7922 {
7923         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
7924
7925         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
7926                                                         "driver", &ndr_table_spoolss);
7927         struct torture_driver_context *t;
7928
7929         t = talloc_zero(mem_ctx, struct torture_driver_context);
7930
7931         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
7932         t->info8.driver_name    = NULL;
7933         t->info8.architecture   = NULL;
7934         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
7935         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
7936         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
7937
7938         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
7939         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
7940
7941         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
7942         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
7943
7944         return suite;
7945 }