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