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