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