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