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