s4-smbtorture: add spoolss_OpenPrinter with unc and printername in RPC-SPOOLSS-PRINTS...
[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                              bool open_only)
5650 {
5651         NTSTATUS status;
5652         struct spoolss_OpenPrinter r;
5653         struct policy_handle handle;
5654         bool ret = true;
5655         struct dcerpc_binding_handle *b = p->binding_handle;
5656
5657         r.in.printername        = name;
5658         r.in.datatype           = NULL;
5659         r.in.devmode_ctr.devmode= NULL;
5660         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5661         r.out.handle            = &handle;
5662
5663         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5664
5665         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5666
5667         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5668
5669         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5670
5671         if (open_only) {
5672                 goto close_printer;
5673         }
5674
5675         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5676                 ret = false;
5677         }
5678
5679         if (!torture_setting_bool(tctx, "samba3", false)) {
5680                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5681                         ret = false;
5682                 }
5683         }
5684
5685  close_printer:
5686         if (!test_ClosePrinter(tctx, b, &handle)) {
5687                 ret = false;
5688         }
5689
5690         return ret;
5691 }
5692
5693 static bool call_OpenPrinterEx(struct torture_context *tctx,
5694                                struct dcerpc_pipe *p,
5695                                const char *name,
5696                                struct spoolss_DeviceMode *devmode,
5697                                struct policy_handle *handle)
5698 {
5699         struct spoolss_OpenPrinterEx r;
5700         struct spoolss_UserLevel1 userlevel1;
5701         NTSTATUS status;
5702         struct dcerpc_binding_handle *b = p->binding_handle;
5703
5704         if (name && name[0]) {
5705                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5706                                                    dcerpc_server_name(p), name);
5707         } else {
5708                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5709                                                    dcerpc_server_name(p));
5710         }
5711
5712         r.in.datatype           = NULL;
5713         r.in.devmode_ctr.devmode= devmode;
5714         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5715         r.in.level              = 1;
5716         r.in.userlevel.level1   = &userlevel1;
5717         r.out.handle = handle;
5718
5719         userlevel1.size = 1234;
5720         userlevel1.client = "hello";
5721         userlevel1.user = "spottyfoot!";
5722         userlevel1.build = 1;
5723         userlevel1.major = 2;
5724         userlevel1.minor = 3;
5725         userlevel1.processor = 4;
5726
5727         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5728
5729         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5730
5731         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5732
5733         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5734
5735         return true;
5736 }
5737
5738 static bool test_printer_rename(struct torture_context *tctx,
5739                                 void *private_data)
5740 {
5741         struct torture_printer_context *t =
5742                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5743         struct dcerpc_pipe *p = t->spoolss_pipe;
5744
5745         bool ret = true;
5746         union spoolss_PrinterInfo info;
5747         union spoolss_SetPrinterInfo sinfo;
5748         struct spoolss_SetPrinterInfoCtr info_ctr;
5749         struct spoolss_DevmodeContainer devmode_ctr;
5750         struct sec_desc_buf secdesc_ctr;
5751         const char *printer_name;
5752         const char *printer_name_orig;
5753         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5754         struct policy_handle new_handle;
5755         const char *q;
5756         struct dcerpc_binding_handle *b = p->binding_handle;
5757
5758         ZERO_STRUCT(devmode_ctr);
5759         ZERO_STRUCT(secdesc_ctr);
5760
5761         torture_comment(tctx, "Testing Printer rename operations\n");
5762
5763         torture_assert(tctx,
5764                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5765                 "failed to call GetPrinter level 2");
5766
5767         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5768
5769         q = strrchr(info.info2.printername, '\\');
5770         if (q) {
5771                 torture_warning(tctx,
5772                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5773         }
5774
5775         torture_assert(tctx,
5776                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5777
5778         sinfo.info2->printername = printer_name_new;
5779
5780         info_ctr.level = 2;
5781         info_ctr.info = sinfo;
5782
5783         torture_assert(tctx,
5784                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5785                 "failed to call SetPrinter level 2");
5786
5787         torture_assert(tctx,
5788                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5789                 "failed to call GetPrinter level 2");
5790
5791         printer_name = talloc_strdup(tctx, info.info2.printername);
5792
5793         q = strrchr(info.info2.printername, '\\');
5794         if (q) {
5795                 torture_warning(tctx,
5796                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5797                 q++;
5798                 printer_name = q;
5799         }
5800
5801         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5802                 "new printer name was not set");
5803
5804         /* samba currently cannot fully rename printers */
5805         if (!torture_setting_bool(tctx, "samba3", false)) {
5806                 torture_assert(tctx,
5807                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5808                         "still can open printer with oldname after rename");
5809         } else {
5810                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5811         }
5812
5813         torture_assert(tctx,
5814                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5815                 "failed to open printer with new name");
5816
5817         torture_assert(tctx,
5818                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5819                 "failed to call GetPrinter level 2");
5820
5821         /* FIXME: we openend with servername! */
5822         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5823                 dcerpc_server_name(p), printer_name_new);
5824
5825         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5826                 "new printer name was not set");
5827
5828         torture_assert(tctx,
5829                 test_ClosePrinter(tctx, b, &new_handle),
5830                 "failed to close printer");
5831
5832         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5833
5834         return ret;
5835 }
5836
5837
5838 static bool test_OpenPrinterEx(struct torture_context *tctx,
5839                                struct dcerpc_pipe *p,
5840                                const char *name,
5841                                const char *environment)
5842 {
5843         struct policy_handle handle;
5844         bool ret = true;
5845         struct dcerpc_binding_handle *b = p->binding_handle;
5846
5847         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5848                 return false;
5849         }
5850
5851         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5852                 ret = false;
5853         }
5854
5855         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5856                 ret = false;
5857         }
5858
5859         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5860                 ret = false;
5861         }
5862
5863         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5864                 ret = false;
5865         }
5866
5867         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5868                 ret = false;
5869         }
5870
5871         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5872                 ret = false;
5873         }
5874
5875         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5876                 ret = false;
5877         }
5878
5879         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5880                 ret = false;
5881         }
5882
5883         if (!test_printer_all_keys(tctx, b, &handle)) {
5884                 ret = false;
5885         }
5886
5887         if (!test_PausePrinter(tctx, b, &handle)) {
5888                 ret = false;
5889         }
5890
5891         if (!test_DoPrintTest(tctx, b, &handle)) {
5892                 ret = false;
5893         }
5894
5895         if (!test_ResumePrinter(tctx, b, &handle)) {
5896                 ret = false;
5897         }
5898
5899         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5900                 ret = false;
5901         }
5902
5903         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5904                 ret = false;
5905         }
5906
5907         if (!torture_setting_bool(tctx, "samba3", false)) {
5908                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5909                         ret = false;
5910                 }
5911         }
5912
5913         if (!test_ClosePrinter(tctx, b, &handle)) {
5914                 ret = false;
5915         }
5916
5917         return ret;
5918 }
5919
5920 static bool test_EnumPrinters_old(struct torture_context *tctx,
5921                                   void *private_data)
5922 {
5923         struct test_spoolss_context *ctx =
5924                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5925         struct spoolss_EnumPrinters r;
5926         NTSTATUS status;
5927         uint16_t levels[] = {1, 2, 4, 5};
5928         int i;
5929         bool ret = true;
5930         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5931         struct dcerpc_binding_handle *b = p->binding_handle;
5932
5933         for (i=0;i<ARRAY_SIZE(levels);i++) {
5934                 union spoolss_PrinterInfo *info;
5935                 int j;
5936                 uint32_t needed;
5937                 uint32_t count;
5938
5939                 r.in.flags      = PRINTER_ENUM_LOCAL;
5940                 r.in.server     = "";
5941                 r.in.level      = levels[i];
5942                 r.in.buffer     = NULL;
5943                 r.in.offered    = 0;
5944                 r.out.needed    = &needed;
5945                 r.out.count     = &count;
5946                 r.out.info      = &info;
5947
5948                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5949
5950                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5951                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5952
5953                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5954                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5955                         r.in.buffer = &blob;
5956                         r.in.offered = needed;
5957                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5958                 }
5959
5960                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5961
5962                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5963
5964                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
5965
5966                 if (!info) {
5967                         torture_comment(tctx, "No printers returned\n");
5968                         return true;
5969                 }
5970
5971                 for (j=0;j<count;j++) {
5972                         if (r.in.level == 1) {
5973                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5974                                 char *slash, *name, *full_name;
5975                                 name = unc;
5976                                 if (unc[0] == '\\' && unc[1] == '\\') {
5977                                         unc +=2;
5978                                 }
5979                                 slash = strchr(unc, '\\');
5980                                 if (slash) {
5981                                         slash++;
5982                                         name = slash;
5983                                 }
5984                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5985                                                             dcerpc_server_name(p), name);
5986                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
5987                                         ret = false;
5988                                 }
5989                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
5990                                         ret = false;
5991                                 }
5992                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
5993                                         ret = false;
5994                                 }
5995                                 if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
5996                                         ret = false;
5997                                 }
5998                         }
5999                 }
6000         }
6001
6002         return ret;
6003 }
6004
6005 static bool test_GetPrinterDriver(struct torture_context *tctx,
6006                                   struct dcerpc_binding_handle *b,
6007                                   struct policy_handle *handle,
6008                                   const char *driver_name)
6009 {
6010         struct spoolss_GetPrinterDriver r;
6011         uint32_t needed;
6012
6013         r.in.handle = handle;
6014         r.in.architecture = "W32X86";
6015         r.in.level = 1;
6016         r.in.buffer = NULL;
6017         r.in.offered = 0;
6018         r.out.needed = &needed;
6019
6020         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6021
6022         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6023                 "failed to call GetPrinterDriver");
6024         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6025                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6026                 r.in.buffer = &blob;
6027                 r.in.offered = needed;
6028                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6029                         "failed to call GetPrinterDriver");
6030         }
6031
6032         torture_assert_werr_ok(tctx, r.out.result,
6033                 "failed to call GetPrinterDriver");
6034
6035         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6036
6037         return true;
6038 }
6039
6040 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6041                                          struct dcerpc_binding_handle *b,
6042                                          struct policy_handle *handle,
6043                                          const char *driver_name,
6044                                          const char *architecture,
6045                                          uint32_t level,
6046                                          uint32_t client_major_version,
6047                                          uint32_t client_minor_version,
6048                                          union spoolss_DriverInfo *info_p,
6049                                          WERROR *result_p)
6050
6051 {
6052         struct spoolss_GetPrinterDriver2 r;
6053         uint32_t needed;
6054         uint32_t server_major_version;
6055         uint32_t server_minor_version;
6056
6057         r.in.handle = handle;
6058         r.in.architecture = architecture;
6059         r.in.client_major_version = client_major_version;
6060         r.in.client_minor_version = client_minor_version;
6061         r.in.buffer = NULL;
6062         r.in.offered = 0;
6063         r.in.level = level;
6064         r.out.needed = &needed;
6065         r.out.server_major_version = &server_major_version;
6066         r.out.server_minor_version = &server_minor_version;
6067
6068         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6069                 driver_name, r.in.level);
6070
6071         torture_assert_ntstatus_ok(tctx,
6072                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6073                 "failed to call GetPrinterDriver2");
6074         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6075                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6076                 r.in.buffer = &blob;
6077                 r.in.offered = needed;
6078                 torture_assert_ntstatus_ok(tctx,
6079                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6080                         "failed to call GetPrinterDriver2");
6081         }
6082
6083         if (result_p) {
6084                 *result_p = r.out.result;
6085         }
6086
6087         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6088                 switch (r.in.level) {
6089                 case 101:
6090                 case 8:
6091                         torture_comment(tctx,
6092                                 "level %d not implemented, not considering as an error\n",
6093                                 r.in.level);
6094                         return true;
6095                 default:
6096                         break;
6097                 }
6098         }
6099
6100         torture_assert_werr_ok(tctx, r.out.result,
6101                 "failed to call GetPrinterDriver2");
6102
6103         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6104
6105         if (info_p) {
6106                 *info_p = *r.out.info;
6107         }
6108
6109         return true;
6110 }
6111
6112 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6113                                    struct dcerpc_binding_handle *b,
6114                                    struct policy_handle *handle,
6115                                    const char *driver_name,
6116                                    const char *architecture)
6117 {
6118         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6119         int i;
6120
6121
6122         for (i=0;i<ARRAY_SIZE(levels);i++) {
6123
6124                 torture_assert(tctx,
6125                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6126                         "");
6127         }
6128
6129         return true;
6130 }
6131
6132 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6133                                         void *private_data)
6134 {
6135         struct test_spoolss_context *ctx =
6136                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6137         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6138         int i;
6139         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6140         struct dcerpc_binding_handle *b = p->binding_handle;
6141         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6142
6143         for (i=0;i<ARRAY_SIZE(levels);i++) {
6144
6145                 uint32_t count;
6146                 union spoolss_DriverInfo *info;
6147
6148                 torture_assert(tctx,
6149                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6150                         "failed to enumerate drivers");
6151
6152                 if (!info) {
6153                         torture_comment(tctx, "No printer drivers returned\n");
6154                         break;
6155                 }
6156         }
6157
6158         return true;
6159 }
6160
6161 static bool test_DeletePrinter(struct torture_context *tctx,
6162                                struct dcerpc_binding_handle *b,
6163                                struct policy_handle *handle)
6164 {
6165         struct spoolss_DeletePrinter r;
6166
6167         torture_comment(tctx, "Testing DeletePrinter\n");
6168
6169         r.in.handle = handle;
6170
6171         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6172                 "failed to delete printer");
6173         torture_assert_werr_ok(tctx, r.out.result,
6174                 "failed to delete printer");
6175
6176         return true;
6177 }
6178
6179 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6180                                        struct dcerpc_binding_handle *b,
6181                                        uint32_t flags,
6182                                        uint32_t level,
6183                                        const char *name,
6184                                        bool *found)
6185 {
6186         struct spoolss_EnumPrinters e;
6187         uint32_t count;
6188         union spoolss_PrinterInfo *info;
6189         uint32_t needed;
6190         int i;
6191
6192         *found = false;
6193
6194         e.in.flags = flags;
6195         e.in.server = NULL;
6196         e.in.level = level;
6197         e.in.buffer = NULL;
6198         e.in.offered = 0;
6199         e.out.count = &count;
6200         e.out.info = &info;
6201         e.out.needed = &needed;
6202
6203         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6204                 "failed to enum printers");
6205
6206         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6207                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6208                 e.in.buffer = &blob;
6209                 e.in.offered = needed;
6210
6211                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6212                         "failed to enum printers");
6213         }
6214
6215         torture_assert_werr_ok(tctx, e.out.result,
6216                 "failed to enum printers");
6217
6218         for (i=0; i < count; i++) {
6219
6220                 const char *current = NULL;
6221                 const char *q;
6222
6223                 switch (level) {
6224                 case 1:
6225                         current = info[i].info1.name;
6226                         break;
6227                 }
6228
6229                 if (strequal(current, name)) {
6230                         *found = true;
6231                         break;
6232                 }
6233
6234                 q = strrchr(current, '\\');
6235                 if (q) {
6236                         if (!e.in.server) {
6237                                 torture_warning(tctx,
6238                                         "server returns printername %s incl. servername although we did not set servername", current);
6239                         }
6240                         q++;
6241                         if (strequal(q, name)) {
6242                                 *found = true;
6243                                 break;
6244                         }
6245                 }
6246         }
6247
6248         return true;
6249 }
6250
6251 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6252                                       struct dcerpc_pipe *p,
6253                                       const char *printername,
6254                                       bool ex)
6255 {
6256         WERROR result;
6257         struct spoolss_AddPrinter r;
6258         struct spoolss_AddPrinterEx rex;
6259         struct spoolss_SetPrinterInfoCtr info_ctr;
6260         struct spoolss_SetPrinterInfo1 info1;
6261         struct spoolss_DevmodeContainer devmode_ctr;
6262         struct sec_desc_buf secdesc_ctr;
6263         struct spoolss_UserLevelCtr userlevel_ctr;
6264         struct policy_handle handle;
6265         bool found = false;
6266         struct dcerpc_binding_handle *b = p->binding_handle;
6267
6268         ZERO_STRUCT(devmode_ctr);
6269         ZERO_STRUCT(secdesc_ctr);
6270         ZERO_STRUCT(userlevel_ctr);
6271         ZERO_STRUCT(info1);
6272
6273         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6274                         ex ? "Ex":"", printername);
6275
6276         /* try to add printer to wellknown printer list (level 1) */
6277
6278         userlevel_ctr.level = 1;
6279
6280         info_ctr.info.info1 = &info1;
6281         info_ctr.level = 1;
6282
6283         rex.in.server = NULL;
6284         rex.in.info_ctr = &info_ctr;
6285         rex.in.devmode_ctr = &devmode_ctr;
6286         rex.in.secdesc_ctr = &secdesc_ctr;
6287         rex.in.userlevel_ctr = &userlevel_ctr;
6288         rex.out.handle = &handle;
6289
6290         r.in.server = NULL;
6291         r.in.info_ctr = &info_ctr;
6292         r.in.devmode_ctr = &devmode_ctr;
6293         r.in.secdesc_ctr = &secdesc_ctr;
6294         r.out.handle = &handle;
6295
6296         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6297                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6298                 "failed to add printer");
6299         result = ex ? rex.out.result : r.out.result;
6300         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6301                 "unexpected result code");
6302
6303         info1.name = printername;
6304         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6305
6306         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6307                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6308                 "failed to add printer");
6309         result = ex ? rex.out.result : r.out.result;
6310         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6311                 "unexpected result code");
6312
6313         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6314            better do a real check to see the printer is really there */
6315
6316         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6317                                                         PRINTER_ENUM_NETWORK, 1,
6318                                                         printername,
6319                                                         &found),
6320                         "failed to enum printers");
6321
6322         torture_assert(tctx, found, "failed to find newly added printer");
6323
6324         info1.flags = 0;
6325
6326         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6327                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6328                 "failed to add printer");
6329         result = ex ? rex.out.result : r.out.result;
6330         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6331                 "unexpected result code");
6332
6333         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6334            better do a real check to see the printer has really been removed
6335            from the well known printer list */
6336
6337         found = false;
6338
6339         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6340                                                         PRINTER_ENUM_NETWORK, 1,
6341                                                         printername,
6342                                                         &found),
6343                         "failed to enum printers");
6344 #if 0
6345         torture_assert(tctx, !found, "printer still in well known printer list");
6346 #endif
6347         return true;
6348 }
6349
6350 static bool test_AddPrinter_normal(struct torture_context *tctx,
6351                                    struct dcerpc_pipe *p,
6352                                    struct policy_handle *handle_p,
6353                                    const char *printername,
6354                                    const char *drivername,
6355                                    const char *portname,
6356                                    struct spoolss_DeviceMode *devmode,
6357                                    bool ex)
6358 {
6359         WERROR result;
6360         struct spoolss_AddPrinter r;
6361         struct spoolss_AddPrinterEx rex;
6362         struct spoolss_SetPrinterInfoCtr info_ctr;
6363         struct spoolss_SetPrinterInfo2 info2;
6364         struct spoolss_DevmodeContainer devmode_ctr;
6365         struct sec_desc_buf secdesc_ctr;
6366         struct spoolss_UserLevelCtr userlevel_ctr;
6367         struct policy_handle handle;
6368         bool found = false;
6369         bool existing_printer_deleted = false;
6370         struct dcerpc_binding_handle *b = p->binding_handle;
6371
6372         ZERO_STRUCT(devmode_ctr);
6373         ZERO_STRUCT(secdesc_ctr);
6374         ZERO_STRUCT(userlevel_ctr);
6375
6376         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6377                         ex ? "Ex":"", printername);
6378
6379         devmode_ctr.devmode = devmode;
6380
6381         userlevel_ctr.level = 1;
6382
6383         rex.in.server = NULL;
6384         rex.in.info_ctr = &info_ctr;
6385         rex.in.devmode_ctr = &devmode_ctr;
6386         rex.in.secdesc_ctr = &secdesc_ctr;
6387         rex.in.userlevel_ctr = &userlevel_ctr;
6388         rex.out.handle = &handle;
6389
6390         r.in.server = NULL;
6391         r.in.info_ctr = &info_ctr;
6392         r.in.devmode_ctr = &devmode_ctr;
6393         r.in.secdesc_ctr = &secdesc_ctr;
6394         r.out.handle = &handle;
6395
6396  again:
6397
6398         /* try to add printer to printer list (level 2) */
6399
6400         ZERO_STRUCT(info2);
6401
6402         info_ctr.info.info2 = &info2;
6403         info_ctr.level = 2;
6404
6405         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6406                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6407                 "failed to add printer");
6408         result = ex ? rex.out.result : r.out.result;
6409         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6410                 "unexpected result code");
6411
6412         info2.printername = printername;
6413
6414         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6415                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6416                 "failed to add printer");
6417         result = ex ? rex.out.result : r.out.result;
6418
6419         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6420                 struct policy_handle printer_handle;
6421
6422                 if (existing_printer_deleted) {
6423                         torture_fail(tctx, "already deleted printer still existing?");
6424                 }
6425
6426                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6427                         "failed to open printer handle");
6428
6429                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6430                         "failed to delete printer");
6431
6432                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6433                         "failed to close server handle");
6434
6435                 existing_printer_deleted = true;
6436
6437                 goto again;
6438         }
6439
6440         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6441                 "unexpected result code");
6442
6443         info2.portname = portname;
6444
6445         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6446                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6447                 "failed to add printer");
6448         result = ex ? rex.out.result : r.out.result;
6449         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6450                 "unexpected result code");
6451
6452         info2.drivername = drivername;
6453
6454         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6455                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6456                 "failed to add printer");
6457         result = ex ? rex.out.result : r.out.result;
6458
6459         /* w2k8r2 allows to add printer w/o defining printprocessor */
6460
6461         if (!W_ERROR_IS_OK(result)) {
6462                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6463                         "unexpected result code");
6464
6465                 info2.printprocessor = "winprint";
6466
6467                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6468                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6469                         "failed to add printer");
6470                 result = ex ? rex.out.result : r.out.result;
6471                 torture_assert_werr_ok(tctx, result,
6472                         "failed to add printer");
6473         }
6474
6475         *handle_p = handle;
6476
6477         /* we are paranoid, really check if the printer is there now */
6478
6479         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6480                                                         PRINTER_ENUM_LOCAL, 1,
6481                                                         printername,
6482                                                         &found),
6483                         "failed to enum printers");
6484         torture_assert(tctx, found, "failed to find newly added printer");
6485
6486         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6487                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6488                 "failed to add printer");
6489         result = ex ? rex.out.result : r.out.result;
6490         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6491                 "unexpected result code");
6492
6493         return true;
6494 }
6495
6496 static bool test_printer_info(struct torture_context *tctx,
6497                               void *private_data)
6498 {
6499         struct torture_printer_context *t =
6500                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6501         struct dcerpc_pipe *p = t->spoolss_pipe;
6502         struct dcerpc_binding_handle *b = p->binding_handle;
6503
6504         bool ret = true;
6505
6506         if (torture_setting_bool(tctx, "samba3", false)) {
6507                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6508         }
6509
6510         if (!test_PrinterInfo(tctx, b, &t->handle)) {
6511                 ret = false;
6512         }
6513
6514         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6515                 ret = false;
6516         }
6517
6518         return ret;
6519 }
6520
6521 static bool test_EnumPrinterKey(struct torture_context *tctx,
6522                                 struct dcerpc_binding_handle *b,
6523                                 struct policy_handle *handle,
6524                                 const char *key_name,
6525                                 const char ***array)
6526 {
6527         struct spoolss_EnumPrinterKey r;
6528         uint32_t needed = 0;
6529         union spoolss_KeyNames key_buffer;
6530         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6531         uint32_t _ndr_size;
6532         int i;
6533
6534         r.in.handle = handle;
6535         r.in.key_name = key_name;
6536         r.out.key_buffer = &key_buffer;
6537         r.out.needed = &needed;
6538         r.out._ndr_size = &_ndr_size;
6539
6540         for (i=0; i < ARRAY_SIZE(offered); i++) {
6541
6542                 if (offered[i] < 0 && needed) {
6543                         if (needed <= 4) {
6544                                 continue;
6545                         }
6546                         r.in.offered = needed + offered[i];
6547                 } else {
6548                         r.in.offered = offered[i];
6549                 }
6550
6551                 ZERO_STRUCT(key_buffer);
6552
6553                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6554
6555                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6556                         "failed to call EnumPrinterKey");
6557                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
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                         r.in.offered = needed;
6564                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6565                                 "failed to call EnumPrinterKey");
6566                 }
6567
6568                 if (offered[i] > 0) {
6569                         torture_assert_werr_ok(tctx, r.out.result,
6570                                 "failed to call EnumPrinterKey");
6571                 }
6572
6573                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6574                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6575                                 _ndr_size, r.in.offered/2));
6576
6577                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6578                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6579
6580                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6581                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6582
6583                 if (key_buffer.string_array) {
6584                         uint32_t calc_needed = 0;
6585                         int s;
6586                         for (s=0; key_buffer.string_array[s]; s++) {
6587                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6588                         }
6589                         if (!key_buffer.string_array[0]) {
6590                                 calc_needed += 2;
6591                         }
6592                         calc_needed += 2;
6593
6594                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6595                                 "EnumPrinterKey unexpected size");
6596                 }
6597         }
6598
6599         if (array) {
6600                 *array = key_buffer.string_array;
6601         }
6602
6603         return true;
6604 }
6605
6606 bool test_printer_all_keys(struct torture_context *tctx,
6607                            struct dcerpc_binding_handle *b,
6608                            struct policy_handle *handle)
6609 {
6610         const char **key_array = NULL;
6611         int i;
6612
6613         torture_comment(tctx, "Testing Printer Keys\n");
6614
6615         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6616                 "failed to call test_EnumPrinterKey");
6617
6618         for (i=0; key_array && key_array[i]; i++) {
6619                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6620                         "failed to call test_EnumPrinterKey");
6621         }
6622         for (i=0; key_array && key_array[i]; i++) {
6623                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6624                         "failed to call test_EnumPrinterDataEx");
6625         }
6626
6627         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6628
6629         return true;
6630 }
6631
6632 static bool test_csetprinter(struct torture_context *tctx,
6633                              void *private_data)
6634 {
6635         struct torture_printer_context *t =
6636                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6637         struct dcerpc_pipe *p = t->spoolss_pipe;
6638
6639         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
6640         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6641         const char *portname = t->info2.portname;
6642
6643         union spoolss_PrinterInfo info;
6644         struct policy_handle new_handle, new_handle2;
6645         struct dcerpc_binding_handle *b = p->binding_handle;
6646
6647         torture_comment(tctx, "Testing c_setprinter\n");
6648
6649         torture_assert(tctx,
6650                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6651                 "failed to get level 0 printer info");
6652         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6653                 info.info0.c_setprinter);
6654
6655         /* check if c_setprinter on 1st handle increases after a printer has
6656          * been added */
6657
6658         torture_assert(tctx,
6659                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6660                 "failed to add new printer");
6661         torture_assert(tctx,
6662                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6663                 "failed to get level 0 printer info");
6664         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6665                 info.info0.c_setprinter);
6666
6667         /* check if c_setprinter on new handle increases after a printer has
6668          * been added */
6669
6670         torture_assert(tctx,
6671                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6672                 "failed to get level 0 printer info");
6673         torture_comment(tctx, "csetprinter on created handle: %d\n",
6674                 info.info0.c_setprinter);
6675
6676         /* open the new printer and check if c_setprinter increases */
6677
6678         torture_assert(tctx,
6679                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6680                 "failed to open created printer");
6681         torture_assert(tctx,
6682                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6683                 "failed to get level 0 printer info");
6684         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6685                 info.info0.c_setprinter);
6686
6687         /* cleanup */
6688
6689         torture_assert(tctx,
6690                 test_ClosePrinter(tctx, b, &new_handle2),
6691                 "failed to close printer");
6692         torture_assert(tctx,
6693                 test_DeletePrinter(tctx, b, &new_handle),
6694                 "failed to delete new printer");
6695
6696         return true;
6697 }
6698
6699 static bool compose_local_driver_directory(struct torture_context *tctx,
6700                                            const char *environment,
6701                                            const char *local_dir,
6702                                            const char **path)
6703 {
6704         char *p;
6705
6706         p = strrchr(local_dir, '/');
6707         if (!p) {
6708                 return NULL;
6709         }
6710         p++;
6711
6712         if (strequal(environment, "Windows x64")) {
6713                 if (!strequal(p, "x64")) {
6714                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6715                 }
6716         } else if (strequal(environment, "Windows NT x86")) {
6717                 if (!strequal(p, "i386")) {
6718                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6719                 }
6720         } else {
6721                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6722         }
6723
6724         return true;
6725 }
6726
6727 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6728                                                      const char *devicename)
6729 {
6730         struct spoolss_DeviceMode *r;
6731
6732         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6733         if (r == NULL) {
6734                 return NULL;
6735         }
6736
6737         r->devicename           = talloc_strdup(r, devicename);
6738         r->specversion          = DMSPEC_NT4_AND_ABOVE;
6739         r->driverversion        = 0x0600;
6740         r->size                 = 0x00dc;
6741         r->__driverextra_length = 0;
6742         r->fields               = DEVMODE_FORMNAME |
6743                                   DEVMODE_TTOPTION |
6744                                   DEVMODE_PRINTQUALITY |
6745                                   DEVMODE_DEFAULTSOURCE |
6746                                   DEVMODE_COPIES |
6747                                   DEVMODE_SCALE |
6748                                   DEVMODE_PAPERSIZE |
6749                                   DEVMODE_ORIENTATION;
6750         r->orientation          = DMORIENT_PORTRAIT;
6751         r->papersize            = DMPAPER_LETTER;
6752         r->paperlength          = 0;
6753         r->paperwidth           = 0;
6754         r->scale                = 100;
6755         r->copies               = 55;
6756         r->defaultsource        = DMBIN_FORMSOURCE;
6757         r->printquality         = DMRES_HIGH;
6758         r->color                = DMRES_MONOCHROME;
6759         r->duplex               = DMDUP_SIMPLEX;
6760         r->yresolution          = 0;
6761         r->ttoption             = DMTT_SUBDEV;
6762         r->collate              = DMCOLLATE_FALSE;
6763         r->formname             = talloc_strdup(r, "Letter");
6764
6765         return r;
6766 }
6767
6768 static bool test_architecture_buffer(struct torture_context *tctx,
6769                                      void *private_data)
6770 {
6771         struct test_spoolss_context *ctx =
6772                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6773
6774         struct spoolss_OpenPrinterEx r;
6775         struct spoolss_UserLevel1 u1;
6776         struct policy_handle handle;
6777         uint32_t architectures[] = {
6778                 PROCESSOR_ARCHITECTURE_INTEL,
6779                 PROCESSOR_ARCHITECTURE_IA64,
6780                 PROCESSOR_ARCHITECTURE_AMD64
6781         };
6782         uint32_t needed[3];
6783         int i;
6784         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6785         struct dcerpc_binding_handle *b = p->binding_handle;
6786
6787         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6788
6789                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6790
6791                 u1.size = 0;
6792                 u1.client = NULL;
6793                 u1.user = NULL;
6794                 u1.build = 0;
6795                 u1.major = 3;
6796                 u1.minor = 0;
6797                 u1.processor = architectures[i];
6798
6799                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6800                 r.in.datatype           = NULL;
6801                 r.in.devmode_ctr.devmode= NULL;
6802                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6803                 r.in.level               = 1;
6804                 r.in.userlevel.level1   = &u1;
6805                 r.out.handle            = &handle;
6806
6807                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6808                 torture_assert_werr_ok(tctx, r.out.result, "");
6809
6810                 {
6811                         struct spoolss_EnumPrinters e;
6812                         uint32_t count;
6813                         union spoolss_PrinterInfo *info;
6814
6815                         e.in.flags = PRINTER_ENUM_LOCAL;
6816                         e.in.server = NULL;
6817                         e.in.level = 2;
6818                         e.in.buffer = NULL;
6819                         e.in.offered = 0;
6820                         e.out.count = &count;
6821                         e.out.info = &info;
6822                         e.out.needed = &needed[i];
6823
6824                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6825 #if 0
6826                         torture_comment(tctx, "needed was %d\n", needed[i]);
6827 #endif
6828                 }
6829
6830                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6831         }
6832
6833         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6834                 if (needed[i-1] != needed[i]) {
6835                         torture_fail(tctx,
6836                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6837                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6838                 }
6839         }
6840
6841         return true;
6842 }
6843
6844 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
6845                                           void *private_data)
6846 {
6847         struct test_spoolss_context *ctx =
6848                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6849         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6850         struct dcerpc_binding_handle *b = p->binding_handle;
6851
6852         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
6853 }
6854
6855 static bool test_PrintServer_Forms(struct torture_context *tctx,
6856                                    void *private_data)
6857 {
6858         struct test_spoolss_context *ctx =
6859                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6860         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6861         struct dcerpc_binding_handle *b = p->binding_handle;
6862
6863         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
6864 }
6865
6866 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
6867                                        void *private_data)
6868 {
6869         struct test_spoolss_context *ctx =
6870                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6871         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6872         struct dcerpc_binding_handle *b = p->binding_handle;
6873
6874         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
6875 }
6876
6877 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
6878 {
6879         NTSTATUS status;
6880
6881         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
6882
6883         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
6884
6885         torture_assert(tctx,
6886                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
6887                 "failed to open printserver");
6888         torture_assert(tctx,
6889                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
6890                 "failed to get environment");
6891
6892         return true;
6893 }
6894
6895 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
6896 {
6897         struct test_spoolss_context *t;
6898
6899         *data = t = talloc_zero(tctx, struct test_spoolss_context);
6900
6901         return torture_rpc_spoolss_setup_common(tctx, t);
6902 }
6903
6904 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
6905 {
6906         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
6907
6908         return true;
6909 }
6910
6911 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
6912 {
6913         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
6914         bool ret;
6915
6916         ret = torture_rpc_spoolss_teardown_common(tctx, t);
6917         talloc_free(t);
6918
6919         return ret;
6920 }
6921
6922 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
6923 {
6924         struct dcerpc_pipe *p;
6925         struct dcerpc_binding_handle *b;
6926         const char *server_name_slash;
6927         const char *driver_name;
6928         const char *printer_name;
6929         const char *port_name;
6930
6931         torture_assert_ntstatus_ok(tctx,
6932                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
6933                 "Error connecting to server");
6934
6935         p = t->spoolss_pipe;
6936         b = p->binding_handle;
6937         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6938
6939         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
6940         t->driver.info8.driver_name             = TORTURE_DRIVER;
6941         t->driver.info8.driver_path             = "pscript5.dll";
6942         t->driver.info8.data_file               = "cups6.ppd";
6943         t->driver.info8.config_file             = "ps5ui.dll";
6944         t->driver.info8.help_file               = "pscript.hlp";
6945         t->driver.info8.default_datatype        = "RAW";
6946         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
6947         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6948         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6949         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6950         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6951         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6952         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6953         t->driver.info8.dependent_files->string[5] = "cups6.ini";
6954         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6955         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6956
6957         t->driver.local.driver_directory= "/usr/share/cups/drivers";
6958
6959         t->info2.drivername             = "Microsoft XPS Document Writer";
6960         t->info2.portname               = "LPT1:";
6961
6962         printer_name = t->info2.printername;
6963         port_name = t->info2.portname;
6964
6965         torture_assert(tctx,
6966                 fillup_printserver_info(tctx, p, &t->driver),
6967                 "failed to fillup printserver info");
6968
6969         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6970
6971         torture_assert(tctx,
6972                 compose_local_driver_directory(tctx, t->driver.remote.environment,
6973                                                t->driver.local.driver_directory,
6974                                                &t->driver.local.driver_directory),
6975                 "failed to compose local driver directory");
6976
6977         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6978                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
6979                         t->info2.drivername, t->driver.remote.environment);
6980                 t->have_driver = true;
6981                 goto try_add;
6982         }
6983
6984         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6985                 t->info2.drivername, t->driver.remote.environment);
6986         torture_comment(tctx, "trying to upload own driver\n");
6987
6988         if (!directory_exist(t->driver.local.driver_directory)) {
6989                 torture_warning(tctx, "no local driver is available!");
6990                 t->have_driver = false;
6991                 goto try_add;
6992         }
6993
6994         torture_assert(tctx,
6995                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6996                 "failed to upload printer driver");
6997
6998         torture_assert(tctx,
6999                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
7000                 "failed to add driver");
7001
7002         t->added_driver = true;
7003         t->have_driver = true;
7004
7005  try_add:
7006         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7007
7008         if (t->wellknown) {
7009                 torture_assert(tctx,
7010                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7011                         "failed to add wellknown printer");
7012         } else {
7013                 torture_assert(tctx,
7014                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7015                         "failed to add printer");
7016         }
7017
7018         return true;
7019 }
7020
7021 static bool torture_rpc_spoolss_printer_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                   = false;
7028         t->wellknown            = false;
7029         t->info2.printername    = TORTURE_PRINTER;
7030         t->devmode              = NULL;
7031
7032         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7033 }
7034
7035 static bool torture_rpc_spoolss_printerex_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                   = true;
7042         t->wellknown            = false;
7043         t->info2.printername    = TORTURE_PRINTER_EX;
7044         t->devmode              = NULL;
7045
7046         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7047 }
7048
7049 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7050 {
7051         struct torture_printer_context *t;
7052
7053         *data = t = talloc_zero(tctx, struct torture_printer_context);
7054
7055         t->ex                   = false;
7056         t->wellknown            = true;
7057         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
7058         t->devmode              = NULL;
7059
7060         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7061                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7062         }
7063
7064         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7065 }
7066
7067 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7068 {
7069         struct torture_printer_context *t;
7070
7071         *data = t = talloc_zero(tctx, struct torture_printer_context);
7072
7073         t->ex                   = true;
7074         t->wellknown            = true;
7075         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7076         t->devmode              = NULL;
7077
7078         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7079                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7080         }
7081
7082         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7083 }
7084
7085 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7086 {
7087         struct torture_printer_context *t;
7088
7089         *data = t = talloc_zero(tctx, struct torture_printer_context);
7090
7091         t->ex                   = true;
7092         t->wellknown            = false;
7093         t->info2.printername    = TORTURE_PRINTER_EX;
7094         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7095
7096         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7097 }
7098
7099 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7100 {
7101         bool found = false;
7102         struct dcerpc_pipe *p = t->spoolss_pipe;
7103         struct dcerpc_binding_handle *b;
7104         const char *printer_name = t->info2.printername;
7105
7106         if (t->added_driver) {
7107                 torture_assert(tctx,
7108                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7109                         "failed to remove printer driver");
7110         }
7111
7112         if (p) {
7113                 b = p->binding_handle;
7114         }
7115
7116         if (!t->wellknown) {
7117                 torture_assert(tctx,
7118                         test_DeletePrinter(tctx, b, &t->handle),
7119                         "failed to delete printer");
7120
7121                 torture_assert(tctx,
7122                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7123                                                    printer_name, &found),
7124                         "failed to enumerate printers");
7125
7126                 torture_assert(tctx, !found, "deleted printer still there");
7127         }
7128
7129         return true;
7130 }
7131
7132 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7133 {
7134         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7135         bool ret;
7136
7137         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7138         talloc_free(t);
7139
7140         return ret;
7141 }
7142
7143 static bool test_print_test(struct torture_context *tctx,
7144                             void *private_data)
7145 {
7146         struct torture_printer_context *t =
7147                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7148         struct dcerpc_pipe *p = t->spoolss_pipe;
7149         struct dcerpc_binding_handle *b = p->binding_handle;
7150
7151         torture_assert(tctx,
7152                 test_PausePrinter(tctx, b, &t->handle),
7153                 "failed to pause printer");
7154
7155         torture_assert(tctx,
7156                 test_DoPrintTest(tctx, b, &t->handle),
7157                 "failed to do print test");
7158
7159         torture_assert(tctx,
7160                 test_ResumePrinter(tctx, b, &t->handle),
7161                 "failed to resume printer");
7162
7163         return true;
7164 }
7165
7166 static bool test_print_test_extended(struct torture_context *tctx,
7167                                      void *private_data)
7168 {
7169         struct torture_printer_context *t =
7170                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7171         struct dcerpc_pipe *p = t->spoolss_pipe;
7172         struct dcerpc_binding_handle *b = p->binding_handle;
7173         bool ret = true;
7174
7175         torture_assert(tctx,
7176                 test_PausePrinter(tctx, b, &t->handle),
7177                 "failed to pause printer");
7178
7179         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7180         if (ret == false) {
7181                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7182                 if (torture_setting_bool(tctx, "samba3", false)) {
7183                         torture_comment(tctx, "non-critical for samba3\n");
7184                         ret = true;
7185                         tctx->last_result = TORTURE_SKIP;
7186                 }
7187         }
7188
7189         torture_assert(tctx,
7190                 test_ResumePrinter(tctx, b, &t->handle),
7191                 "failed to resume printer");
7192
7193         return ret;
7194 }
7195
7196 static bool test_printer_sd(struct torture_context *tctx,
7197                             void *private_data)
7198 {
7199         struct torture_printer_context *t =
7200                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7201         struct dcerpc_pipe *p = t->spoolss_pipe;
7202         struct dcerpc_binding_handle *b = p->binding_handle;
7203
7204         torture_assert(tctx,
7205                 test_PrinterInfo_SD(tctx, b, &t->handle),
7206                 "failed to test security descriptors");
7207
7208         return true;
7209 }
7210
7211 static bool test_printer_dm(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_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7220                 "failed to test devicemodes");
7221
7222         return true;
7223 }
7224
7225 static bool test_printer_info_winreg(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_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7234                 "failed to test printer info winreg");
7235
7236         return true;
7237 }
7238
7239 static bool test_printer_change_id(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
7246         torture_assert(tctx,
7247                 test_ChangeID(tctx, p, &t->handle),
7248                 "failed to test change id");
7249
7250         return true;
7251 }
7252
7253 static bool test_printer_keys(struct torture_context *tctx,
7254                               void *private_data)
7255 {
7256         struct torture_printer_context *t =
7257                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7258         struct dcerpc_pipe *p = t->spoolss_pipe;
7259         struct dcerpc_binding_handle *b = p->binding_handle;
7260
7261         torture_assert(tctx,
7262                 test_printer_all_keys(tctx, b, &t->handle),
7263                 "failed to test printer keys");
7264
7265         return true;
7266 }
7267
7268 static bool test_printer_data_consistency(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_EnumPrinterData_consistency(tctx, p, &t->handle),
7277                 "failed to test printer data consistency");
7278
7279         return true;
7280 }
7281
7282 static bool test_printer_data_keys(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_keys(tctx, p, &t->handle),
7291                 "failed to test printer data keys");
7292
7293         return true;
7294 }
7295
7296 static bool test_printer_data_values(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_values(tctx, p, &t->handle),
7305                 "failed to test printer data values");
7306
7307         return true;
7308 }
7309
7310 static bool test_printer_data_set(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_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7319                 "failed to test printer data set");
7320
7321         return true;
7322 }
7323
7324 static bool test_printer_data_winreg(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_winreg(tctx, p, &t->handle, t->info2.printername),
7333                 "failed to test printer data winreg");
7334
7335         return true;
7336 }
7337
7338 static bool test_printer_data_dsspooler(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
7345         torture_assert(tctx,
7346                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7347                 "failed to test printer data winreg dsspooler");
7348
7349         return true;
7350 }
7351
7352 static bool test_driver_info_winreg(struct torture_context *tctx,
7353                                     void *private_data)
7354 {
7355         struct torture_printer_context *t =
7356                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7357         struct dcerpc_pipe *p = t->spoolss_pipe;
7358         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7359
7360         if (!t->have_driver) {
7361                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7362         }
7363
7364         torture_assert(tctx,
7365                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7366                 "failed to test driver info winreg");
7367
7368         return true;
7369 }
7370
7371 void torture_tcase_printer(struct torture_tcase *tcase)
7372 {
7373         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7374         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7375         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7376         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7377         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7378         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7379         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7380         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7381         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7382         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7383         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7384         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7385         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7386         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7387         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7388         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7389         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7390 }
7391
7392 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7393 {
7394         struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
7395         struct torture_tcase *tcase;
7396
7397         tcase = torture_suite_add_tcase(suite, "addprinter");
7398
7399         torture_tcase_set_fixture(tcase,
7400                                   torture_rpc_spoolss_printer_setup,
7401                                   torture_rpc_spoolss_printer_teardown);
7402
7403         torture_tcase_printer(tcase);
7404
7405         tcase = torture_suite_add_tcase(suite, "addprinterex");
7406
7407         torture_tcase_set_fixture(tcase,
7408                                   torture_rpc_spoolss_printerex_setup,
7409                                   torture_rpc_spoolss_printer_teardown);
7410
7411         torture_tcase_printer(tcase);
7412
7413         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7414
7415         torture_tcase_set_fixture(tcase,
7416                                   torture_rpc_spoolss_printerwkn_setup,
7417                                   torture_rpc_spoolss_printer_teardown);
7418
7419         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7420
7421         torture_tcase_set_fixture(tcase,
7422                                   torture_rpc_spoolss_printerexwkn_setup,
7423                                   torture_rpc_spoolss_printer_teardown);
7424
7425 #if 0
7426         /* test is not correct */
7427         tcase = torture_suite_add_tcase(suite, "addprinterdm");
7428
7429         torture_tcase_set_fixture(tcase,
7430                                   torture_rpc_spoolss_printerdm_setup,
7431                                   torture_rpc_spoolss_printer_teardown);
7432
7433         torture_tcase_printer(tcase);
7434 #endif
7435         return suite;
7436 }
7437
7438 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7439 {
7440         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7441         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7442
7443         torture_tcase_set_fixture(tcase,
7444                                   torture_rpc_spoolss_setup,
7445                                   torture_rpc_spoolss_teardown);
7446
7447         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7448         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7449         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7450         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7451         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7452         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7453         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7454         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7455         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7456         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7457         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7458         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7459         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7460         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7461         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7462         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7463         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7464         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7465         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7466
7467         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7468
7469         return suite;
7470 }
7471
7472 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7473                                                   struct dcerpc_binding_handle *b,
7474                                                   const char *server,
7475                                                   const char *environment,
7476                                                   const char **dir_p)
7477 {
7478         struct spoolss_GetPrinterDriverDirectory r;
7479         uint32_t needed;
7480
7481         r.in.server             = server;
7482         r.in.environment        = environment;
7483         r.in.level              = 1;
7484         r.in.buffer             = NULL;
7485         r.in.offered            = 0;
7486         r.out.needed            = &needed;
7487
7488         torture_assert_ntstatus_ok(tctx,
7489                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7490                 "failed to query driver directory");
7491
7492         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7493                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7494                 r.in.buffer = &blob;
7495                 r.in.offered = needed;
7496
7497                 torture_assert_ntstatus_ok(tctx,
7498                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7499                         "failed to query driver directory");
7500         }
7501
7502         torture_assert_werr_ok(tctx, r.out.result,
7503                 "failed to query driver directory");
7504
7505         if (dir_p) {
7506                 *dir_p = r.out.info->info1.directory_name;
7507         }
7508
7509         return true;
7510 }
7511
7512 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7513 {
7514         if (info_ctr == NULL) {
7515                 return NULL;
7516         }
7517
7518         switch (info_ctr->level) {
7519         case 1:
7520                 return info_ctr->info.info1->driver_name;
7521         case 2:
7522                 return info_ctr->info.info2->driver_name;
7523         case 3:
7524                 return info_ctr->info.info3->driver_name;
7525         case 4:
7526                 return info_ctr->info.info4->driver_name;
7527         case 6:
7528                 return info_ctr->info.info6->driver_name;
7529         case 8:
7530                 return info_ctr->info.info8->driver_name;
7531         default:
7532                 return NULL;
7533         }
7534 }
7535
7536 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7537 {
7538         if (info_ctr == NULL) {
7539                 return NULL;
7540         }
7541
7542         switch (info_ctr->level) {
7543         case 2:
7544                 return info_ctr->info.info2->architecture;
7545         case 3:
7546                 return info_ctr->info.info3->architecture;
7547         case 4:
7548                 return info_ctr->info.info4->architecture;
7549         case 6:
7550                 return info_ctr->info.info6->architecture;
7551         case 8:
7552                 return info_ctr->info.info8->architecture;
7553         default:
7554                 return NULL;
7555         }
7556 }
7557
7558
7559 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7560                                       struct dcerpc_binding_handle *b,
7561                                       const char *servername,
7562                                       struct spoolss_AddDriverInfoCtr *info_ctr,
7563                                       WERROR expected_result)
7564 {
7565         struct spoolss_AddPrinterDriver r;
7566         const char *drivername = get_driver_from_info(info_ctr);
7567         const char *environment = get_environment_from_info(info_ctr);
7568
7569         r.in.servername = servername;
7570         r.in.info_ctr = info_ctr;
7571
7572         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7573                 drivername, info_ctr->level, environment);
7574
7575         torture_assert_ntstatus_ok(tctx,
7576                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7577                 "spoolss_AddPrinterDriver failed");
7578         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7579                 "spoolss_AddPrinterDriver failed with unexpected result");
7580
7581         return true;
7582
7583 }
7584
7585 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7586                                         struct dcerpc_binding_handle *b,
7587                                         const char *servername,
7588                                         struct spoolss_AddDriverInfoCtr *info_ctr,
7589                                         uint32_t flags,
7590                                         WERROR expected_result)
7591 {
7592         struct spoolss_AddPrinterDriverEx r;
7593         const char *drivername = get_driver_from_info(info_ctr);
7594         const char *environment = get_environment_from_info(info_ctr);
7595
7596         r.in.servername = servername;
7597         r.in.info_ctr = info_ctr;
7598         r.in.flags = flags;
7599
7600         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7601                 drivername, info_ctr->level, environment);
7602
7603         torture_assert_ntstatus_ok(tctx,
7604                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7605                 "AddPrinterDriverEx failed");
7606         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7607                 "AddPrinterDriverEx failed with unexpected result");
7608
7609         return true;
7610 }
7611
7612 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7613                                                struct dcerpc_binding_handle *b,
7614                                                const char *server_name,
7615                                                struct spoolss_AddDriverInfo8 *r,
7616                                                uint32_t flags,
7617                                                bool ex)
7618 {
7619         struct spoolss_AddDriverInfoCtr info_ctr;
7620         struct spoolss_AddDriverInfo1 info1;
7621
7622         ZERO_STRUCT(info1);
7623
7624         info_ctr.level = 1;
7625         info_ctr.info.info1 = &info1;
7626
7627         if (ex) {
7628                 torture_assert(tctx,
7629                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7630                         "failed to test AddPrinterDriverEx level 1");
7631         } else {
7632                 torture_assert(tctx,
7633                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7634                         "failed to test AddPrinterDriver level 1");
7635         }
7636
7637         info1.driver_name = r->driver_name;
7638
7639         if (ex) {
7640                 torture_assert(tctx,
7641                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7642                         "failed to test AddPrinterDriverEx level 1");
7643         } else {
7644                 torture_assert(tctx,
7645                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7646                         "failed to test AddPrinterDriver level 1");
7647         }
7648
7649         return true;
7650 }
7651
7652 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7653                                                struct dcerpc_binding_handle *b,
7654                                                const char *server_name,
7655                                                struct spoolss_AddDriverInfo8 *r,
7656                                                uint32_t flags,
7657                                                bool ex)
7658 {
7659         struct spoolss_AddDriverInfoCtr info_ctr;
7660         struct spoolss_AddDriverInfo2 info2;
7661
7662         ZERO_STRUCT(info2);
7663
7664         info_ctr.level = 2;
7665         info_ctr.info.info2 = &info2;
7666
7667         if (ex) {
7668                 torture_assert(tctx,
7669                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7670                         "failed to test AddPrinterDriverEx level 2");
7671         } else {
7672                 torture_assert(tctx,
7673                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7674                         "failed to test AddPrinterDriver level 2");
7675         }
7676
7677         info2.driver_name = r->driver_name;
7678
7679         if (ex) {
7680                 torture_assert(tctx,
7681                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7682                         "failed to test AddPrinterDriverEx level 2");
7683         } else {
7684                 torture_assert(tctx,
7685                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7686                         "failed to test AddPrinterDriver level 2");
7687         }
7688
7689         info2.version = r->version;
7690
7691         if (ex) {
7692                 torture_assert(tctx,
7693                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7694                         "failed to test AddPrinterDriverEx level 2");
7695         } else {
7696                 torture_assert(tctx,
7697                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7698                         "failed to test AddPrinterDriver level 2");
7699         }
7700
7701         info2.architecture = r->architecture;
7702
7703         if (ex) {
7704                 torture_assert(tctx,
7705                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7706                         "failed to test AddPrinterDriverEx level 2");
7707         } else {
7708                 torture_assert(tctx,
7709                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7710                         "failed to test AddPrinterDriver level 2");
7711         }
7712
7713         info2.driver_path = r->driver_path;
7714
7715         if (ex) {
7716                 torture_assert(tctx,
7717                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7718                         "failed to test AddPrinterDriverEx level 2");
7719         } else {
7720                 torture_assert(tctx,
7721                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7722                         "failed to test AddPrinterDriver level 2");
7723         }
7724
7725         info2.data_file = r->data_file;
7726
7727         if (ex) {
7728                 torture_assert(tctx,
7729                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7730                         "failed to test AddPrinterDriverEx level 2");
7731         } else {
7732                 torture_assert(tctx,
7733                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7734                         "failed to test AddPrinterDriver level 2");
7735         }
7736
7737         info2.config_file = r->config_file;
7738
7739         if (ex) {
7740                 torture_assert(tctx,
7741                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7742                         "failed to test AddPrinterDriverEx");
7743         }
7744
7745         if (ex) {
7746                 torture_assert(tctx,
7747                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7748                         "failed to test AddPrinterDriverEx level 2");
7749         } else {
7750                 torture_assert(tctx,
7751                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7752                         "failed to test AddPrinterDriver level 2");
7753         }
7754
7755         torture_assert(tctx,
7756                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7757                 "failed to find added printer driver");
7758
7759         return true;
7760 }
7761
7762 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7763                                                struct dcerpc_binding_handle *b,
7764                                                const char *server_name,
7765                                                struct spoolss_AddDriverInfo8 *r,
7766                                                uint32_t flags,
7767                                                bool ex)
7768 {
7769         struct spoolss_AddDriverInfoCtr info_ctr;
7770         struct spoolss_AddDriverInfo3 info3;
7771
7772         info3.driver_name       = r->driver_name;
7773         info3.version           = r->version;
7774         info3.architecture      = r->architecture;
7775         info3.driver_path       = r->driver_path;
7776         info3.data_file         = r->data_file;
7777         info3.config_file       = r->config_file;
7778         info3.help_file         = r->help_file;
7779         info3.monitor_name      = r->monitor_name;
7780         info3.default_datatype  = r->default_datatype;
7781         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7782         info3.dependent_files   = r->dependent_files;
7783
7784         info_ctr.level = 3;
7785         info_ctr.info.info3 = &info3;
7786
7787         if (ex) {
7788                 torture_assert(tctx,
7789                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7790                         "failed to test AddPrinterDriverEx level 3");
7791         } else {
7792                 torture_assert(tctx,
7793                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7794                         "failed to test AddPrinterDriver level 3");
7795         }
7796
7797         torture_assert(tctx,
7798                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7799                 "failed to find added printer driver");
7800
7801         return true;
7802 }
7803
7804 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7805                                                struct dcerpc_binding_handle *b,
7806                                                const char *server_name,
7807                                                struct spoolss_AddDriverInfo8 *r,
7808                                                uint32_t flags,
7809                                                bool ex)
7810 {
7811         struct spoolss_AddDriverInfoCtr info_ctr;
7812         struct spoolss_AddDriverInfo4 info4;
7813
7814         info4.version           = r->version;
7815         info4.driver_name       = r->driver_name;
7816         info4.architecture      = r->architecture;
7817         info4.driver_path       = r->driver_path;
7818         info4.data_file         = r->data_file;
7819         info4.config_file       = r->config_file;
7820         info4.help_file         = r->help_file;
7821         info4.monitor_name      = r->monitor_name;
7822         info4.default_datatype  = r->default_datatype;
7823         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7824         info4.dependent_files   = r->dependent_files;
7825         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7826         info4.previous_names = r->previous_names;
7827
7828         info_ctr.level = 4;
7829         info_ctr.info.info4 = &info4;
7830
7831         if (ex) {
7832                 torture_assert(tctx,
7833                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7834                         "failed to test AddPrinterDriverEx level 4");
7835         } else {
7836                 torture_assert(tctx,
7837                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7838                         "failed to test AddPrinterDriver level 4");
7839         }
7840
7841         torture_assert(tctx,
7842                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7843                 "failed to find added printer driver");
7844
7845         return true;
7846 }
7847
7848 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7849                                                struct dcerpc_binding_handle *b,
7850                                                const char *server_name,
7851                                                struct spoolss_AddDriverInfo8 *r,
7852                                                uint32_t flags,
7853                                                bool ex)
7854 {
7855         struct spoolss_AddDriverInfoCtr info_ctr;
7856         struct spoolss_AddDriverInfo6 info6;
7857
7858         info6.version           = r->version;
7859         info6.driver_name       = r->driver_name;
7860         info6.architecture      = r->architecture;
7861         info6.driver_path       = r->driver_path;
7862         info6.data_file         = r->data_file;
7863         info6.config_file       = r->config_file;
7864         info6.help_file         = r->help_file;
7865         info6.monitor_name      = r->monitor_name;
7866         info6.default_datatype  = r->default_datatype;
7867         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7868         info6.dependent_files   = r->dependent_files;
7869         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7870         info6.previous_names    = r->previous_names;
7871         info6.driver_date       = r->driver_date;
7872         info6.driver_version    = r->driver_version;
7873         info6.manufacturer_name = r->manufacturer_name;
7874         info6.manufacturer_url  = r->manufacturer_url;
7875         info6.hardware_id       = r->hardware_id;
7876         info6.provider          = r->provider;
7877
7878         info_ctr.level = 6;
7879         info_ctr.info.info6 = &info6;
7880
7881         if (ex) {
7882                 torture_assert(tctx,
7883                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7884                         "failed to test AddPrinterDriverEx level 6");
7885         } else {
7886                 torture_assert(tctx,
7887                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7888                         "failed to test AddPrinterDriver level 6");
7889         }
7890
7891         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7892
7893         if (!ex) {
7894                 return true;
7895         }
7896
7897         torture_assert(tctx,
7898                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7899                 "failed to find added printer driver");
7900
7901         return true;
7902 }
7903
7904 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7905                                                struct dcerpc_binding_handle *b,
7906                                                const char *server_name,
7907                                                struct spoolss_AddDriverInfo8 *r,
7908                                                uint32_t flags,
7909                                                bool ex)
7910 {
7911         struct spoolss_AddDriverInfoCtr info_ctr;
7912
7913         info_ctr.level = 8;
7914         info_ctr.info.info8 = r;
7915
7916         if (ex) {
7917                 torture_assert(tctx,
7918                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7919                         "failed to test AddPrinterDriverEx level 8");
7920         } else {
7921                 torture_assert(tctx,
7922                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7923                         "failed to test AddPrinterDriver level 8");
7924         }
7925
7926         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7927
7928         if (!ex) {
7929                 return true;
7930         }
7931
7932         torture_assert(tctx,
7933                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7934                 "failed to find added printer driver");
7935
7936         return true;
7937 }
7938
7939 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7940                                          struct dcerpc_binding_handle *b,
7941                                          const char *server,
7942                                          const char *driver,
7943                                          const char *environment,
7944                                          WERROR expected_result)
7945 {
7946         struct spoolss_DeletePrinterDriver r;
7947
7948         r.in.server = server;
7949         r.in.architecture = environment;
7950         r.in.driver = driver;
7951
7952         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7953
7954         torture_assert_ntstatus_ok(tctx,
7955                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7956                 "DeletePrinterDriver failed");
7957         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7958                 "DeletePrinterDriver failed with unexpected result");
7959
7960         return true;
7961 }
7962
7963 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7964                                            struct dcerpc_binding_handle *b,
7965                                            const char *server,
7966                                            const char *driver,
7967                                            const char *environment,
7968                                            uint32_t delete_flags,
7969                                            uint32_t version,
7970                                            WERROR expected_result)
7971 {
7972         struct spoolss_DeletePrinterDriverEx r;
7973
7974         r.in.server = server;
7975         r.in.architecture = environment;
7976         r.in.driver = driver;
7977         r.in.delete_flags = delete_flags;
7978         r.in.version = version;
7979
7980         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7981
7982         torture_assert_ntstatus_ok(tctx,
7983                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7984                 "DeletePrinterDriverEx failed");
7985         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7986                 "DeletePrinterDriverEx failed with unexpected result");
7987
7988         return true;
7989 }
7990
7991 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7992                                      struct dcerpc_binding_handle *b,
7993                                      const char *server_name,
7994                                      const char *driver,
7995                                      const char *environment)
7996 {
7997         torture_assert(tctx,
7998                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7999                 "failed to delete driver");
8000
8001         torture_assert(tctx,
8002                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8003                 "failed to delete driver");
8004
8005         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8006                 torture_fail(tctx, "deleted driver still enumerated");
8007         }
8008
8009         torture_assert(tctx,
8010                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8011                 "2nd delete failed");
8012
8013         return true;
8014 }
8015
8016 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8017                                        struct dcerpc_binding_handle *b,
8018                                        const char *server_name,
8019                                        const char *driver,
8020                                        const char *environment,
8021                                        uint32_t delete_flags,
8022                                        uint32_t version)
8023 {
8024         torture_assert(tctx,
8025                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8026                 "failed to delete driver");
8027
8028         torture_assert(tctx,
8029                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8030                 "failed to delete driver");
8031
8032         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8033                 torture_fail(tctx, "deleted driver still enumerated");
8034         }
8035
8036         torture_assert(tctx,
8037                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8038                 "2nd delete failed");
8039
8040         return true;
8041 }
8042
8043 static bool test_PrinterDriver_args(struct torture_context *tctx,
8044                                     struct dcerpc_binding_handle *b,
8045                                     const char *server_name,
8046                                     uint32_t level,
8047                                     struct spoolss_AddDriverInfo8 *r,
8048                                     uint32_t add_flags,
8049                                     uint32_t delete_flags,
8050                                     uint32_t delete_version,
8051                                     bool ex)
8052 {
8053         bool ret = true;
8054
8055         switch (level) {
8056         case 1:
8057                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
8058                 break;
8059         case 2:
8060                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
8061                 break;
8062         case 3:
8063                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
8064                 break;
8065         case 4:
8066                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
8067                 break;
8068         case 6:
8069                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
8070                 break;
8071         case 8:
8072                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
8073                 break;
8074         default:
8075                 return false;
8076         }
8077
8078         if (ret == false) {
8079                 return ret;
8080         }
8081
8082         if (level == 1) {
8083                 return ret;
8084         }
8085
8086         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8087
8088         if (!ex && (level == 6 || level == 8)) {
8089                 return ret;
8090         }
8091
8092         if (ex) {
8093                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8094         } else {
8095                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8096         }
8097 }
8098
8099 static bool fillup_printserver_info(struct torture_context *tctx,
8100                                     struct dcerpc_pipe *p,
8101                                     struct torture_driver_context *d)
8102 {
8103         struct policy_handle server_handle;
8104         struct dcerpc_binding_handle *b = p->binding_handle;
8105         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8106
8107         torture_assert(tctx,
8108                 test_OpenPrinter_server(tctx, p, &server_handle),
8109                 "failed to open printserver");
8110         torture_assert(tctx,
8111                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8112                 "failed to get environment");
8113         torture_assert(tctx,
8114                 test_ClosePrinter(tctx, b, &server_handle),
8115                 "failed to close printserver");
8116
8117         torture_assert(tctx,
8118                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8119                         d->local.environment ? d->local.environment : d->remote.environment,
8120                         &d->remote.driver_directory),
8121                 "failed to get driver directory");
8122
8123         return true;
8124 }
8125
8126 static const char *driver_directory_dir(const char *driver_directory)
8127 {
8128         char *p;
8129
8130         p = strrchr(driver_directory, '\\');
8131         if (p) {
8132                 return p+1;
8133         }
8134
8135         return NULL;
8136 }
8137
8138 static const char *driver_directory_share(struct torture_context *tctx,
8139                                           const char *driver_directory)
8140 {
8141         const char *p;
8142         char *tok;
8143
8144         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8145                 driver_directory += 2;
8146         }
8147
8148         p = talloc_strdup(tctx, driver_directory);
8149
8150         torture_assert(tctx,
8151                 next_token_talloc(tctx, &p, &tok, "\\"),
8152                 "cannot explode uri");
8153         torture_assert(tctx,
8154                 next_token_talloc(tctx, &p, &tok, "\\"),
8155                 "cannot explode uri");
8156
8157         return tok;
8158 }
8159
8160 static bool upload_printer_driver_file(struct torture_context *tctx,
8161                                        struct smbcli_state *cli,
8162                                        struct torture_driver_context *d,
8163                                        const char *file_name)
8164 {
8165         XFILE *f;
8166         int fnum;
8167         uint8_t *buf;
8168         int maxwrite = 64512;
8169         off_t nread = 0;
8170         size_t start = 0;
8171         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8172         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8173         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8174
8175         if (!file_name) {
8176                 return true;
8177         }
8178
8179         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8180
8181         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8182         if (fnum == -1) {
8183                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8184         }
8185
8186         f = x_fopen(local_name, O_RDONLY, 0);
8187         if (f == NULL) {
8188                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8189         }
8190
8191         buf = talloc_array(tctx, uint8_t, maxwrite);
8192         if (!buf) {
8193                 return false;
8194         }
8195
8196         while (!x_feof(f)) {
8197                 int n = maxwrite;
8198                 int ret;
8199
8200                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8201                         if((n == 0) && x_feof(f))
8202                                 break; /* Empty local file. */
8203
8204                         torture_warning(tctx,
8205                                 "failed to read file: %s\n", strerror(errno));
8206                         break;
8207                 }
8208
8209                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8210
8211                 if (n != ret) {
8212                         torture_warning(tctx,
8213                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8214                         break;
8215                 }
8216
8217                 nread += n;
8218         }
8219
8220         x_fclose(f);
8221
8222         torture_assert_ntstatus_ok(tctx,
8223                 smbcli_close(cli->tree, fnum),
8224                 "failed to close file");
8225
8226         return true;
8227 }
8228
8229 static bool connect_printer_driver_share(struct torture_context *tctx,
8230                                          const char *server_name,
8231                                          const char *share_name,
8232                                          struct smbcli_state **cli)
8233 {
8234         struct smbcli_options smb_options;
8235         struct smbcli_session_options smb_session_options;
8236
8237         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8238                 share_name, server_name);
8239
8240         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8241         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8242
8243         torture_assert_ntstatus_ok(tctx,
8244                 smbcli_full_connection(tctx, cli, server_name,
8245                                         lpcfg_smb_ports(tctx->lp_ctx),
8246                                         share_name, NULL,
8247                                         lpcfg_socket_options(tctx->lp_ctx),
8248                                         cmdline_credentials,
8249                                         lpcfg_resolve_context(tctx->lp_ctx),
8250                                         tctx->ev,
8251                                         &smb_options,
8252                                         &smb_session_options,
8253                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8254                 "failed to open driver share");
8255
8256         return true;
8257 }
8258
8259 static bool upload_printer_driver(struct torture_context *tctx,
8260                                   const char *server_name,
8261                                   struct torture_driver_context *d)
8262 {
8263         struct smbcli_state *cli;
8264         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8265         int i;
8266
8267         torture_assert(tctx,
8268                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8269                 "failed to connect to driver share");
8270
8271         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8272                 server_name, share_name);
8273
8274         torture_assert(tctx,
8275                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8276                 "failed to upload driver_path");
8277         torture_assert(tctx,
8278                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8279                 "failed to upload data_file");
8280         torture_assert(tctx,
8281                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8282                 "failed to upload config_file");
8283         torture_assert(tctx,
8284                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8285                 "failed to upload help_file");
8286         if (d->info8.dependent_files) {
8287                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8288                         torture_assert(tctx,
8289                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8290                                 "failed to upload dependent_files");
8291                 }
8292         }
8293
8294         talloc_free(cli);
8295
8296         return true;
8297 }
8298
8299 static bool remove_printer_driver_file(struct torture_context *tctx,
8300                                        struct smbcli_state *cli,
8301                                        struct torture_driver_context *d,
8302                                        const char *file_name)
8303 {
8304         const char *remote_name;
8305         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
8306
8307         if (!file_name) {
8308                 return true;
8309         }
8310
8311         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8312
8313         torture_comment(tctx, "Removing %s\n", remote_name);
8314
8315         torture_assert_ntstatus_ok(tctx,
8316                 smbcli_unlink(cli->tree, remote_name),
8317                 "failed to unlink");
8318
8319         return true;
8320 }
8321
8322 static bool remove_printer_driver(struct torture_context *tctx,
8323                                   const char *server_name,
8324                                   struct torture_driver_context *d)
8325 {
8326         struct smbcli_state *cli;
8327         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8328         int i;
8329
8330         torture_assert(tctx,
8331                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8332                 "failed to connect to driver share");
8333
8334         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8335                 server_name, share_name);
8336
8337         torture_assert(tctx,
8338                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8339                 "failed to remove driver_path");
8340         torture_assert(tctx,
8341                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8342                 "failed to remove data_file");
8343         torture_assert(tctx,
8344                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8345                 "failed to remove config_file");
8346         torture_assert(tctx,
8347                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8348                 "failed to remove help_file");
8349         if (d->info8.dependent_files) {
8350                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8351                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8352                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8353                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8354                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8355                                 continue;
8356                         }
8357                         torture_assert(tctx,
8358                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8359                                 "failed to remove dependent_files");
8360                 }
8361         }
8362
8363         talloc_free(cli);
8364
8365         return true;
8366
8367 }
8368
8369 static bool test_add_driver_arg(struct torture_context *tctx,
8370                                 struct dcerpc_pipe *p,
8371                                 struct torture_driver_context *d)
8372 {
8373         bool ret = true;
8374         struct dcerpc_binding_handle *b = p->binding_handle;
8375         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8376         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8377         int i;
8378         struct spoolss_AddDriverInfo8 info8;
8379         uint32_t add_flags = APD_COPY_NEW_FILES;
8380         uint32_t delete_flags = 0;
8381
8382         ZERO_STRUCT(info8);
8383
8384         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8385                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8386
8387         torture_assert(tctx,
8388                 fillup_printserver_info(tctx, p, d),
8389                 "failed to fillup printserver info");
8390
8391         if (!directory_exist(d->local.driver_directory)) {
8392                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8393         }
8394
8395         torture_assert(tctx,
8396                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8397                 "failed to upload printer driver");
8398
8399         info8.version           = d->info8.version;
8400         info8.driver_name       = d->info8.driver_name;
8401         info8.architecture      = d->local.environment;
8402         info8.driver_path       = d->info8.driver_path;
8403         info8.data_file         = d->info8.data_file;
8404         info8.config_file       = d->info8.config_file;
8405
8406         for (i=0; i < ARRAY_SIZE(levels); i++) {
8407
8408                 if (torture_setting_bool(tctx, "samba3", false)) {
8409                         switch (levels[i]) {
8410                         case 2:
8411                         case 4:
8412                         case 8:
8413                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8414                                 continue;
8415                         default:
8416                                 break;
8417                         }
8418                 }
8419
8420                 torture_comment(tctx,
8421                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
8422                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8423
8424                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8425         }
8426
8427         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8428         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8429         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8430
8431         for (i=0; i < ARRAY_SIZE(levels); i++) {
8432
8433                 if (torture_setting_bool(tctx, "samba3", false)) {
8434                         switch (levels[i]) {
8435                         case 2:
8436                         case 4:
8437                         case 8:
8438                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8439                                 continue;
8440                         default:
8441                                 break;
8442                         }
8443                 }
8444
8445
8446                 torture_comment(tctx,
8447                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8448                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8449
8450                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8451         }
8452
8453         torture_assert(tctx,
8454                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8455                 "failed to remove printer driver");
8456
8457         torture_comment(tctx, "\n");
8458
8459         return ret;
8460 }
8461
8462 static bool test_add_driver_ex_64(struct torture_context *tctx,
8463                                   struct dcerpc_pipe *p,
8464                                   void *private_data)
8465 {
8466         struct torture_driver_context *d =
8467                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8468
8469         d->local.environment            = talloc_strdup(d, "Windows x64");
8470         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8471         d->info8.driver_name            = TORTURE_DRIVER_EX;
8472         d->ex                           = true;
8473
8474         return test_add_driver_arg(tctx, p, d);
8475 }
8476
8477 static bool test_add_driver_ex_32(struct torture_context *tctx,
8478                                   struct dcerpc_pipe *p,
8479                                   void *private_data)
8480 {
8481         struct torture_driver_context *d =
8482                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8483
8484         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8485         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8486         d->info8.driver_name            = TORTURE_DRIVER_EX;
8487         d->ex                           = true;
8488
8489         return test_add_driver_arg(tctx, p, d);
8490 }
8491
8492 static bool test_add_driver_64(struct torture_context *tctx,
8493                                struct dcerpc_pipe *p,
8494                                void *private_data)
8495 {
8496         struct torture_driver_context *d =
8497                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8498
8499         d->local.environment            = talloc_strdup(d, "Windows x64");
8500         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8501         d->info8.driver_name            = TORTURE_DRIVER;
8502         d->ex                           = false;
8503
8504         return test_add_driver_arg(tctx, p, d);
8505 }
8506
8507 static bool test_add_driver_32(struct torture_context *tctx,
8508                                struct dcerpc_pipe *p,
8509                                void *private_data)
8510 {
8511         struct torture_driver_context *d =
8512                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8513
8514         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8515         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8516         d->info8.driver_name            = TORTURE_DRIVER;
8517         d->ex                           = false;
8518
8519         return test_add_driver_arg(tctx, p, d);
8520 }
8521
8522 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8523 {
8524         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8525
8526         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8527                                                         "driver", &ndr_table_spoolss);
8528         struct torture_driver_context *t;
8529
8530         t = talloc_zero(mem_ctx, struct torture_driver_context);
8531
8532         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
8533         t->info8.driver_name    = NULL;
8534         t->info8.architecture   = NULL;
8535         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
8536         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
8537         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
8538
8539         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8540         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8541
8542         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8543         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8544
8545         return suite;
8546 }