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