s4-smbtorture: add tests for the size member of spoolss devicemodes.
[ddiss/samba.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2011
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_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) 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_EXP(SetPrinter, s, expected_result) \
2151                 if (W_ERROR_IS_OK(expected_result)) { \
2152                         TESTGETCALL(GetPrinter, q) \
2153                         INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2154                         q.in.level = lvl2; \
2155                         TESTGETCALL(GetPrinter, q) \
2156                         INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2157                 }\
2158         } while (0)
2159
2160 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2161         TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2162         } while (0)
2163
2164 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2165         TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2166         } while (0)
2167
2168         ZERO_STRUCT(devmode_ctr);
2169         ZERO_STRUCT(secdesc_ctr);
2170         ZERO_STRUCT(info8);
2171
2172         s.in.handle = handle;
2173         s.in.command = 0;
2174         s.in.info_ctr = &info_ctr;
2175         s.in.devmode_ctr = &devmode_ctr;
2176         s.in.secdesc_ctr = &secdesc_ctr;
2177
2178         q.in.handle = handle;
2179         q.out.info = &info;
2180         q0 = q;
2181
2182 #if 0
2183         const char *devicename;/* [charset(UTF16)] */
2184         enum spoolss_DeviceModeSpecVersion specversion;
2185         uint16_t driverversion;
2186         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2187         uint32_t fields;
2188 #endif
2189
2190         TEST_DEVMODE_INT_EXP(8, size,           8, size, __LINE__, WERR_INVALID_PARAM);
2191         TEST_DEVMODE_INT_EXP(8, size,           8, size, 0, WERR_INVALID_PARAM);
2192         TEST_DEVMODE_INT_EXP(8, size,           8, size, 0xffff, WERR_INVALID_PARAM);
2193         TEST_DEVMODE_INT_EXP(8, size,           8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), WERR_INVALID_PARAM);
2194         TEST_DEVMODE_INT(8, size,               8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2195         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
2196         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
2197         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
2198         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
2199         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
2200         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
2201         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
2202         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
2203         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
2204         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
2205         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
2206         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
2207         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
2208 #if 0
2209         const char *formname;/* [charset(UTF16)] */
2210 #endif
2211         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
2212         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
2213         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
2214         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
2215         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
2216         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
2217         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
2218         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
2219         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
2220         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
2221         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
2222         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
2223         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
2224         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
2225
2226         return ret;
2227 }
2228
2229 static bool call_OpenPrinterEx(struct torture_context *tctx,
2230                                struct dcerpc_pipe *p,
2231                                const char *name,
2232                                struct spoolss_DeviceMode *devmode,
2233                                struct policy_handle *handle);
2234
2235 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2236                                       struct dcerpc_pipe *p,
2237                                       struct policy_handle *handle,
2238                                       const char *name)
2239 {
2240         union spoolss_PrinterInfo info;
2241         struct spoolss_DeviceMode *devmode;
2242         struct spoolss_DeviceMode *devmode2;
2243         struct policy_handle handle_devmode;
2244         struct dcerpc_binding_handle *b = p->binding_handle;
2245
2246         /* simply compare level8 and level2 devmode */
2247
2248         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2249
2250         devmode = info.info8.devmode;
2251
2252         if (devmode && devmode->size == 0) {
2253                 torture_fail(tctx,
2254                         "devmode of zero size!");
2255         }
2256
2257         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2258
2259         devmode2 = info.info2.devmode;
2260
2261         if (devmode2 && devmode2->size == 0) {
2262                 torture_fail(tctx,
2263                         "devmode of zero size!");
2264         }
2265
2266         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2267                 "DM level 8 != DM level 2");
2268
2269
2270         /* set devicemode level 8 and see if it persists */
2271
2272         devmode->copies = 93;
2273         devmode->formname = talloc_strdup(tctx, "Legal");
2274
2275         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2276
2277         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2278
2279         devmode2 = info.info8.devmode;
2280
2281         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2282                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2283
2284         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2285
2286         devmode2 = info.info2.devmode;
2287
2288         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2289                 "modified DM level 8 != DM level 2");
2290
2291
2292         /* set devicemode level 2 and see if it persists */
2293
2294         devmode->copies = 39;
2295         devmode->formname = talloc_strdup(tctx, "Executive");
2296
2297         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2298
2299         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2300
2301         devmode2 = info.info8.devmode;
2302
2303         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2304                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2305
2306         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2307
2308         devmode2 = info.info2.devmode;
2309
2310         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2311                 "modified DM level 8 != DM level 2");
2312
2313
2314         /* check every single bit in public part of devicemode */
2315
2316         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2317                 "failed to set every single devicemode component");
2318
2319
2320         /* change formname upon open and see if it persists in getprinter calls */
2321
2322         devmode->formname = talloc_strdup(tctx, "A4");
2323         devmode->copies = 42;
2324
2325         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2326                 "failed to open printer handle");
2327
2328         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2329
2330         devmode2 = info.info8.devmode;
2331
2332         if (strequal(devmode->devicename, devmode2->devicename)) {
2333                 torture_warning(tctx, "devicenames are the same\n");
2334         } else {
2335                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2336                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2337         }
2338
2339         if (strequal(devmode->formname, devmode2->formname)) {
2340                 torture_warning(tctx, "formname are the same\n");
2341         } else {
2342                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2343                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2344         }
2345
2346         if (devmode->copies == devmode2->copies) {
2347                 torture_warning(tctx, "copies are the same\n");
2348         } else {
2349                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2350                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2351         }
2352
2353         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2354
2355         devmode2 = info.info2.devmode;
2356
2357         if (strequal(devmode->devicename, devmode2->devicename)) {
2358                 torture_warning(tctx, "devicenames are the same\n");
2359         } else {
2360                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2361                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2362         }
2363
2364         if (strequal(devmode->formname, devmode2->formname)) {
2365                 torture_warning(tctx, "formname is the same\n");
2366         } else {
2367                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2368                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2369         }
2370
2371         if (devmode->copies == devmode2->copies) {
2372                 torture_warning(tctx, "copies are the same\n");
2373         } else {
2374                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2375                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2376         }
2377
2378         test_ClosePrinter(tctx, b, &handle_devmode);
2379
2380         return true;
2381 }
2382
2383 /*
2384  * wrapper call that saves original devmode, runs tests, and restores devmode
2385  */
2386
2387 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2388                                      struct dcerpc_pipe *p,
2389                                      struct policy_handle *handle,
2390                                      const char *name,
2391                                      struct spoolss_DeviceMode *addprinter_devmode)
2392 {
2393         union spoolss_PrinterInfo info;
2394         struct spoolss_DeviceMode *devmode;
2395         bool ret = true;
2396         struct dcerpc_binding_handle *b = p->binding_handle;
2397
2398         torture_comment(tctx, "Testing Printer Devicemodes\n");
2399
2400         /* save original devmode */
2401
2402         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2403                 "failed to get initial global devicemode");
2404
2405         devmode = info.info8.devmode;
2406
2407         if (devmode && devmode->size == 0) {
2408                 torture_fail(tctx,
2409                         "devmode of zero size!");
2410         }
2411
2412         if (addprinter_devmode) {
2413                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2414                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
2415                 }
2416         }
2417
2418         /* run tests */
2419
2420         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2421
2422         /* restore original devmode */
2423
2424         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2425                 "failed to restore initial global device mode");
2426
2427         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2428                 ret ? "succeeded" : "failed");
2429
2430
2431         return ret;
2432 }
2433
2434 bool test_ClosePrinter(struct torture_context *tctx,
2435                        struct dcerpc_binding_handle *b,
2436                        struct policy_handle *handle)
2437 {
2438         NTSTATUS status;
2439         struct spoolss_ClosePrinter r;
2440
2441         r.in.handle = handle;
2442         r.out.handle = handle;
2443
2444         torture_comment(tctx, "Testing ClosePrinter\n");
2445
2446         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2447         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2448         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2449
2450         return true;
2451 }
2452
2453 static bool test_GetForm_args(struct torture_context *tctx,
2454                               struct dcerpc_binding_handle *b,
2455                               struct policy_handle *handle,
2456                               const char *form_name,
2457                               uint32_t level,
2458                               union spoolss_FormInfo *info_p)
2459 {
2460         NTSTATUS status;
2461         struct spoolss_GetForm r;
2462         uint32_t needed;
2463
2464         r.in.handle = handle;
2465         r.in.form_name = form_name;
2466         r.in.level = level;
2467         r.in.buffer = NULL;
2468         r.in.offered = 0;
2469         r.out.needed = &needed;
2470
2471         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2472
2473         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2474         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2475
2476         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2477                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2478                 r.in.buffer = &blob;
2479                 r.in.offered = needed;
2480                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2481                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2482
2483                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2484
2485                 torture_assert(tctx, r.out.info, "No form info returned");
2486         }
2487
2488         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2489
2490         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2491
2492         if (info_p) {
2493                 *info_p = *r.out.info;
2494         }
2495
2496         return true;
2497 }
2498
2499 static bool test_GetForm(struct torture_context *tctx,
2500                          struct dcerpc_binding_handle *b,
2501                          struct policy_handle *handle,
2502                          const char *form_name,
2503                          uint32_t level)
2504 {
2505         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2506 }
2507
2508 static bool test_EnumForms(struct torture_context *tctx,
2509                            struct dcerpc_binding_handle *b,
2510                            struct policy_handle *handle,
2511                            bool print_server,
2512                            uint32_t level,
2513                            uint32_t *count_p,
2514                            union spoolss_FormInfo **info_p)
2515 {
2516         struct spoolss_EnumForms r;
2517         uint32_t needed;
2518         uint32_t count;
2519         union spoolss_FormInfo *info;
2520
2521         r.in.handle = handle;
2522         r.in.level = level;
2523         r.in.buffer = NULL;
2524         r.in.offered = 0;
2525         r.out.needed = &needed;
2526         r.out.count = &count;
2527         r.out.info = &info;
2528
2529         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2530
2531         torture_assert_ntstatus_ok(tctx,
2532                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2533                 "EnumForms failed");
2534
2535         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2536                 torture_skip(tctx, "EnumForms level 2 not supported");
2537         }
2538
2539         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2540                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2541         }
2542
2543         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2544                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2545                 r.in.buffer = &blob;
2546                 r.in.offered = needed;
2547
2548                 torture_assert_ntstatus_ok(tctx,
2549                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2550                         "EnumForms failed");
2551
2552                 torture_assert(tctx, info, "No forms returned");
2553         }
2554
2555         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2556
2557         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2558
2559         if (info_p) {
2560                 *info_p = info;
2561         }
2562         if (count_p) {
2563                 *count_p = count;
2564         }
2565
2566         return true;
2567 }
2568
2569 static bool test_EnumForms_all(struct torture_context *tctx,
2570                                struct dcerpc_binding_handle *b,
2571                                struct policy_handle *handle,
2572                                bool print_server)
2573 {
2574         uint32_t levels[] = { 1, 2 };
2575         int i, j;
2576
2577         for (i=0; i<ARRAY_SIZE(levels); i++) {
2578
2579                 uint32_t count = 0;
2580                 union spoolss_FormInfo *info = NULL;
2581
2582                 torture_assert(tctx,
2583                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2584                         "failed to enum forms");
2585
2586                 for (j = 0; j < count; j++) {
2587                         if (!print_server) {
2588                                 torture_assert(tctx,
2589                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2590                                         "failed to get form");
2591                         }
2592                 }
2593         }
2594
2595         return true;
2596 }
2597
2598 static bool test_EnumForms_find_one(struct torture_context *tctx,
2599                                     struct dcerpc_binding_handle *b,
2600                                     struct policy_handle *handle,
2601                                     bool print_server,
2602                                     const char *form_name)
2603 {
2604         union spoolss_FormInfo *info;
2605         uint32_t count;
2606         bool found = false;
2607         int i;
2608
2609         torture_assert(tctx,
2610                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2611                 "failed to enumerate forms");
2612
2613         for (i=0; i<count; i++) {
2614                 if (strequal(form_name, info[i].info1.form_name)) {
2615                         found = true;
2616                         break;
2617                 }
2618         }
2619
2620         return found;
2621 }
2622
2623 static bool test_DeleteForm(struct torture_context *tctx,
2624                             struct dcerpc_binding_handle *b,
2625                             struct policy_handle *handle,
2626                             const char *form_name,
2627                             WERROR expected_result)
2628 {
2629         struct spoolss_DeleteForm r;
2630
2631         r.in.handle = handle;
2632         r.in.form_name = form_name;
2633
2634         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2635
2636         torture_assert_ntstatus_ok(tctx,
2637                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2638                 "DeleteForm failed");
2639         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2640                 "DeleteForm gave unexpected result");
2641         if (W_ERROR_IS_OK(r.out.result)) {
2642                 torture_assert_ntstatus_ok(tctx,
2643                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2644                         "2nd DeleteForm failed");
2645                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2646                         "2nd DeleteForm failed");
2647         }
2648
2649         return true;
2650 }
2651
2652 static bool test_AddForm(struct torture_context *tctx,
2653                          struct dcerpc_binding_handle *b,
2654                          struct policy_handle *handle,
2655                          uint32_t level,
2656                          union spoolss_AddFormInfo *info,
2657                          WERROR expected_result)
2658 {
2659         struct spoolss_AddForm r;
2660
2661         if (level != 1) {
2662                 torture_skip(tctx, "only level 1 supported");
2663         }
2664
2665         r.in.handle     = handle;
2666         r.in.level      = level;
2667         r.in.info       = *info;
2668
2669         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2670                 r.in.info.info1->form_name, r.in.level,
2671                 r.in.info.info1->flags);
2672
2673         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2674                 "AddForm failed");
2675         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2676                 "AddForm gave unexpected result");
2677
2678         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2679                 "2nd AddForm failed");
2680         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2681                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2682                         "2nd AddForm gave unexpected result");
2683         } else {
2684                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2685                         "2nd AddForm gave unexpected result");
2686         }
2687
2688         return true;
2689 }
2690
2691 static bool test_SetForm(struct torture_context *tctx,
2692                          struct dcerpc_binding_handle *b,
2693                          struct policy_handle *handle,
2694                          const char *form_name,
2695                          uint32_t level,
2696                          union spoolss_AddFormInfo *info)
2697 {
2698         struct spoolss_SetForm r;
2699
2700         r.in.handle     = handle;
2701         r.in.form_name  = form_name;
2702         r.in.level      = level;
2703         r.in.info       = *info;
2704
2705         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2706                 form_name, r.in.level);
2707
2708         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2709                 "SetForm failed");
2710
2711         torture_assert_werr_ok(tctx, r.out.result,
2712                 "SetForm failed");
2713
2714         return true;
2715 }
2716
2717 static bool test_GetForm_winreg(struct torture_context *tctx,
2718                                 struct dcerpc_binding_handle *b,
2719                                 struct policy_handle *handle,
2720                                 const char *key_name,
2721                                 const char *form_name,
2722                                 enum winreg_Type *w_type,
2723                                 uint32_t *w_size,
2724                                 uint32_t *w_length,
2725                                 uint8_t **w_data);
2726
2727 static bool test_Forms_args(struct torture_context *tctx,
2728                             struct dcerpc_binding_handle *b,
2729                             struct policy_handle *handle,
2730                             bool print_server,
2731                             const char *printer_name,
2732                             struct dcerpc_binding_handle *winreg_handle,
2733                             struct policy_handle *hive_handle,
2734                             const char *form_name,
2735                             struct spoolss_AddFormInfo1 *info1,
2736                             WERROR expected_add_result,
2737                             WERROR expected_delete_result)
2738 {
2739         union spoolss_FormInfo info;
2740         union spoolss_AddFormInfo add_info;
2741
2742         enum winreg_Type w_type;
2743         uint32_t w_size;
2744         uint32_t w_length;
2745         uint8_t *w_data;
2746
2747         add_info.info1 = info1;
2748
2749         torture_assert(tctx,
2750                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2751                 "failed to add form");
2752
2753         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2754
2755                 struct spoolss_FormInfo1 i1;
2756
2757                 torture_assert(tctx,
2758                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2759                         "failed to get form via winreg");
2760
2761                 i1.size.width   = IVAL(w_data, 0);
2762                 i1.size.height  = IVAL(w_data, 4);
2763                 i1.area.left    = IVAL(w_data, 8);
2764                 i1.area.top     = IVAL(w_data, 12);
2765                 i1.area.right   = IVAL(w_data, 16);
2766                 i1.area.bottom  = IVAL(w_data, 20);
2767                 /* skip index here */
2768                 i1.flags        = IVAL(w_data, 28);
2769
2770                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2771                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2772                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2773                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2774                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2775                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2776                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2777                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2778                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2779                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2780         }
2781
2782         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2783                 torture_assert(tctx,
2784                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2785                         "failed to get added form");
2786
2787                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2788                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2789                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2790                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2791                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2792                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2793                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2794
2795                 if (winreg_handle && hive_handle) {
2796
2797                         struct spoolss_FormInfo1 i1;
2798
2799                         i1.size.width   = IVAL(w_data, 0);
2800                         i1.size.height  = IVAL(w_data, 4);
2801                         i1.area.left    = IVAL(w_data, 8);
2802                         i1.area.top     = IVAL(w_data, 12);
2803                         i1.area.right   = IVAL(w_data, 16);
2804                         i1.area.bottom  = IVAL(w_data, 20);
2805                         /* skip index here */
2806                         i1.flags        = IVAL(w_data, 28);
2807
2808                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2809                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2810                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2811                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2812                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2813                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2814                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2815                 }
2816
2817                 add_info.info1->size.width = 1234;
2818
2819                 torture_assert(tctx,
2820                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2821                         "failed to set form");
2822                 torture_assert(tctx,
2823                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2824                         "failed to get setted form");
2825
2826                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2827         }
2828
2829         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2830                 torture_assert(tctx,
2831                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2832                         "Newly added form not found in enum call");
2833         }
2834
2835         torture_assert(tctx,
2836                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2837                 "failed to delete form");
2838
2839         return true;
2840 }
2841
2842 static bool test_Forms(struct torture_context *tctx,
2843                        struct dcerpc_binding_handle *b,
2844                        struct policy_handle *handle,
2845                        bool print_server,
2846                        const char *printer_name,
2847                        struct dcerpc_binding_handle *winreg_handle,
2848                        struct policy_handle *hive_handle)
2849 {
2850         const struct spoolss_FormSize size = {
2851                 .width  = 50,
2852                 .height = 25
2853         };
2854         const struct spoolss_FormArea area = {
2855                 .left   = 5,
2856                 .top    = 10,
2857                 .right  = 45,
2858                 .bottom = 15
2859         };
2860         int i;
2861
2862         struct {
2863                 struct spoolss_AddFormInfo1 info1;
2864                 WERROR expected_add_result;
2865                 WERROR expected_delete_result;
2866         } forms[] = {
2867                 {
2868                         .info1 = {
2869                                 .flags          = SPOOLSS_FORM_USER,
2870                                 .form_name      = "testform_user",
2871                                 .size           = size,
2872                                 .area           = area,
2873                         },
2874                         .expected_add_result    = WERR_OK,
2875                         .expected_delete_result = WERR_OK
2876                 },
2877 /*
2878                 weird, we can add a builtin form but we can never remove it
2879                 again - gd
2880
2881                 {
2882                         .info1 = {
2883                                 .flags          = SPOOLSS_FORM_BUILTIN,
2884                                 .form_name      = "testform_builtin",
2885                                 .size           = size,
2886                                 .area           = area,
2887                         },
2888                         .expected_add_result    = WERR_OK,
2889                         .expected_delete_result = WERR_INVALID_PARAM,
2890                 },
2891 */
2892                 {
2893                         .info1 = {
2894                                 .flags          = SPOOLSS_FORM_PRINTER,
2895                                 .form_name      = "testform_printer",
2896                                 .size           = size,
2897                                 .area           = area,
2898                         },
2899                         .expected_add_result    = WERR_OK,
2900                         .expected_delete_result = WERR_OK
2901                 },
2902                 {
2903                         .info1 = {
2904                                 .flags          = SPOOLSS_FORM_USER,
2905                                 .form_name      = "Letter",
2906                                 .size           = size,
2907                                 .area           = area,
2908                         },
2909                         .expected_add_result    = WERR_FILE_EXISTS,
2910                         .expected_delete_result = WERR_INVALID_PARAM
2911                 },
2912                 {
2913                         .info1 = {
2914                                 .flags          = SPOOLSS_FORM_BUILTIN,
2915                                 .form_name      = "Letter",
2916                                 .size           = size,
2917                                 .area           = area,
2918                         },
2919                         .expected_add_result    = WERR_FILE_EXISTS,
2920                         .expected_delete_result = WERR_INVALID_PARAM
2921                 },
2922                 {
2923                         .info1 = {
2924                                 .flags          = SPOOLSS_FORM_PRINTER,
2925                                 .form_name      = "Letter",
2926                                 .size           = size,
2927                                 .area           = area,
2928                         },
2929                         .expected_add_result    = WERR_FILE_EXISTS,
2930                         .expected_delete_result = WERR_INVALID_PARAM
2931                 },
2932                 {
2933                         .info1 = {
2934                                 .flags          = 12345,
2935                                 .form_name      = "invalid_flags",
2936                                 .size           = size,
2937                                 .area           = area,
2938                         },
2939                         .expected_add_result    = WERR_INVALID_PARAM,
2940                         .expected_delete_result = WERR_INVALID_FORM_NAME
2941                 }
2942
2943         };
2944
2945         for (i=0; i < ARRAY_SIZE(forms); i++) {
2946                 torture_assert(tctx,
2947                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2948                                         winreg_handle, hive_handle,
2949                                         forms[i].info1.form_name,
2950                                         &forms[i].info1,
2951                                         forms[i].expected_add_result,
2952                                         forms[i].expected_delete_result),
2953                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2954         }
2955
2956         return true;
2957 }
2958
2959 static bool test_EnumPorts_old(struct torture_context *tctx,
2960                                void *private_data)
2961 {
2962         struct test_spoolss_context *ctx =
2963                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2964
2965         NTSTATUS status;
2966         struct spoolss_EnumPorts r;
2967         uint32_t needed;
2968         uint32_t count;
2969         union spoolss_PortInfo *info;
2970         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2971         struct dcerpc_binding_handle *b = p->binding_handle;
2972
2973         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2974                                           dcerpc_server_name(p));
2975         r.in.level = 2;
2976         r.in.buffer = NULL;
2977         r.in.offered = 0;
2978         r.out.needed = &needed;
2979         r.out.count = &count;
2980         r.out.info = &info;
2981
2982         torture_comment(tctx, "Testing EnumPorts\n");
2983
2984         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2985
2986         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2987
2988         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2989                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2990                 r.in.buffer = &blob;
2991                 r.in.offered = needed;
2992
2993                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2994                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2995                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2996
2997                 torture_assert(tctx, info, "No ports returned");
2998         }
2999
3000         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3001
3002         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3003
3004         return true;
3005 }
3006
3007 static bool test_AddPort(struct torture_context *tctx,
3008                          void *private_data)
3009 {
3010         struct test_spoolss_context *ctx =
3011                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3012
3013         NTSTATUS status;
3014         struct spoolss_AddPort r;
3015         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3016         struct dcerpc_binding_handle *b = p->binding_handle;
3017
3018         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3019                                            dcerpc_server_name(p));
3020         r.in.unknown = 0;
3021         r.in.monitor_name = "foo";
3022
3023         torture_comment(tctx, "Testing AddPort\n");
3024
3025         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3026
3027         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3028
3029         /* win2k3 returns WERR_NOT_SUPPORTED */
3030
3031 #if 0
3032
3033         if (!W_ERROR_IS_OK(r.out.result)) {
3034                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3035                 return false;
3036         }
3037
3038 #endif
3039
3040         return true;
3041 }
3042
3043 static bool test_GetJob_args(struct torture_context *tctx,
3044                              struct dcerpc_binding_handle *b,
3045                              struct policy_handle *handle,
3046                              uint32_t job_id,
3047                              uint32_t level,
3048                              union spoolss_JobInfo *info_p)
3049 {
3050         NTSTATUS status;
3051         struct spoolss_GetJob r;
3052         union spoolss_JobInfo info;
3053         uint32_t needed;
3054
3055         r.in.handle = handle;
3056         r.in.job_id = job_id;
3057         r.in.level = level;
3058         r.in.buffer = NULL;
3059         r.in.offered = 0;
3060         r.out.needed = &needed;
3061         r.out.info = &info;
3062
3063         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3064
3065         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3066         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3067         if (level == 0) {
3068                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3069         }
3070
3071         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3072                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3073                 r.in.buffer = &blob;
3074                 r.in.offered = needed;
3075
3076                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3077                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3078         }
3079
3080         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3081         torture_assert(tctx, r.out.info, "No job info returned");
3082
3083         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3084
3085         if (info_p) {
3086                 *info_p = *r.out.info;
3087         }
3088
3089         return true;
3090 }
3091
3092 static bool test_GetJob(struct torture_context *tctx,
3093                         struct dcerpc_binding_handle *b,
3094                         struct policy_handle *handle,
3095                         uint32_t job_id)
3096 {
3097         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3098         uint32_t i;
3099
3100         for (i=0; i < ARRAY_SIZE(levels); i++) {
3101                 torture_assert(tctx,
3102                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3103                         "GetJob failed");
3104         }
3105
3106         return true;
3107 }
3108
3109 static bool test_SetJob(struct torture_context *tctx,
3110                         struct dcerpc_binding_handle *b,
3111                         struct policy_handle *handle,
3112                         uint32_t job_id,
3113                         struct spoolss_JobInfoContainer *ctr,
3114                         enum spoolss_JobControl command)
3115 {
3116         NTSTATUS status;
3117         struct spoolss_SetJob r;
3118
3119         r.in.handle     = handle;
3120         r.in.job_id     = job_id;
3121         r.in.ctr        = ctr;
3122         r.in.command    = command;
3123
3124         switch (command) {
3125         case SPOOLSS_JOB_CONTROL_PAUSE:
3126                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3127                 break;
3128         case SPOOLSS_JOB_CONTROL_RESUME:
3129                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3130                 break;
3131         case SPOOLSS_JOB_CONTROL_CANCEL:
3132                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3133                 break;
3134         case SPOOLSS_JOB_CONTROL_RESTART:
3135                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3136                 break;
3137         case SPOOLSS_JOB_CONTROL_DELETE:
3138                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3139                 break;
3140         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3141                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3142                 break;
3143         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3144                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3145                 break;
3146         case SPOOLSS_JOB_CONTROL_RETAIN:
3147                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3148                 break;
3149         case SPOOLSS_JOB_CONTROL_RELEASE:
3150                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3151                 break;
3152         default:
3153                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3154                 break;
3155         }
3156
3157         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3158         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3159         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3160
3161         return true;
3162 }
3163
3164 static bool test_AddJob(struct torture_context *tctx,
3165                         struct dcerpc_binding_handle *b,
3166                         struct policy_handle *handle)
3167 {
3168         NTSTATUS status;
3169         struct spoolss_AddJob r;
3170         uint32_t needed;
3171
3172         r.in.level = 0;
3173         r.in.handle = handle;
3174         r.in.offered = 0;
3175         r.out.needed = &needed;
3176         r.in.buffer = r.out.buffer = NULL;
3177
3178         torture_comment(tctx, "Testing AddJob\n");
3179
3180         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3181         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3182
3183         r.in.level = 1;
3184
3185         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3186         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3187
3188         return true;
3189 }
3190
3191
3192 static bool test_EnumJobs_args(struct torture_context *tctx,
3193                                struct dcerpc_binding_handle *b,
3194                                struct policy_handle *handle,
3195                                uint32_t level,
3196                                uint32_t *count_p,
3197                                union spoolss_JobInfo **info_p)
3198 {
3199         NTSTATUS status;
3200         struct spoolss_EnumJobs r;
3201         uint32_t needed;
3202         uint32_t count;
3203         union spoolss_JobInfo *info;
3204
3205         r.in.handle = handle;
3206         r.in.firstjob = 0;
3207         r.in.numjobs = 0xffffffff;
3208         r.in.level = level;
3209         r.in.buffer = NULL;
3210         r.in.offered = 0;
3211         r.out.needed = &needed;
3212         r.out.count = &count;
3213         r.out.info = &info;
3214
3215         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3216
3217         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3218
3219         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3220
3221         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3222                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3223                 r.in.buffer = &blob;
3224                 r.in.offered = needed;
3225
3226                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3227
3228                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3229                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3230                 torture_assert(tctx, info, "No jobs returned");
3231
3232                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3233
3234         } else {
3235                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3236         }
3237
3238         if (count_p) {
3239                 *count_p = count;
3240         }
3241         if (info_p) {
3242                 *info_p = info;
3243         }
3244
3245         return true;
3246 }
3247
3248 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3249                                          struct dcerpc_binding_handle *b,
3250                                          struct policy_handle *handle,
3251                                          uint32_t *job_id)
3252 {
3253         NTSTATUS status;
3254         struct spoolss_StartDocPrinter s;
3255         struct spoolss_DocumentInfo1 info1;
3256         struct spoolss_StartPagePrinter sp;
3257         struct spoolss_WritePrinter w;
3258         struct spoolss_EndPagePrinter ep;
3259         struct spoolss_EndDocPrinter e;
3260         int i;
3261         uint32_t num_written;
3262
3263         torture_comment(tctx, "Testing StartDocPrinter\n");
3264
3265         s.in.handle             = handle;
3266         s.in.level              = 1;
3267         s.in.info.info1         = &info1;
3268         s.out.job_id            = job_id;
3269         info1.document_name     = "TorturePrintJob";
3270         info1.output_file       = NULL;
3271         info1.datatype          = "RAW";
3272
3273         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3274         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3275         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3276
3277         for (i=1; i < 4; i++) {
3278                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3279
3280                 sp.in.handle            = handle;
3281
3282                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3283                 torture_assert_ntstatus_ok(tctx, status,
3284                                            "dcerpc_spoolss_StartPagePrinter failed");
3285                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3286
3287                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3288
3289                 w.in.handle             = handle;
3290                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3291                 w.out.num_written       = &num_written;
3292
3293                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3294                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3295                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3296
3297                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3298
3299                 ep.in.handle            = handle;
3300
3301                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3302                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3303                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3304         }
3305
3306         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3307
3308         e.in.handle = handle;
3309
3310         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3311         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3312         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3313
3314         return true;
3315 }
3316
3317 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3318                                         struct dcerpc_binding_handle *b,
3319                                         struct policy_handle *handle,
3320                                         uint32_t num_jobs,
3321                                         uint32_t *job_ids)
3322 {
3323         uint32_t count;
3324         union spoolss_JobInfo *info = NULL;
3325         int i;
3326
3327         torture_assert(tctx,
3328                 test_AddJob(tctx, b, handle),
3329                 "AddJob failed");
3330
3331         torture_assert(tctx,
3332                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3333                 "EnumJobs level 1 failed");
3334
3335         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3336
3337         for (i=0; i < num_jobs; i++) {
3338                 union spoolss_JobInfo ginfo;
3339                 const char *document_name;
3340                 const char *new_document_name = "any_other_docname";
3341                 struct spoolss_JobInfoContainer ctr;
3342                 struct spoolss_SetJobInfo1 info1;
3343
3344                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3345
3346                 torture_assert(tctx,
3347                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3348                         "failed to call test_GetJob");
3349
3350                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3351
3352                 document_name = ginfo.info1.document_name;
3353
3354                 info1.job_id            = ginfo.info1.job_id;
3355                 info1.printer_name      = ginfo.info1.printer_name;
3356                 info1.server_name       = ginfo.info1.server_name;
3357                 info1.user_name         = ginfo.info1.user_name;
3358                 info1.document_name     = new_document_name;
3359                 info1.data_type         = ginfo.info1.data_type;
3360                 info1.text_status       = ginfo.info1.text_status;
3361                 info1.status            = ginfo.info1.status;
3362                 info1.priority          = ginfo.info1.priority;
3363                 info1.position          = ginfo.info1.position;
3364                 info1.total_pages       = ginfo.info1.total_pages;
3365                 info1.pages_printed     = ginfo.info1.pages_printed;
3366                 info1.submitted         = ginfo.info1.submitted;
3367
3368                 ctr.level = 1;
3369                 ctr.info.info1 = &info1;
3370
3371                 torture_assert(tctx,
3372                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3373                         "failed to call test_SetJob level 1");
3374
3375                 torture_assert(tctx,
3376                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3377                         "failed to call test_GetJob");
3378
3379                 if (strequal(ginfo.info1.document_name, document_name)) {
3380                         torture_warning(tctx,
3381                                         "document_name did *NOT* change from '%s' to '%s'\n",
3382                                         document_name, new_document_name);
3383                 }
3384         }
3385
3386         for (i=0; i < num_jobs; i++) {
3387                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3388                         torture_warning(tctx, "failed to pause printjob\n");
3389                 }
3390                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3391                         torture_warning(tctx, "failed to resume printjob\n");
3392                 }
3393         }
3394
3395         return true;
3396 }
3397
3398 static bool test_DoPrintTest(struct torture_context *tctx,
3399                              struct dcerpc_binding_handle *b,
3400                              struct policy_handle *handle)
3401 {
3402         bool ret = true;
3403         uint32_t num_jobs = 8;
3404         uint32_t *job_ids;
3405         int i;
3406
3407         torture_comment(tctx, "Testing real print operations\n");
3408
3409         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3410
3411         for (i=0; i < num_jobs; i++) {
3412                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3413         }
3414
3415         for (i=0; i < num_jobs; i++) {
3416                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3417         }
3418
3419         if (ret == true) {
3420                 torture_comment(tctx, "real print operations test succeeded\n\n");
3421         }
3422
3423         return ret;
3424 }
3425
3426 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3427                                       struct dcerpc_binding_handle *b,
3428                                       struct policy_handle *handle)
3429 {
3430         bool ret = true;
3431         uint32_t num_jobs = 8;
3432         uint32_t *job_ids;
3433         int i;
3434         torture_comment(tctx, "Testing real print operations (extended)\n");
3435
3436         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3437
3438         for (i=0; i < num_jobs; i++) {
3439                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3440         }
3441
3442         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3443
3444         for (i=0; i < num_jobs; i++) {
3445                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3446         }
3447
3448         if (ret == true) {
3449                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3450         }
3451
3452         return ret;
3453 }
3454
3455 static bool test_PausePrinter(struct torture_context *tctx,
3456                               struct dcerpc_binding_handle *b,
3457                               struct policy_handle *handle)
3458 {
3459         NTSTATUS status;
3460         struct spoolss_SetPrinter r;
3461         struct spoolss_SetPrinterInfoCtr info_ctr;
3462         struct spoolss_DevmodeContainer devmode_ctr;
3463         struct sec_desc_buf secdesc_ctr;
3464
3465         info_ctr.level = 0;
3466         info_ctr.info.info0 = NULL;
3467
3468         ZERO_STRUCT(devmode_ctr);
3469         ZERO_STRUCT(secdesc_ctr);
3470
3471         r.in.handle             = handle;
3472         r.in.info_ctr           = &info_ctr;
3473         r.in.devmode_ctr        = &devmode_ctr;
3474         r.in.secdesc_ctr        = &secdesc_ctr;
3475         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3476
3477         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3478
3479         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3480
3481         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3482
3483         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3484
3485         return true;
3486 }
3487
3488 static bool test_ResumePrinter(struct torture_context *tctx,
3489                                struct dcerpc_binding_handle *b,
3490                                struct policy_handle *handle)
3491 {
3492         NTSTATUS status;
3493         struct spoolss_SetPrinter r;
3494         struct spoolss_SetPrinterInfoCtr info_ctr;
3495         struct spoolss_DevmodeContainer devmode_ctr;
3496         struct sec_desc_buf secdesc_ctr;
3497
3498         info_ctr.level = 0;
3499         info_ctr.info.info0 = NULL;
3500
3501         ZERO_STRUCT(devmode_ctr);
3502         ZERO_STRUCT(secdesc_ctr);
3503
3504         r.in.handle             = handle;
3505         r.in.info_ctr           = &info_ctr;
3506         r.in.devmode_ctr        = &devmode_ctr;
3507         r.in.secdesc_ctr        = &secdesc_ctr;
3508         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3509
3510         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3511
3512         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3513
3514         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3515
3516         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3517
3518         return true;
3519 }
3520
3521 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3522                                           struct dcerpc_binding_handle *b,
3523                                           struct policy_handle *handle,
3524                                           const char *value_name,
3525                                           enum winreg_Type *expected_type,
3526                                           enum winreg_Type *type_p,
3527                                           uint8_t **data_p,
3528                                           uint32_t *needed_p)
3529 {
3530         NTSTATUS status;
3531         struct spoolss_GetPrinterData r;
3532         uint32_t needed;
3533         enum winreg_Type type;
3534         union spoolss_PrinterData data;
3535
3536         r.in.handle = handle;
3537         r.in.value_name = value_name;
3538         r.in.offered = 0;
3539         r.out.needed = &needed;
3540         r.out.type = &type;
3541         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3542
3543         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3544
3545         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3546         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3547
3548         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3549                 if (expected_type) {
3550                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3551                 }
3552                 r.in.offered = needed;
3553                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3554                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3555                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3556         }
3557
3558         torture_assert_werr_ok(tctx, r.out.result,
3559                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3560
3561         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3562
3563         if (type_p) {
3564                 *type_p = type;
3565         }
3566
3567         if (data_p) {
3568                 *data_p = r.out.data;
3569         }
3570
3571         if (needed_p) {
3572                 *needed_p = needed;
3573         }
3574
3575         return true;
3576 }
3577
3578 static bool test_GetPrinterData(struct torture_context *tctx,
3579                                 struct dcerpc_binding_handle *b,
3580                                 struct policy_handle *handle,
3581                                 const char *value_name,
3582                                 enum winreg_Type *type_p,
3583                                 uint8_t **data_p,
3584                                 uint32_t *needed_p)
3585 {
3586         return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3587                                              NULL, type_p, data_p, needed_p);
3588 }
3589
3590 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3591                                             struct dcerpc_pipe *p,
3592                                             struct policy_handle *handle,
3593                                             const char *key_name,
3594                                             const char *value_name,
3595                                             enum winreg_Type *expected_type,
3596                                             enum winreg_Type *type_p,
3597                                             uint8_t **data_p,
3598                                             uint32_t *needed_p)
3599 {
3600         NTSTATUS status;
3601         struct spoolss_GetPrinterDataEx r;
3602         enum winreg_Type type;
3603         uint32_t needed;
3604         union spoolss_PrinterData data;
3605         struct dcerpc_binding_handle *b = p->binding_handle;
3606
3607         r.in.handle = handle;
3608         r.in.key_name = key_name;
3609         r.in.value_name = value_name;
3610         r.in.offered = 0;
3611         r.out.type = &type;
3612         r.out.needed = &needed;
3613         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3614
3615         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3616                 r.in.key_name, r.in.value_name);
3617
3618         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3619         if (!NT_STATUS_IS_OK(status)) {
3620                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3621                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3622                 }
3623                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3624         }
3625
3626         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3627                 if (expected_type) {
3628                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3629                 }
3630                 r.in.offered = needed;
3631                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3632                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3633                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3634         }
3635
3636         torture_assert_werr_ok(tctx, r.out.result,
3637                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3638
3639         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3640
3641         if (type_p) {
3642                 *type_p = type;
3643         }
3644
3645         if (data_p) {
3646                 *data_p = r.out.data;
3647         }
3648
3649         if (needed_p) {
3650                 *needed_p = needed;
3651         }
3652
3653         return true;
3654 }
3655
3656 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3657                                   struct dcerpc_pipe *p,
3658                                   struct policy_handle *handle,
3659                                   const char *key_name,
3660                                   const char *value_name,
3661                                   enum winreg_Type *type_p,
3662                                   uint8_t **data_p,
3663                                   uint32_t *needed_p)
3664 {
3665         return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3666                                                NULL, type_p, data_p, needed_p);
3667 }
3668
3669 static bool test_get_environment(struct torture_context *tctx,
3670                                  struct dcerpc_binding_handle *b,
3671                                  struct policy_handle *handle,
3672                                  const char **architecture)
3673 {
3674         DATA_BLOB blob;
3675         enum winreg_Type type;
3676         uint8_t *data;
3677         uint32_t needed;
3678
3679         torture_assert(tctx,
3680                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3681                 "failed to get Architecture");
3682
3683         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3684
3685         blob = data_blob_const(data, needed);
3686         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3687
3688         return true;
3689 }
3690
3691 static bool test_GetPrinterData_list(struct torture_context *tctx,
3692                                      void *private_data)
3693 {
3694         struct test_spoolss_context *ctx =
3695                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3696         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3697         struct dcerpc_binding_handle *b = p->binding_handle;
3698         const char *list[] = {
3699                 "W3SvcInstalled",
3700                 "BeepEnabled",
3701                 "EventLog",
3702                 /* "NetPopup", not on w2k8 */
3703                 /* "NetPopupToComputer", not on w2k8 */
3704                 "MajorVersion",
3705                 "MinorVersion",
3706                 "DefaultSpoolDirectory",
3707                 "Architecture",
3708                 "DsPresent",
3709                 "OSVersion",
3710                 /* "OSVersionEx", not on s3 */
3711                 "DNSMachineName"
3712         };
3713         int i;
3714
3715         for (i=0; i < ARRAY_SIZE(list); i++) {
3716                 enum winreg_Type type, type_ex;
3717                 uint8_t *data, *data_ex;
3718                 uint32_t needed, needed_ex;
3719
3720                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3721                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3722                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3723                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3724                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3725                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3726                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3727         }
3728
3729         return true;
3730 }
3731
3732 static bool test_EnumPrinterData(struct torture_context *tctx,
3733                                  struct dcerpc_pipe *p,
3734                                  struct policy_handle *handle,
3735                                  uint32_t enum_index,
3736                                  uint32_t value_offered,
3737                                  uint32_t data_offered,
3738                                  enum winreg_Type *type_p,
3739                                  uint32_t *value_needed_p,
3740                                  uint32_t *data_needed_p,
3741                                  const char **value_name_p,
3742                                  uint8_t **data_p,
3743                                  WERROR *result_p)
3744 {
3745         struct spoolss_EnumPrinterData r;
3746         uint32_t data_needed;
3747         uint32_t value_needed;
3748         enum winreg_Type type;
3749         struct dcerpc_binding_handle *b = p->binding_handle;
3750
3751         r.in.handle = handle;
3752         r.in.enum_index = enum_index;
3753         r.in.value_offered = value_offered;
3754         r.in.data_offered = data_offered;
3755         r.out.data_needed = &data_needed;
3756         r.out.value_needed = &value_needed;
3757         r.out.type = &type;
3758         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3759         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3760
3761         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3762
3763         torture_assert_ntstatus_ok(tctx,
3764                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3765                 "EnumPrinterData failed");
3766
3767         if (type_p) {
3768                 *type_p = type;
3769         }
3770         if (value_needed_p) {
3771                 *value_needed_p = value_needed;
3772         }
3773         if (data_needed_p) {
3774                 *data_needed_p = data_needed;
3775         }
3776         if (value_name_p) {
3777                 *value_name_p = r.out.value_name;
3778         }
3779         if (data_p) {
3780                 *data_p = r.out.data;
3781         }
3782         if (result_p) {
3783                 *result_p = r.out.result;
3784         }
3785
3786         return true;
3787 }
3788
3789
3790 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3791                                      struct dcerpc_pipe *p,
3792                                      struct policy_handle *handle)
3793 {
3794         uint32_t enum_index = 0;
3795         enum winreg_Type type;
3796         uint32_t value_needed;
3797         uint32_t data_needed;
3798         uint8_t *data;
3799         const char *value_name;
3800         WERROR result;
3801
3802         torture_comment(tctx, "Testing EnumPrinterData\n");
3803
3804         do {
3805                 torture_assert(tctx,
3806                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3807                                              &type, &value_needed, &data_needed,
3808                                              &value_name, &data, &result),
3809                         "EnumPrinterData failed");
3810
3811                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3812                         break;
3813                 }
3814
3815                 torture_assert(tctx,
3816                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3817                                              &type, &value_needed, &data_needed,
3818                                              &value_name, &data, &result),
3819                         "EnumPrinterData failed");
3820
3821                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3822                         break;
3823                 }
3824
3825                 enum_index++;
3826
3827         } while (W_ERROR_IS_OK(result));
3828
3829         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3830
3831         return true;
3832 }
3833
3834 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3835                                    struct dcerpc_binding_handle *b,
3836                                    struct policy_handle *handle,
3837                                    const char *key_name,
3838                                    uint32_t *count_p,
3839                                    struct spoolss_PrinterEnumValues **info_p)
3840 {
3841         struct spoolss_EnumPrinterDataEx r;
3842         struct spoolss_PrinterEnumValues *info;
3843         uint32_t needed;
3844         uint32_t count;
3845
3846         r.in.handle = handle;
3847         r.in.key_name = key_name;
3848         r.in.offered = 0;
3849         r.out.needed = &needed;
3850         r.out.count = &count;
3851         r.out.info = &info;
3852
3853         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3854
3855         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3856                 "EnumPrinterDataEx failed");
3857         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3858                 r.in.offered = needed;
3859                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3860                         "EnumPrinterDataEx failed");
3861         }
3862
3863         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3864
3865         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3866
3867         if (count_p) {
3868                 *count_p = count;
3869         }
3870         if (info_p) {
3871                 *info_p = info;
3872         }
3873
3874         return true;
3875 }
3876
3877 static bool test_SetPrinterData(struct torture_context *tctx,
3878                                 struct dcerpc_binding_handle *b,
3879                                 struct policy_handle *handle,
3880                                 const char *value_name,
3881                                 enum winreg_Type type,
3882                                 uint8_t *data,
3883                                 uint32_t offered);
3884 static bool test_DeletePrinterData(struct torture_context *tctx,
3885                                    struct dcerpc_binding_handle *b,
3886                                    struct policy_handle *handle,
3887                                    const char *value_name);
3888
3889 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3890                                              struct dcerpc_pipe *p,
3891                                              struct policy_handle *handle)
3892 {
3893         uint32_t count;
3894         struct spoolss_PrinterEnumValues *info;
3895         int i;
3896         uint32_t value_needed, data_needed;
3897         uint32_t value_offered, data_offered;
3898         WERROR result;
3899         struct dcerpc_binding_handle *b = p->binding_handle;
3900
3901         enum winreg_Type type;
3902         DATA_BLOB blob;
3903
3904         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3905
3906         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3907         type = REG_SZ;
3908
3909         torture_assert(tctx,
3910                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3911                 "SetPrinterData failed");
3912
3913         blob = data_blob_string_const("torture_data2");
3914
3915         torture_assert(tctx,
3916                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3917                 "SetPrinterData failed");
3918
3919         blob = data_blob_talloc(tctx, NULL, 4);
3920         SIVAL(blob.data, 0, 0x11223344);
3921
3922         torture_assert(tctx,
3923                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3924                 "SetPrinterData failed");
3925
3926         torture_assert(tctx,
3927                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3928                 "failed to call EnumPrinterDataEx");
3929
3930         /* get the max sizes for value and data */
3931
3932         torture_assert(tctx,
3933                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3934                                      NULL, &value_needed, &data_needed,
3935                                      NULL, NULL, &result),
3936                 "EnumPrinterData failed");
3937         torture_assert_werr_ok(tctx, result, "unexpected result");
3938
3939         /* check if the reply from the EnumPrinterData really matches max values */
3940
3941         for (i=0; i < count; i++) {
3942                 if (info[i].value_name_len > value_needed) {
3943                         torture_fail(tctx,
3944                                 talloc_asprintf(tctx,
3945                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3946                                 info[i].value_name_len, value_needed));
3947                 }
3948                 if (info[i].data_length > data_needed) {
3949                         torture_fail(tctx,
3950                                 talloc_asprintf(tctx,
3951                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3952                                 info[i].data_length, data_needed));
3953                 }
3954         }
3955
3956         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3957          * sort or not sort the replies by value name, we should be able to do
3958          * the following entry comparison */
3959
3960         data_offered = data_needed;
3961         value_offered = value_needed;
3962
3963         for (i=0; i < count; i++) {
3964
3965                 const char *value_name;
3966                 uint8_t *data;
3967
3968                 torture_assert(tctx,
3969                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3970                                              &type, &value_needed, &data_needed,
3971                                              &value_name, &data, &result),
3972                         "EnumPrinterData failed");
3973
3974                 if (i -1 == count) {
3975                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3976                                 "unexpected result");
3977                         break;
3978                 } else {
3979                         torture_assert_werr_ok(tctx, result, "unexpected result");
3980                 }
3981
3982                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3983                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3984                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3985                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3986                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3987         }
3988
3989         torture_assert(tctx,
3990                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3991                 "DeletePrinterData failed");
3992         torture_assert(tctx,
3993                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3994                 "DeletePrinterData failed");
3995         torture_assert(tctx,
3996                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3997                 "DeletePrinterData failed");
3998
3999         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4000
4001         return true;
4002 }
4003
4004 static bool test_DeletePrinterData(struct torture_context *tctx,
4005                                    struct dcerpc_binding_handle *b,
4006                                    struct policy_handle *handle,
4007                                    const char *value_name)
4008 {
4009         NTSTATUS status;
4010         struct spoolss_DeletePrinterData r;
4011
4012         r.in.handle = handle;
4013         r.in.value_name = value_name;
4014
4015         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4016                 r.in.value_name);
4017
4018         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4019
4020         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4021         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4022
4023         return true;
4024 }
4025
4026 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4027                                      struct dcerpc_binding_handle *b,
4028                                      struct policy_handle *handle,
4029                                      const char *key_name,
4030                                      const char *value_name)
4031 {
4032         struct spoolss_DeletePrinterDataEx r;
4033
4034         r.in.handle = handle;
4035         r.in.key_name = key_name;
4036         r.in.value_name = value_name;
4037
4038         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4039                 r.in.key_name, r.in.value_name);
4040
4041         torture_assert_ntstatus_ok(tctx,
4042                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4043                 "DeletePrinterDataEx failed");
4044         torture_assert_werr_ok(tctx, r.out.result,
4045                 "DeletePrinterDataEx failed");
4046
4047         return true;
4048 }
4049
4050 static bool test_DeletePrinterKey(struct torture_context *tctx,
4051                                   struct dcerpc_binding_handle *b,
4052                                   struct policy_handle *handle,
4053                                   const char *key_name)
4054 {
4055         struct spoolss_DeletePrinterKey r;
4056
4057         r.in.handle = handle;
4058         r.in.key_name = key_name;
4059
4060         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4061
4062         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4063                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4064                 return true;
4065         }
4066
4067         torture_assert_ntstatus_ok(tctx,
4068                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4069                 "DeletePrinterKey failed");
4070         torture_assert_werr_ok(tctx, r.out.result,
4071                 "DeletePrinterKey failed");
4072
4073         return true;
4074 }
4075
4076 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4077                                  struct dcerpc_binding_handle *b,
4078                                  struct policy_handle *handle)
4079 {
4080         struct winreg_OpenHKLM r;
4081
4082         r.in.system_name = NULL;
4083         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4084         r.out.handle = handle;
4085
4086         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4087
4088         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4089         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4090
4091         return true;
4092 }
4093
4094 static void init_winreg_String(struct winreg_String *name, const char *s)
4095 {
4096         name->name = s;
4097         if (s) {
4098                 name->name_len = 2 * (strlen_m(s) + 1);
4099                 name->name_size = name->name_len;
4100         } else {
4101                 name->name_len = 0;
4102                 name->name_size = 0;
4103         }
4104 }
4105
4106 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4107                                      struct dcerpc_binding_handle *b,
4108                                      struct policy_handle *hive_handle,
4109                                      const char *keyname,
4110                                      uint32_t options,
4111                                      struct policy_handle *key_handle)
4112 {
4113         struct winreg_OpenKey r;
4114
4115         r.in.parent_handle = hive_handle;
4116         init_winreg_String(&r.in.keyname, keyname);
4117         r.in.options = options;
4118         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4119         r.out.handle = key_handle;
4120
4121         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4122
4123         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4124         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4125
4126         return true;
4127 }
4128
4129 static bool test_winreg_OpenKey(struct torture_context *tctx,
4130                                 struct dcerpc_binding_handle *b,
4131                                 struct policy_handle *hive_handle,
4132                                 const char *keyname,
4133                                 struct policy_handle *key_handle)
4134 {
4135         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4136                                         REG_OPTION_NON_VOLATILE, key_handle);
4137 }
4138
4139 static bool test_winreg_CloseKey(struct torture_context *tctx,
4140                                  struct dcerpc_binding_handle *b,
4141                                  struct policy_handle *handle)
4142 {
4143         struct winreg_CloseKey r;
4144
4145         r.in.handle = handle;
4146         r.out.handle = handle;
4147
4148         torture_comment(tctx, "Testing winreg_CloseKey\n");
4149
4150         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4151         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4152
4153         return true;
4154 }
4155
4156 bool test_winreg_QueryValue(struct torture_context *tctx,
4157                             struct dcerpc_binding_handle *b,
4158                             struct policy_handle *handle,
4159                             const char *value_name,
4160                             enum winreg_Type *type_p,
4161                             uint32_t *data_size_p,
4162                             uint32_t *data_length_p,
4163                             uint8_t **data_p)
4164 {
4165         struct winreg_QueryValue r;
4166         enum winreg_Type type = REG_NONE;
4167         uint32_t data_size = 0;
4168         uint32_t data_length = 0;
4169         struct winreg_String valuename;
4170         uint8_t *data = NULL;
4171
4172         init_winreg_String(&valuename, value_name);
4173
4174         data = talloc_zero_array(tctx, uint8_t, 0);
4175
4176         r.in.handle = handle;
4177         r.in.value_name = &valuename;
4178         r.in.type = &type;
4179         r.in.data_size = &data_size;
4180         r.in.data_length = &data_length;
4181         r.in.data = data;
4182         r.out.type = &type;
4183         r.out.data = data;
4184         r.out.data_size = &data_size;
4185         r.out.data_length = &data_length;
4186
4187         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4188
4189         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4190         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4191                 *r.in.data_size = *r.out.data_size;
4192                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4193                 r.in.data = data;
4194                 r.out.data = data;
4195                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4196         }
4197         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4198
4199         if (type_p) {
4200                 *type_p = *r.out.type;
4201         }
4202         if (data_size_p) {
4203                 *data_size_p = *r.out.data_size;
4204         }
4205         if (data_length_p) {
4206                 *data_length_p = *r.out.data_length;
4207         }
4208         if (data_p) {
4209                 *data_p = r.out.data;
4210         }
4211
4212         return true;
4213 }
4214
4215 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4216                                           struct dcerpc_binding_handle *b,
4217                                           struct policy_handle *handle,
4218                                           const char *printer_name,
4219                                           const char *key_name,
4220                                           const char *value_name,
4221                                           enum winreg_Type *w_type,
4222                                           uint32_t *w_size,
4223                                           uint32_t *w_length,
4224                                           uint8_t **w_data)
4225 {
4226         const char *printer_key;
4227         struct policy_handle key_handle;
4228
4229         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4230                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4231
4232         torture_assert(tctx,
4233                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4234
4235         torture_assert(tctx,
4236                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4237
4238         torture_assert(tctx,
4239                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4240
4241         return true;
4242 }
4243
4244 static bool test_GetForm_winreg(struct torture_context *tctx,
4245                                 struct dcerpc_binding_handle *b,
4246                                 struct policy_handle *handle,
4247                                 const char *key_name,
4248                                 const char *form_name,
4249                                 enum winreg_Type *w_type,
4250                                 uint32_t *w_size,
4251                                 uint32_t *w_length,
4252                                 uint8_t **w_data)
4253 {
4254         struct policy_handle key_handle;
4255
4256         torture_assert(tctx,
4257                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4258
4259         torture_assert(tctx,
4260                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4261
4262         torture_assert(tctx,
4263                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4264
4265         return true;
4266 }
4267
4268 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4269                                       struct dcerpc_binding_handle *b,
4270                                       struct policy_handle *handle,
4271                                       const char *symlink_keyname,
4272                                       const char *symlink_destination)
4273 {
4274         /* check if the first key is a symlink to the second key */
4275
4276         enum winreg_Type w_type;
4277         uint32_t w_size;
4278         uint32_t w_length;
4279         uint8_t *w_data;
4280         struct policy_handle key_handle;
4281         DATA_BLOB blob;
4282         const char *str;
4283
4284         if (torture_setting_bool(tctx, "samba3", false)) {
4285                 torture_skip(tctx, "skip winreg symlink test against samba");
4286         }
4287
4288         torture_assert(tctx,
4289                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4290                         "failed to open key link");
4291
4292         torture_assert(tctx,
4293                 test_winreg_QueryValue(tctx, b, &key_handle,
4294                                        "SymbolicLinkValue",
4295                                        &w_type, &w_size, &w_length, &w_data),
4296                 "failed to query for 'SymbolicLinkValue' attribute");
4297
4298         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4299
4300         blob = data_blob(w_data, w_size);
4301         str = reg_val_data_string(tctx, REG_SZ, blob);
4302
4303         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4304
4305         torture_assert(tctx,
4306                 test_winreg_CloseKey(tctx, b, &key_handle),
4307                 "failed to close key link");
4308
4309         return true;
4310 }
4311
4312 static const char *strip_unc(const char *unc)
4313 {
4314         char *name;
4315
4316         if (!unc) {
4317                 return NULL;
4318         }
4319
4320         if (unc[0] == '\\' && unc[1] == '\\') {
4321                 unc +=2;
4322         }
4323
4324         name = strchr(unc, '\\');
4325         if (name) {
4326                 return name+1;
4327         }
4328
4329         return unc;
4330 }
4331
4332 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4333                                        struct dcerpc_binding_handle *b,
4334                                        struct policy_handle *handle,
4335                                        const char *printer_name,
4336                                        struct dcerpc_binding_handle *winreg_handle,
4337                                        struct policy_handle *hive_handle)
4338 {
4339         union spoolss_PrinterInfo info;
4340         const char *keys[] = {
4341                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4342                 TOP_LEVEL_PRINT_PRINTERS_KEY
4343         };
4344         int i;
4345         const char *printername, *sharename;
4346
4347         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4348
4349         torture_assert(tctx,
4350                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4351                 "failed to get printer info level 2");
4352
4353         printername = strip_unc(info.info2.printername);
4354         sharename = strip_unc(info.info2.sharename);
4355
4356 #define test_sz(wname, iname) \
4357 do {\
4358         DATA_BLOB blob;\
4359         const char *str;\
4360         enum winreg_Type w_type;\
4361         uint32_t w_size;\
4362         uint32_t w_length;\
4363         uint8_t *w_data;\
4364         torture_assert(tctx,\
4365                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4366                                        &w_type, &w_size, &w_length, &w_data),\
4367                 "failed to query winreg");\
4368         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4369         blob = data_blob(w_data, w_size);\
4370         str = reg_val_data_string(tctx, REG_SZ, blob);\
4371         if (w_size == 2 && iname == NULL) {\
4372                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4373         } else {\
4374                 torture_assert_str_equal(tctx, str, iname,\
4375                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4376         }\
4377 } while(0);
4378
4379 #define test_dword(wname, iname) \
4380 do {\
4381         uint32_t value;\
4382         enum winreg_Type w_type;\
4383         uint32_t w_size;\
4384         uint32_t w_length;\
4385         uint8_t *w_data;\
4386         torture_assert(tctx,\
4387                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4388                                        &w_type, &w_size, &w_length, &w_data),\
4389                 "failed to query winreg");\
4390         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4391         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4392         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4393         value = IVAL(w_data, 0);\
4394         torture_assert_int_equal(tctx, value, iname,\
4395                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4396 } while(0);
4397
4398 #define test_binary(wname, iname) \
4399 do {\
4400         enum winreg_Type w_type;\
4401         uint32_t w_size;\
4402         uint32_t w_length;\
4403         uint8_t *w_data;\
4404         torture_assert(tctx,\
4405                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4406                                        &w_type, &w_size, &w_length, &w_data),\
4407                 "failed to query winreg");\
4408         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4409         torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4410         torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4411                 "binary unequal");\
4412 } while(0);
4413
4414
4415 #define test_dm(wname, iname) \
4416 do {\
4417         DATA_BLOB blob;\
4418         struct spoolss_DeviceMode dm;\
4419         enum ndr_err_code ndr_err;\
4420         enum winreg_Type w_type;\
4421         uint32_t w_size;\
4422         uint32_t w_length;\
4423         uint8_t *w_data;\
4424         torture_assert(tctx,\
4425                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4426                                        &w_type, &w_size, &w_length, &w_data),\
4427                 "failed to query winreg");\
4428         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4429         blob = data_blob(w_data, w_size);\
4430         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4431                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4432         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4433         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4434                 "dm unequal");\
4435 } while(0);
4436
4437 #define test_sd(wname, iname) \
4438 do {\
4439         DATA_BLOB blob;\
4440         struct security_descriptor sd;\
4441         enum ndr_err_code ndr_err;\
4442         enum winreg_Type w_type;\
4443         uint32_t w_size;\
4444         uint32_t w_length;\
4445         uint8_t *w_data;\
4446         torture_assert(tctx,\
4447                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4448                                        &w_type, &w_size, &w_length, &w_data),\
4449                 "failed to query winreg");\
4450         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4451         blob = data_blob(w_data, w_size);\
4452         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4453                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4454         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4455         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4456                 "sd unequal");\
4457 } while(0);
4458
4459 #define test_multi_sz(wname, iname) \
4460 do {\
4461         DATA_BLOB blob;\
4462         const char **array;\
4463         enum winreg_Type w_type;\
4464         uint32_t w_size;\
4465         uint32_t w_length;\
4466         uint8_t *w_data;\
4467         int i;\
4468         torture_assert(tctx,\
4469                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4470                                        &w_type, &w_size, &w_length, &w_data),\
4471                 "failed to query winreg");\
4472         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4473         blob = data_blob(w_data, w_size);\
4474         torture_assert(tctx, \
4475                 pull_reg_multi_sz(tctx, &blob, &array),\
4476                 "failed to pull multi sz");\
4477         for (i=0; array[i] != NULL; i++) {\
4478                 torture_assert_str_equal(tctx, array[i], iname[i],\
4479                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4480         }\
4481 } while(0);
4482
4483         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4484                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4485                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4486         {
4487                 torture_warning(tctx, "failed to check for winreg symlink");
4488         }
4489
4490         for (i=0; i < ARRAY_SIZE(keys); i++) {
4491
4492                 const char *printer_key;
4493                 struct policy_handle key_handle;
4494
4495                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4496                         keys[i], printer_name);
4497
4498                 torture_assert(tctx,
4499                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4500
4501                 test_sz("Name", printername);
4502                 test_sz("Share Name", sharename);
4503                 test_sz("Port", info.info2.portname);
4504                 test_sz("Printer Driver", info.info2.drivername);
4505                 test_sz("Description", info.info2.comment);
4506                 test_sz("Location", info.info2.location);
4507                 test_sz("Separator File", info.info2.sepfile);
4508                 test_sz("Print Processor", info.info2.printprocessor);
4509                 test_sz("Datatype", info.info2.datatype);
4510                 test_sz("Parameters", info.info2.parameters);
4511                 /* winreg: 0, spoolss not */
4512 /*              test_dword("Attributes", info.info2.attributes); */
4513                 test_dword("Priority", info.info2.priority);
4514                 test_dword("Default Priority", info.info2.defaultpriority);
4515                 /* winreg: 60, spoolss: 0 */
4516 /*              test_dword("StartTime", info.info2.starttime); */
4517 /*              test_dword("UntilTime", info.info2.untiltime); */
4518                 /* winreg != spoolss */
4519 /*              test_dword("Status", info.info2.status); */
4520                 test_dm("Default DevMode", info.info2.devmode);
4521                 test_sd("Security", info.info2.secdesc);
4522
4523                 torture_assert(tctx,
4524                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4525         }
4526
4527 #undef test_dm
4528 #undef test_sd
4529
4530         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4531
4532         return true;
4533 }
4534
4535 static bool test_PrintProcessors(struct torture_context *tctx,
4536                                  struct dcerpc_binding_handle *b,
4537                                  const char *environment,
4538                                  struct dcerpc_binding_handle *winreg_handle,
4539                                  struct policy_handle *hive_handle)
4540 {
4541         union spoolss_PrintProcessorInfo *info;
4542         uint32_t count;
4543         int i;
4544
4545         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4546
4547         torture_assert(tctx,
4548                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4549                 "failed to enum print processors level 1");
4550
4551         for (i=0; i < count; i++) {
4552
4553                 const char *processor_key;
4554                 struct policy_handle key_handle;
4555
4556                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4557                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4558                                                 environment,
4559                                                 info[i].info1.print_processor_name);
4560
4561                 torture_assert(tctx,
4562                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4563
4564                 /* nothing to check in there so far */
4565
4566                 torture_assert(tctx,
4567                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4568         }
4569
4570         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4571
4572         return true;
4573 }
4574
4575 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4576                                          struct dcerpc_binding_handle *b,
4577                                          struct policy_handle *handle,
4578                                          const char *driver_name,
4579                                          const char *architecture,
4580                                          uint32_t level,
4581                                          uint32_t client_major_version,
4582                                          uint32_t client_minor_version,
4583                                          union spoolss_DriverInfo *info_p,
4584                                          WERROR *result);
4585
4586 static const char *strip_path(const char *path)
4587 {
4588         char *p;
4589
4590         if (path == NULL) {
4591                 return NULL;
4592         }
4593
4594         p = strrchr(path, '\\');
4595         if (p) {
4596                 return p+1;
4597         }
4598
4599         return path;
4600 }
4601
4602 static const char **strip_paths(const char **path_array)
4603 {
4604         int i;
4605
4606         if (path_array == NULL) {
4607                 return NULL;
4608         }
4609
4610         for (i=0; path_array[i] != NULL; i++) {
4611                 path_array[i] = strip_path(path_array[i]);
4612         }
4613
4614         return path_array;
4615 }
4616
4617 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4618 {
4619         time_t t;
4620         struct tm *tm;
4621
4622         if (nt == 0) {
4623                 return talloc_strdup(mem_ctx, "01/01/1601");
4624         }
4625
4626         t = nt_time_to_unix(nt);
4627         tm = localtime(&t);
4628
4629         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4630                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4631 }
4632
4633 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4634 {
4635         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4636                 (unsigned)((v >> 48) & 0xFFFF),
4637                 (unsigned)((v >> 32) & 0xFFFF),
4638                 (unsigned)((v >> 16) & 0xFFFF),
4639                 (unsigned)(v & 0xFFFF));
4640 }
4641
4642 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4643                                       struct dcerpc_binding_handle *b,
4644                                       struct policy_handle *handle,
4645                                       const char *printer_name,
4646                                       const char *driver_name,
4647                                       const char *environment,
4648                                       enum spoolss_DriverOSVersion version,
4649                                       struct dcerpc_binding_handle *winreg_handle,
4650                                       struct policy_handle *hive_handle,
4651                                       const char *server_name_slash)
4652 {
4653         WERROR result;
4654         union spoolss_DriverInfo info;
4655         const char *driver_key;
4656         struct policy_handle key_handle;
4657
4658         const char *driver_path;
4659         const char *data_file;
4660         const char *config_file;
4661         const char *help_file;
4662         const char **dependent_files;
4663
4664         const char *driver_date;
4665         const char *inbox_driver_date;
4666
4667         const char *driver_version;
4668         const char *inbox_driver_version;
4669
4670         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4671
4672         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4673                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4674                                      environment,
4675                                      version,
4676                                      driver_name);
4677
4678         torture_assert(tctx,
4679                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4680                 "failed to open driver key");
4681
4682         if (torture_setting_bool(tctx, "samba3", false) ||
4683             torture_setting_bool(tctx, "w2k3", false)) {
4684                 goto try_level6;
4685         }
4686
4687         if (handle) {
4688                 torture_assert(tctx,
4689                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4690                         "failed to get driver info level 8");
4691         } else {
4692                 torture_assert(tctx,
4693                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4694                         "failed to get driver info level 8");
4695         }
4696
4697         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4698                 goto try_level6;
4699         }
4700
4701         driver_path     = strip_path(info.info8.driver_path);
4702         data_file       = strip_path(info.info8.data_file);
4703         config_file     = strip_path(info.info8.config_file);
4704         help_file       = strip_path(info.info8.help_file);
4705         dependent_files = strip_paths(info.info8.dependent_files);
4706
4707         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4708         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4709
4710         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4711         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4712
4713         test_sz("Configuration File",           config_file);
4714         test_sz("Data File",                    data_file);
4715         test_sz("Datatype",                     info.info8.default_datatype);
4716         test_sz("Driver",                       driver_path);
4717         test_sz("DriverDate",                   driver_date);
4718         test_sz("DriverVersion",                driver_version);
4719         test_sz("HardwareID",                   info.info8.hardware_id);
4720         test_sz("Help File",                    help_file);
4721         test_sz("InfPath",                      info.info8.inf_path);
4722         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4723         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4724         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4725         test_sz("Monitor",                      info.info8.monitor_name);
4726         test_sz("OEM URL",                      info.info8.manufacturer_url);
4727         test_sz("Print Processor",              info.info8.print_processor);
4728         test_sz("Provider",                     info.info8.provider);
4729         test_sz("VendorSetup",                  info.info8.vendor_setup);
4730         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4731         test_multi_sz("Dependent Files",        dependent_files);
4732         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4733         test_multi_sz("Previous Names",         info.info8.previous_names);
4734 /*      test_dword("Attributes",                ?); */
4735         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4736         test_dword("Version",                   info.info8.version);
4737 /*      test_dword("TempDir",                   ?); */
4738
4739  try_level6:
4740
4741         if (handle) {
4742                 torture_assert(tctx,
4743                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4744                         "failed to get driver info level 6");
4745         } else {
4746                 torture_assert(tctx,
4747                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4748                         "failed to get driver info level 6");
4749         }
4750
4751         driver_path     = strip_path(info.info6.driver_path);
4752         data_file       = strip_path(info.info6.data_file);
4753         config_file     = strip_path(info.info6.config_file);
4754         help_file       = strip_path(info.info6.help_file);
4755         dependent_files = strip_paths(info.info6.dependent_files);
4756
4757         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4758
4759         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4760
4761         test_sz("Configuration File",           config_file);
4762         test_sz("Data File",                    data_file);
4763         test_sz("Datatype",                     info.info6.default_datatype);
4764         test_sz("Driver",                       driver_path);
4765         if (torture_setting_bool(tctx, "w2k3", false)) {
4766                 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4767                 push_nttime(blob.data, 0, info.info6.driver_date);
4768                 test_binary("DriverDate",       blob);
4769                 SBVAL(blob.data, 0, info.info6.driver_version);
4770                 test_binary("DriverVersion",    blob);
4771         } else {
4772                 test_sz("DriverDate",           driver_date);
4773                 test_sz("DriverVersion",        driver_version);
4774         }
4775         test_sz("HardwareID",                   info.info6.hardware_id);
4776         test_sz("Help File",                    help_file);
4777         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4778         test_sz("Monitor",                      info.info6.monitor_name);
4779         test_sz("OEM URL",                      info.info6.manufacturer_url);
4780         test_sz("Provider",                     info.info6.provider);
4781         test_multi_sz("Dependent Files",        dependent_files);
4782         test_multi_sz("Previous Names",         info.info6.previous_names);
4783 /*      test_dword("Attributes",                ?); */
4784         test_dword("Version",                   info.info6.version);
4785 /*      test_dword("TempDir",                   ?); */
4786
4787         if (handle) {
4788                 torture_assert(tctx,
4789                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4790                         "failed to get driver info level 3");
4791         } else {
4792                 torture_assert(tctx,
4793                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4794                         "failed to get driver info level 3");
4795         }
4796
4797         driver_path     = strip_path(info.info3.driver_path);
4798         data_file       = strip_path(info.info3.data_file);
4799         config_file     = strip_path(info.info3.config_file);
4800         help_file       = strip_path(info.info3.help_file);
4801         dependent_files = strip_paths(info.info3.dependent_files);
4802
4803         test_sz("Configuration File",           config_file);
4804         test_sz("Data File",                    data_file);
4805         test_sz("Datatype",                     info.info3.default_datatype);
4806         test_sz("Driver",                       driver_path);
4807         test_sz("Help File",                    help_file);
4808         test_sz("Monitor",                      info.info3.monitor_name);
4809         test_multi_sz("Dependent Files",        dependent_files);
4810 /*      test_dword("Attributes",                ?); */
4811         test_dword("Version",                   info.info3.version);
4812 /*      test_dword("TempDir",                   ?); */
4813
4814
4815         torture_assert(tctx,
4816                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4817
4818         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4819
4820         return true;
4821 }
4822
4823 #undef test_sz
4824 #undef test_dword
4825
4826 static bool test_SetPrinterData(struct torture_context *tctx,
4827                                 struct dcerpc_binding_handle *b,
4828                                 struct policy_handle *handle,
4829                                 const char *value_name,
4830                                 enum winreg_Type type,
4831                                 uint8_t *data,
4832                                 uint32_t offered)
4833 {
4834         struct spoolss_SetPrinterData r;
4835
4836         r.in.handle = handle;
4837         r.in.value_name = value_name;
4838         r.in.type = type;
4839         r.in.data = data;
4840         r.in.offered = offered;
4841
4842         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4843                 r.in.value_name);
4844
4845         torture_assert_ntstatus_ok(tctx,
4846                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4847                 "SetPrinterData failed");
4848         torture_assert_werr_ok(tctx, r.out.result,
4849                 "SetPrinterData failed");
4850
4851         return true;
4852 }
4853
4854 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4855                                        struct dcerpc_binding_handle *b,
4856                                        struct policy_handle *handle,
4857                                        const char *printer_name,
4858                                        struct dcerpc_binding_handle *winreg_handle,
4859                                        struct policy_handle *hive_handle)
4860 {
4861         const char *values[] = {
4862                 "spootyfoot",
4863                 "spooty\\foot",
4864 #if 0
4865         /* FIXME: not working with s3 atm. */
4866                 "spooty,foot",
4867                 "spooty,fo,ot",
4868 #endif
4869                 "spooty foot",
4870 #if 0
4871         /* FIXME: not working with s3 atm. */
4872                 "spooty\\fo,ot",
4873                 "spooty,fo\\ot"
4874 #endif
4875         };
4876         int i;
4877
4878         for (i=0; i < ARRAY_SIZE(values); i++) {
4879
4880                 enum winreg_Type type, expected_type = REG_SZ;
4881                 DATA_BLOB blob;
4882                 uint8_t *data;
4883                 uint32_t needed;
4884
4885                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4886                 type = REG_SZ;
4887
4888                 torture_assert(tctx,
4889                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4890                         "SetPrinterData failed");
4891
4892                 torture_assert(tctx,
4893                         test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4894                         "GetPrinterData failed");
4895
4896                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4897                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4898                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4899
4900                 if (winreg_handle && hive_handle) {
4901
4902                         enum winreg_Type w_type;
4903                         uint32_t w_size;
4904                         uint32_t w_length;
4905                         uint8_t *w_data;
4906
4907                         torture_assert(tctx,
4908                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4909                                         printer_name, "PrinterDriverData", values[i],
4910                                         &w_type, &w_size, &w_length, &w_data), "");
4911
4912                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4913                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4914                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4915                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4916                 }
4917
4918                 torture_assert(tctx,
4919                         test_DeletePrinterData(tctx, b, handle, values[i]),
4920                         "DeletePrinterData failed");
4921         }
4922
4923         return true;
4924 }
4925
4926
4927 static bool test_EnumPrinterKey(struct torture_context *tctx,
4928                                 struct dcerpc_binding_handle *b,
4929                                 struct policy_handle *handle,
4930                                 const char *key_name,
4931                                 const char ***array);
4932
4933 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4934                                   struct dcerpc_binding_handle *b,
4935                                   struct policy_handle *handle,
4936                                   const char *key_name,
4937                                   const char *value_name,
4938                                   enum winreg_Type type,
4939                                   uint8_t *data,
4940                                   uint32_t offered)
4941 {
4942         NTSTATUS status;
4943         struct spoolss_SetPrinterDataEx r;
4944
4945         r.in.handle = handle;
4946         r.in.key_name = key_name;
4947         r.in.value_name = value_name;
4948         r.in.type = type;
4949         r.in.data = data;
4950         r.in.offered = offered;
4951
4952         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4953                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4954
4955         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4956
4957         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4958         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4959
4960         return true;
4961 }
4962
4963 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4964                                        struct dcerpc_pipe *p,
4965                                        struct policy_handle *handle)
4966 {
4967         struct dcerpc_binding_handle *b = p->binding_handle;
4968         const char *value_name = "dog";
4969         const char *keys[] = {
4970                 "torturedataex",
4971                 "torture data ex",
4972                 "torturedataex_with_subkey\\subkey",
4973                 "torturedataex_with_subkey\\subkey:0",
4974                 "torturedataex_with_subkey\\subkey:1",
4975                 "torturedataex_with_subkey\\subkey\\subsubkey",
4976                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4977                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4978                 "torture,data",
4979                 "torture,data,ex",
4980                 "torture,data\\ex",
4981                 "torture\\data,ex",
4982                 "torture/data",
4983                 "torture/data ex",
4984                 "torture/data ex/sub",
4985                 "torture//data",
4986                 "torture//data ex",
4987                 "torture//data ex/sub",
4988                 "torture//data ex//sub",
4989         };
4990         int i;
4991
4992         for (i=0; i < ARRAY_SIZE(keys); i++) {
4993
4994                 char *c;
4995                 const char *key;
4996                 enum winreg_Type type;
4997                 DATA_BLOB blob_in, blob_out;
4998                 const char **subkeys;
4999                 uint32_t ecount;
5000                 struct spoolss_PrinterEnumValues *einfo;
5001                 uint32_t needed;
5002
5003                 blob_in = data_blob_talloc(tctx, NULL, 42);
5004
5005                 generate_random_buffer(blob_in.data, blob_in.length);
5006
5007                 torture_assert(tctx,
5008                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5009                         "failed to call SetPrinterDataEx");
5010
5011                 torture_assert(tctx,
5012                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5013                         "failed to call GetPrinterDataEx");
5014
5015                 blob_out.length = needed;
5016                 torture_assert(tctx,
5017                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5018                         "failed to call EnumPrinterDataEx");
5019
5020                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5021                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5022                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5023
5024                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5025                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5026                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5027                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5028                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5029                 if (einfo[0].data_length > 0) {
5030                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5031                 }
5032
5033                 key = talloc_strdup(tctx, keys[i]);
5034
5035                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5036                         return false;
5037                 }
5038
5039                 c = strchr(key, '\\');
5040                 if (c) {
5041                         int k;
5042
5043                         /* we have subkeys */
5044
5045                         *c = 0;
5046
5047                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5048                                 return false;
5049                         }
5050
5051                         for (k=0; subkeys && subkeys[k]; k++) {
5052
5053                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5054
5055                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5056                                         return false;
5057                                 }
5058                         }
5059
5060                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5061                                 return false;
5062                         }
5063
5064                 } else {
5065                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5066                                 return false;
5067                         }
5068                 }
5069         }
5070
5071         return true;
5072 }
5073
5074 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5075                                          struct dcerpc_pipe *p,
5076                                          struct policy_handle *handle)
5077 {
5078         struct dcerpc_binding_handle *b = p->binding_handle;
5079         const char *key = "torturedataex";
5080         const char *values[] = {
5081                 "torture_value",
5082                 "torture value",
5083                 "torture,value",
5084                 "torture/value",
5085                 "torture\\value",
5086                 "torture\\\\value"
5087         };
5088         int i;
5089
5090         for (i=0; i < ARRAY_SIZE(values); i++) {
5091
5092                 enum winreg_Type type;
5093                 DATA_BLOB blob_in, blob_out;
5094                 uint32_t ecount;
5095                 struct spoolss_PrinterEnumValues *einfo;
5096                 uint32_t needed;
5097
5098                 if (torture_setting_bool(tctx, "samba3", false)) {
5099                         char *q;
5100                         q = strrchr(values[i], ',');
5101                         if (q) {
5102                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5103                                                 values[i]);
5104                                 continue;
5105                         }
5106                 }
5107
5108                 blob_in = data_blob_talloc(tctx, NULL, 42);
5109
5110                 generate_random_buffer(blob_in.data, blob_in.length);
5111
5112                 torture_assert(tctx,
5113                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5114                         "failed to call SetPrinterDataEx");
5115
5116                 torture_assert(tctx,
5117                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5118                         "failed to call GetPrinterDataEx");
5119
5120                 blob_out.length = needed;
5121                 torture_assert(tctx,
5122                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5123                         "failed to call EnumPrinterDataEx");
5124
5125                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5126                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5127                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5128
5129                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5130                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5131                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5132                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5133                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5134                 if (einfo[0].data_length > 0) {
5135                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5136                 }
5137
5138                 torture_assert(tctx,
5139                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5140                         "failed to call DeletePrinterDataEx");
5141         }
5142
5143         return true;
5144 }
5145
5146
5147 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5148                                          struct dcerpc_pipe *p,
5149                                          struct policy_handle *handle,
5150                                          const char *printername,
5151                                          struct dcerpc_binding_handle *winreg_handle,
5152                                          struct policy_handle *hive_handle)
5153 {
5154         struct dcerpc_binding_handle *b = p->binding_handle;
5155         const char *value_name = "dog";
5156         const char *key_name = "torturedataex";
5157         enum winreg_Type types[] = {
5158                 REG_SZ,
5159                 REG_MULTI_SZ,
5160                 REG_DWORD,
5161                 REG_BINARY
5162         };
5163         const char *str = "abcdefghi";
5164         int t, s;
5165
5166         for (t=0; t < ARRAY_SIZE(types); t++) {
5167         for (s=0; s < strlen(str); s++) {
5168
5169                 enum winreg_Type type;
5170                 const char *string = talloc_strndup(tctx, str, s);
5171                 const char *array[2];
5172                 DATA_BLOB blob = data_blob_string_const(string);
5173                 DATA_BLOB data;
5174                 uint8_t *data_out;
5175                 uint32_t needed, offered = 0;
5176                 uint32_t ecount;
5177                 struct spoolss_PrinterEnumValues *einfo;
5178
5179                 array[0] = talloc_strdup(tctx, string);
5180                 array[1] = NULL;
5181
5182                 if (types[t] == REG_DWORD) {
5183                         s = 0xffff;
5184                 }
5185
5186                 switch (types[t]) {
5187                 case REG_BINARY:
5188                         data = blob;
5189                         offered = blob.length;
5190                         break;
5191                 case REG_DWORD:
5192                         data = data_blob_talloc(tctx, NULL, 4);
5193                         SIVAL(data.data, 0, 0x12345678);
5194                         offered = 4;
5195                         break;
5196                 case REG_SZ:
5197                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5198                         type = REG_SZ;
5199                         offered = data.length;
5200                         /*strlen_m_term(data.string)*2;*/
5201                         break;
5202                 case REG_MULTI_SZ:
5203                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5204                         type = REG_MULTI_SZ;
5205                         offered = data.length;
5206                         break;
5207                 default:
5208                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5209                 }
5210
5211                 torture_assert(tctx,
5212                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5213                         "failed to call SetPrinterDataEx");
5214
5215                 torture_assert(tctx,
5216                         test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5217                         "failed to call GetPrinterDataEx");
5218
5219                 torture_assert(tctx,
5220                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5221                         "failed to call EnumPrinterDataEx");
5222
5223                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5224                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5225                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5226
5227                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5228                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5229                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5230                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5231                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5232                 if (einfo[0].data_length > 0) {
5233                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5234                 }
5235
5236                 if (winreg_handle && hive_handle) {
5237                         enum winreg_Type w_type;
5238                         uint32_t w_size;
5239                         uint32_t w_length;
5240                         uint8_t *w_data;
5241
5242                         torture_assert(tctx,
5243                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5244                                         printername, key_name, value_name,
5245                                         &w_type, &w_size, &w_length, &w_data), "");
5246
5247                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5248                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5249                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5250                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5251                 }
5252
5253                 torture_assert(tctx,
5254                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5255                         "failed to call DeletePrinterDataEx");
5256         }
5257         }
5258
5259         return true;
5260 }
5261
5262 static bool test_PrinterData_winreg(struct torture_context *tctx,
5263                                     struct dcerpc_pipe *p,
5264                                     struct policy_handle *handle,
5265                                     const char *printer_name)
5266 {
5267         struct dcerpc_binding_handle *b = p->binding_handle;
5268         struct dcerpc_pipe *p2;
5269         bool ret = true;
5270         struct policy_handle hive_handle;
5271         struct dcerpc_binding_handle *b2;
5272
5273         torture_assert_ntstatus_ok(tctx,
5274                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5275                 "could not open winreg pipe");
5276         b2 = p2->binding_handle;
5277
5278         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5279
5280         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5281         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5282
5283         test_winreg_CloseKey(tctx, b2, &hive_handle);
5284
5285         talloc_free(p2);
5286
5287         return ret;
5288 }
5289
5290 static bool test_Forms_winreg(struct torture_context *tctx,
5291                               struct dcerpc_binding_handle *b,
5292                               struct policy_handle *handle,
5293                               bool print_server,
5294                               const char *printer_name)
5295 {
5296         struct dcerpc_pipe *p2;
5297         bool ret = true;
5298         struct policy_handle hive_handle;
5299         struct dcerpc_binding_handle *b2;
5300
5301         torture_assert_ntstatus_ok(tctx,
5302                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5303                 "could not open winreg pipe");
5304         b2 = p2->binding_handle;
5305
5306         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5307
5308         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5309
5310         test_winreg_CloseKey(tctx, b2, &hive_handle);
5311
5312         talloc_free(p2);
5313
5314         return ret;
5315 }
5316
5317 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5318                                     struct dcerpc_pipe *p,
5319                                     struct policy_handle *handle,
5320                                     const char *printer_name)
5321 {
5322         struct dcerpc_binding_handle *b = p->binding_handle;
5323         struct dcerpc_pipe *p2;
5324         bool ret = true;
5325         struct policy_handle hive_handle;
5326         struct dcerpc_binding_handle *b2;
5327
5328         torture_assert_ntstatus_ok(tctx,
5329                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5330                 "could not open winreg pipe");
5331         b2 = p2->binding_handle;
5332
5333         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5334
5335         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5336
5337         test_winreg_CloseKey(tctx, b2, &hive_handle);
5338
5339         talloc_free(p2);
5340
5341         return ret;
5342 }
5343
5344 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5345                                    struct dcerpc_pipe *p,
5346                                    struct policy_handle *handle,
5347                                    const char *printer_name,
5348                                    const char *driver_name,
5349                                    const char *environment,
5350                                    enum spoolss_DriverOSVersion version)
5351 {
5352         struct dcerpc_binding_handle *b = p->binding_handle;
5353         struct dcerpc_pipe *p2;
5354         bool ret = true;
5355         struct policy_handle hive_handle;
5356         struct dcerpc_binding_handle *b2;
5357
5358         torture_assert_ntstatus_ok(tctx,
5359                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5360                 "could not open winreg pipe");
5361         b2 = p2->binding_handle;
5362
5363         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5364
5365         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5366
5367         test_winreg_CloseKey(tctx, b2, &hive_handle);
5368
5369         talloc_free(p2);
5370
5371         return ret;
5372 }
5373
5374 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5375                                         struct dcerpc_binding_handle *b,
5376                                         const char *environment)
5377 {
5378         struct dcerpc_pipe *p2;
5379         bool ret = true;
5380         struct policy_handle hive_handle;
5381         struct dcerpc_binding_handle *b2;
5382
5383         torture_assert_ntstatus_ok(tctx,
5384                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5385                 "could not open winreg pipe");
5386         b2 = p2->binding_handle;
5387
5388         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5389
5390         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5391
5392         test_winreg_CloseKey(tctx, b2, &hive_handle);
5393
5394         talloc_free(p2);
5395
5396         return ret;
5397 }
5398
5399 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5400                                        struct dcerpc_pipe *p,
5401                                        struct policy_handle *handle,
5402                                        const char *printer_name)
5403 {
5404         struct spoolss_SetPrinterInfoCtr info_ctr;
5405         struct spoolss_DevmodeContainer devmode_ctr;
5406         struct sec_desc_buf secdesc_ctr;
5407         union spoolss_SetPrinterInfo sinfo;
5408         union spoolss_PrinterInfo info;
5409         struct dcerpc_binding_handle *b = p->binding_handle;
5410         const char *pname;
5411
5412         ZERO_STRUCT(info_ctr);
5413         ZERO_STRUCT(devmode_ctr);
5414         ZERO_STRUCT(secdesc_ctr);
5415
5416         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5417
5418         torture_assert(tctx,
5419                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5420                 "failed to query Printer level 2");
5421
5422         torture_assert(tctx,
5423                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5424                 "failed to convert");
5425
5426         info_ctr.level = 2;
5427         info_ctr.info = sinfo;
5428
5429 #define TEST_SZ(wname, iname) \
5430 do {\
5431         enum winreg_Type type;\
5432         uint8_t *data;\
5433         uint32_t needed;\
5434         DATA_BLOB blob;\
5435         const char *str;\
5436         torture_assert(tctx,\
5437                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5438                 "failed to query");\
5439         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5440         blob = data_blob_const(data, needed);\
5441         torture_assert(tctx,\
5442                 pull_reg_sz(tctx, &blob, &str),\
5443                 "failed to pull REG_SZ");\
5444         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5445 } while(0);
5446
5447
5448 #define TEST_SET_SZ(wname, iname, val) \
5449 do {\
5450         enum winreg_Type type;\
5451         uint8_t *data;\
5452         uint32_t needed;\
5453         DATA_BLOB blob;\
5454         const char *str;\
5455         sinfo.info2->iname = val;\
5456         torture_assert(tctx,\
5457                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5458                 "failed to call SetPrinter");\
5459         torture_assert(tctx,\
5460                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5461                 "failed to query");\
5462         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5463         blob = data_blob_const(data, needed);\
5464         torture_assert(tctx,\
5465                 pull_reg_sz(tctx, &blob, &str),\
5466                 "failed to pull REG_SZ");\
5467         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5468 } while(0);
5469
5470 #define TEST_SET_DWORD(wname, iname, val) \
5471 do {\
5472         enum winreg_Type type;\
5473         uint8_t *data;\
5474         uint32_t needed;\
5475         uint32_t value;\
5476         sinfo.info2->iname = val;\
5477         torture_assert(tctx,\
5478                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5479                 "failed to call SetPrinter");\
5480         torture_assert(tctx,\
5481                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5482                 "failed to query");\
5483         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5484         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5485         value = IVAL(data, 0); \
5486         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5487 } while(0);
5488
5489         TEST_SET_SZ("description", comment, "newval");
5490         TEST_SET_SZ("location", location, "newval");
5491 /*      TEST_SET_DWORD("priority", priority, 25); */
5492
5493         torture_assert(tctx,
5494                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5495                 "failed to query Printer level 2");
5496
5497         TEST_SZ("description", info.info2.comment);
5498         TEST_SZ("driverName", info.info2.drivername);
5499         TEST_SZ("location", info.info2.location);
5500
5501         pname = strrchr(info.info2.printername, '\\');
5502         if (pname == NULL) {
5503                 pname = info.info2.printername;
5504         } else {
5505                 pname++;
5506         }
5507         TEST_SZ("printerName", pname);
5508         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5509         /* TEST_SZ("printShareName", info.info2.sharename); */
5510
5511         /* FIXME gd: complete the list */
5512
5513 #undef TEST_SZ
5514 #undef TEST_SET_SZ
5515 #undef TEST_DWORD
5516
5517         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5518
5519         return true;
5520 }
5521
5522 static bool test_print_processors_winreg(struct torture_context *tctx,
5523                                          void *private_data)
5524 {
5525         struct test_spoolss_context *ctx =
5526                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5527         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5528         struct dcerpc_binding_handle *b = p->binding_handle;
5529
5530         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5531 }
5532
5533 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5534                                          struct dcerpc_binding_handle *b,
5535                                          struct policy_handle *handle,
5536                                          uint32_t *change_id)
5537 {
5538         enum winreg_Type type;
5539         uint8_t *data;
5540         uint32_t needed;
5541
5542         torture_assert(tctx,
5543                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5544                 "failed to call GetPrinterData");
5545
5546         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5547         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5548
5549         *change_id = IVAL(data, 0);
5550
5551         return true;
5552 }
5553
5554 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5555                                            struct dcerpc_pipe *p,
5556                                            struct policy_handle *handle,
5557                                            uint32_t *change_id)
5558 {
5559         enum winreg_Type type;
5560         uint8_t *data;
5561         uint32_t needed;
5562
5563         torture_assert(tctx,
5564                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5565                 "failed to call GetPrinterData");
5566
5567         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5568         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5569
5570         *change_id = IVAL(data, 0);
5571
5572         return true;
5573 }
5574
5575 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5576                                          struct dcerpc_binding_handle *b,
5577                                          struct policy_handle *handle,
5578                                          uint32_t *change_id)
5579 {
5580         union spoolss_PrinterInfo info;
5581
5582         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5583                 "failed to query Printer level 0");
5584
5585         *change_id = info.info0.change_id;
5586
5587         return true;
5588 }
5589
5590 static bool test_ChangeID(struct torture_context *tctx,
5591                           struct dcerpc_pipe *p,
5592                           struct policy_handle *handle)
5593 {
5594         uint32_t change_id, change_id_ex, change_id_info;
5595         uint32_t change_id2, change_id_ex2, change_id_info2;
5596         union spoolss_PrinterInfo info;
5597         const char *comment;
5598         struct dcerpc_binding_handle *b = p->binding_handle;
5599
5600         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5601
5602         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5603                 "failed to query for ChangeID");
5604         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5605                 "failed to query for ChangeID");
5606         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5607                 "failed to query for ChangeID");
5608
5609         torture_assert_int_equal(tctx, change_id, change_id_ex,
5610                 "change_ids should all be equal");
5611         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5612                 "change_ids should all be equal");
5613
5614
5615         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5616
5617         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5618                 "failed to query for ChangeID");
5619         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5620                 "failed to query Printer level 2");
5621         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5622                 "failed to query for ChangeID");
5623         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5624                 "failed to query for ChangeID");
5625         torture_assert_int_equal(tctx, change_id, change_id_ex,
5626                 "change_id should not have changed");
5627         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5628                 "change_id should not have changed");
5629
5630
5631         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5632
5633         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5634                 "failed to query for ChangeID");
5635         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5636                 "failed to query for ChangeID");
5637         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5638                 "failed to query for ChangeID");
5639         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5640                 "failed to query Printer level 2");
5641         comment = talloc_strdup(tctx, info.info2.comment);
5642
5643         {
5644                 struct spoolss_SetPrinterInfoCtr info_ctr;
5645                 struct spoolss_DevmodeContainer devmode_ctr;
5646                 struct sec_desc_buf secdesc_ctr;
5647                 union spoolss_SetPrinterInfo sinfo;
5648
5649                 ZERO_STRUCT(info_ctr);
5650                 ZERO_STRUCT(devmode_ctr);
5651                 ZERO_STRUCT(secdesc_ctr);
5652
5653
5654                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5655                 sinfo.info2->comment    = "torture_comment";
5656
5657                 info_ctr.level = 2;
5658                 info_ctr.info = sinfo;
5659
5660                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5661                         "failed to call SetPrinter");
5662
5663                 sinfo.info2->comment    = comment;
5664
5665                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5666                         "failed to call SetPrinter");
5667
5668         }
5669
5670         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5671                 "failed to query for ChangeID");
5672         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5673                 "failed to query for ChangeID");
5674         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5675                 "failed to query for ChangeID");
5676
5677         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5678                 "change_ids should all be equal");
5679         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5680                 "change_ids should all be equal");
5681
5682         torture_assert(tctx, (change_id < change_id2),
5683                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5684                 change_id2, change_id));
5685         torture_assert(tctx, (change_id_ex < change_id_ex2),
5686                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5687                 change_id_ex2, change_id_ex));
5688         torture_assert(tctx, (change_id_info < change_id_info2),
5689                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5690                 change_id_info2, change_id_info));
5691
5692         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5693
5694         return true;
5695 }
5696
5697 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5698                                        struct dcerpc_pipe *p,
5699                                        struct policy_handle *handle)
5700 {
5701         NTSTATUS status;
5702         struct dcerpc_binding *b;
5703         struct dcerpc_pipe *p2;
5704         struct spoolss_ClosePrinter cp;
5705
5706         /* only makes sense on SMB */
5707         if (p->conn->transport.transport != NCACN_NP) {
5708                 return true;
5709         }
5710
5711         torture_comment(tctx, "Testing close on secondary pipe\n");
5712
5713         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5714         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5715
5716         status = dcerpc_secondary_connection(p, &p2, b);
5717         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5718
5719         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5720         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5721
5722         cp.in.handle = handle;
5723         cp.out.handle = handle;
5724
5725         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5726         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5727                         "ERROR: Allowed close on secondary connection");
5728
5729         talloc_free(p2);
5730
5731         return true;
5732 }
5733
5734 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5735                                      struct dcerpc_binding_handle *b, const char *name)
5736 {
5737         NTSTATUS status;
5738         struct spoolss_OpenPrinter op;
5739         struct spoolss_OpenPrinterEx opEx;
5740         struct policy_handle handle;
5741         bool ret = true;
5742
5743         op.in.printername       = name;
5744         op.in.datatype          = NULL;
5745         op.in.devmode_ctr.devmode= NULL;
5746         op.in.access_mask       = 0;
5747         op.out.handle           = &handle;
5748
5749         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5750
5751         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5752         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5753         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5754                 "unexpected result");
5755
5756         if (W_ERROR_IS_OK(op.out.result)) {
5757                 ret &=test_ClosePrinter(tctx, b, &handle);
5758         }
5759
5760         opEx.in.printername             = name;
5761         opEx.in.datatype                = NULL;
5762         opEx.in.devmode_ctr.devmode     = NULL;
5763         opEx.in.access_mask             = 0;
5764         opEx.in.level                   = 1;
5765         opEx.in.userlevel.level1        = NULL;
5766         opEx.out.handle                 = &handle;
5767
5768         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5769
5770         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5771         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5772         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5773                 "unexpected result");
5774
5775         if (W_ERROR_IS_OK(opEx.out.result)) {
5776                 ret &=test_ClosePrinter(tctx, b, &handle);
5777         }
5778
5779         return ret;
5780 }
5781
5782 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5783                                           void *private_data)
5784 {
5785         struct test_spoolss_context *ctx =
5786                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5787
5788         const char *badnames[] = {
5789                 "__INVALID_PRINTER__",
5790                 "\\\\__INVALID_HOST__",
5791                 "",
5792                 "\\\\\\",
5793                 "\\\\\\__INVALID_PRINTER__"
5794         };
5795         const char *badname;
5796         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5797         const char *server_name = dcerpc_server_name(p);
5798         struct dcerpc_binding_handle *b = p->binding_handle;
5799         int i;
5800
5801         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5802                 torture_assert(tctx,
5803                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5804                         "");
5805         }
5806
5807         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5808         torture_assert(tctx,
5809                 test_OpenPrinter_badname(tctx, b, badname),
5810                 "");
5811
5812         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5813         torture_assert(tctx,
5814                 test_OpenPrinter_badname(tctx, b, badname),
5815                 "");
5816
5817         return true;
5818 }
5819
5820 static bool test_OpenPrinter(struct torture_context *tctx,
5821                              struct dcerpc_pipe *p,
5822                              const char *name,
5823                              const char *environment,
5824                              bool open_only)
5825 {
5826         NTSTATUS status;
5827         struct spoolss_OpenPrinter r;
5828         struct policy_handle handle;
5829         bool ret = true;
5830         struct dcerpc_binding_handle *b = p->binding_handle;
5831
5832         r.in.printername        = name;
5833         r.in.datatype           = NULL;
5834         r.in.devmode_ctr.devmode= NULL;
5835         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5836         r.out.handle            = &handle;
5837
5838         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5839
5840         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5841
5842         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5843
5844         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5845
5846         if (open_only) {
5847                 goto close_printer;
5848         }
5849
5850         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5851                 ret = false;
5852         }
5853
5854         if (!torture_setting_bool(tctx, "samba3", false)) {
5855                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5856                         ret = false;
5857                 }
5858         }
5859
5860  close_printer:
5861         if (!test_ClosePrinter(tctx, b, &handle)) {
5862                 ret = false;
5863         }
5864
5865         return ret;
5866 }
5867
5868 static bool test_OpenPrinterEx(struct torture_context *tctx,
5869                                struct dcerpc_binding_handle *b,
5870                                const char *printername,
5871                                const char *datatype,
5872                                struct spoolss_DeviceMode *devmode,
5873                                uint32_t access_mask,
5874                                uint32_t level,
5875                                union spoolss_UserLevel *userlevel,
5876                                struct policy_handle *handle,
5877                                WERROR expected_result)
5878 {
5879         struct spoolss_OpenPrinterEx r;
5880
5881         r.in.printername        = printername;
5882         r.in.datatype           = datatype;
5883         r.in.devmode_ctr.devmode= devmode;
5884         r.in.access_mask        = access_mask;
5885         r.in.level              = level;
5886         r.in.userlevel          = *userlevel;
5887         r.out.handle            = handle;
5888
5889         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5890
5891         torture_assert_ntstatus_ok(tctx,
5892                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5893                 "OpenPrinterEx failed");
5894
5895         torture_assert_werr_equal(tctx, r.out.result, expected_result,
5896                 "OpenPrinterEx failed");
5897
5898         return true;
5899 }
5900
5901 static bool call_OpenPrinterEx(struct torture_context *tctx,
5902                                struct dcerpc_pipe *p,
5903                                const char *name,
5904                                struct spoolss_DeviceMode *devmode,
5905                                struct policy_handle *handle)
5906 {
5907         union spoolss_UserLevel userlevel;
5908         struct spoolss_UserLevel1 userlevel1;
5909         struct dcerpc_binding_handle *b = p->binding_handle;
5910
5911         userlevel1.size = 1234;
5912         userlevel1.client = "hello";
5913         userlevel1.user = "spottyfoot!";
5914         userlevel1.build = 1;
5915         userlevel1.major = 2;
5916         userlevel1.minor = 3;
5917         userlevel1.processor = 4;
5918
5919         userlevel.level1 = &userlevel1;
5920
5921         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5922                                   SEC_FLAG_MAXIMUM_ALLOWED,
5923                                   1,
5924                                   &userlevel,
5925                                   handle,
5926                                   WERR_OK);
5927 }
5928
5929 static bool test_printer_rename(struct torture_context *tctx,
5930                                 void *private_data)
5931 {
5932         struct torture_printer_context *t =
5933                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5934         struct dcerpc_pipe *p = t->spoolss_pipe;
5935
5936         bool ret = true;
5937         union spoolss_PrinterInfo info;
5938         union spoolss_SetPrinterInfo sinfo;
5939         struct spoolss_SetPrinterInfoCtr info_ctr;
5940         struct spoolss_DevmodeContainer devmode_ctr;
5941         struct sec_desc_buf secdesc_ctr;
5942         const char *printer_name;
5943         const char *printer_name_orig;
5944         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5945         struct policy_handle new_handle;
5946         const char *q;
5947         struct dcerpc_binding_handle *b = p->binding_handle;
5948
5949         ZERO_STRUCT(devmode_ctr);
5950         ZERO_STRUCT(secdesc_ctr);
5951
5952         torture_comment(tctx, "Testing Printer rename operations\n");
5953
5954         torture_assert(tctx,
5955                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5956                 "failed to call GetPrinter level 2");
5957
5958         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5959
5960         q = strrchr(info.info2.printername, '\\');
5961         if (q) {
5962                 torture_warning(tctx,
5963                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5964         }
5965
5966         torture_assert(tctx,
5967                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5968
5969         sinfo.info2->printername = printer_name_new;
5970
5971         info_ctr.level = 2;
5972         info_ctr.info = sinfo;
5973
5974         torture_assert(tctx,
5975                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5976                 "failed to call SetPrinter level 2");
5977
5978         torture_assert(tctx,
5979                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5980                 "failed to call GetPrinter level 2");
5981
5982         printer_name = talloc_strdup(tctx, info.info2.printername);
5983
5984         q = strrchr(info.info2.printername, '\\');
5985         if (q) {
5986                 torture_warning(tctx,
5987                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5988                 q++;
5989                 printer_name = q;
5990         }
5991
5992         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5993                 "new printer name was not set");
5994
5995         /* samba currently cannot fully rename printers */
5996         if (!torture_setting_bool(tctx, "samba3", false)) {
5997                 torture_assert(tctx,
5998                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5999                         "still can open printer with oldname after rename");
6000         } else {
6001                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6002         }
6003
6004         torture_assert(tctx,
6005                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6006                 "failed to open printer with new name");
6007
6008         torture_assert(tctx,
6009                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6010                 "failed to call GetPrinter level 2");
6011
6012         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6013                 "new printer name was not set");
6014
6015         torture_assert(tctx,
6016                 test_ClosePrinter(tctx, b, &new_handle),
6017                 "failed to close printer");
6018
6019         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6020
6021         return ret;
6022 }
6023
6024 static bool test_openprinter(struct torture_context *tctx,
6025                              struct dcerpc_binding_handle *b,
6026                              const char *real_printername)
6027 {
6028         union spoolss_UserLevel userlevel;
6029         struct policy_handle handle;
6030         struct spoolss_UserLevel1 userlevel1;
6031         const char *printername = NULL;
6032         int i;
6033
6034         struct {
6035                 const char *suffix;
6036                 WERROR expected_result;
6037         } tests[] = {
6038                 {
6039                         .suffix                 = "rubbish",
6040                         .expected_result        = WERR_INVALID_PRINTER_NAME
6041                 },{
6042                         .suffix                 = ", LocalOnl",
6043                         .expected_result        = WERR_INVALID_PRINTER_NAME
6044                 },{
6045                         .suffix                 = ", localOnly",
6046                         .expected_result        = WERR_INVALID_PRINTER_NAME
6047                 },{
6048                         .suffix                 = ", localonl",
6049                         .expected_result        = WERR_INVALID_PRINTER_NAME
6050                 },{
6051                         .suffix                 = ",LocalOnl",
6052                         .expected_result        = WERR_INVALID_PRINTER_NAME
6053                 },{
6054                         .suffix                 = ",localOnl2",
6055                         .expected_result        = WERR_INVALID_PRINTER_NAME
6056                 },{
6057                         .suffix                 = ", DrvConver2t",
6058                         .expected_result        = WERR_INVALID_PRINTER_NAME
6059                 },{
6060                         .suffix                 = ", drvconvert",
6061                         .expected_result        = WERR_INVALID_PRINTER_NAME
6062                 },{
6063                         .suffix                 = ",drvconvert",
6064                         .expected_result        = WERR_INVALID_PRINTER_NAME
6065                 },{
6066                         .suffix                 = ", DrvConvert",
6067                         .expected_result        = WERR_OK
6068                 },{
6069                         .suffix                 = " , DrvConvert",
6070                         .expected_result        = WERR_INVALID_PRINTER_NAME
6071                 },{
6072                         .suffix                 = ",DrvConvert",
6073                         .expected_result        = WERR_OK
6074                 },{
6075                         .suffix                 = ", DrvConvertsadfasdf",
6076                         .expected_result        = WERR_OK
6077                 },{
6078                         .suffix                 = ",DrvConvertasdfasd",
6079                         .expected_result        = WERR_OK
6080                 },{
6081                         .suffix                 = ", LocalOnly",
6082                         .expected_result        = WERR_OK
6083                 },{
6084                         .suffix                 = " , LocalOnly",
6085                         .expected_result        = WERR_INVALID_PRINTER_NAME
6086                 },{
6087                         .suffix                 = ",LocalOnly",
6088                         .expected_result        = WERR_OK
6089                 },{
6090                         .suffix                 = ", LocalOnlysagi4gjfkd",
6091                         .expected_result        = WERR_OK
6092                 },{
6093                         .suffix                 = ",LocalOnlysagi4gjfkd",
6094                         .expected_result        = WERR_OK
6095                 }
6096         };
6097
6098         userlevel1.size = 1234;
6099         userlevel1.client = "hello";
6100         userlevel1.user = "spottyfoot!";
6101         userlevel1.build = 1;
6102         userlevel1.major = 2;
6103         userlevel1.minor = 3;
6104         userlevel1.processor = 4;
6105
6106         userlevel.level1 = &userlevel1;
6107
6108         torture_comment(tctx, "Testing openprinterex printername pattern\n");
6109
6110         torture_assert(tctx,
6111                 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6112                                    &userlevel, &handle,
6113                                    WERR_OK),
6114                 "OpenPrinterEx failed");
6115         test_ClosePrinter(tctx, b, &handle);
6116
6117         for (i=0; i < ARRAY_SIZE(tests); i++) {
6118
6119                 printername = talloc_asprintf(tctx, "%s%s",
6120                                               real_printername,
6121                                               tests[i].suffix);
6122
6123                 torture_assert(tctx,
6124                         test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6125                                            &userlevel, &handle,
6126                                            tests[i].expected_result),
6127                         "OpenPrinterEx failed");
6128                 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6129                         test_ClosePrinter(tctx, b, &handle);
6130                 }
6131         }
6132
6133         return true;
6134 }
6135
6136
6137 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6138                                                 struct dcerpc_pipe *p,
6139                                                 const char *name,
6140                                                 const char *environment)
6141 {
6142         struct policy_handle handle;
6143         bool ret = true;
6144         struct dcerpc_binding_handle *b = p->binding_handle;
6145
6146         if (!test_openprinter(tctx, b, name)) {
6147                 return false;
6148         }
6149
6150         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6151                 return false;
6152         }
6153
6154         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6155                 ret = false;
6156         }
6157
6158         if (!test_GetPrinter(tctx, b, &handle, environment)) {
6159                 ret = false;
6160         }
6161
6162         if (!test_EnumForms_all(tctx, b, &handle, false)) {
6163                 ret = false;
6164         }
6165
6166         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6167                 ret = false;
6168         }
6169
6170         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6171                 ret = false;
6172         }
6173
6174         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6175                 ret = false;
6176         }
6177
6178         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6179                 ret = false;
6180         }
6181
6182         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6183                 ret = false;
6184         }
6185
6186         if (!test_printer_all_keys(tctx, b, &handle)) {
6187                 ret = false;
6188         }
6189
6190         if (!test_PausePrinter(tctx, b, &handle)) {
6191                 ret = false;
6192         }
6193
6194         if (!test_DoPrintTest(tctx, b, &handle)) {
6195                 ret = false;
6196         }
6197
6198         if (!test_ResumePrinter(tctx, b, &handle)) {
6199                 ret = false;
6200         }
6201
6202         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6203                 ret = false;
6204         }
6205
6206         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6207                 ret = false;
6208         }
6209
6210         if (!torture_setting_bool(tctx, "samba3", false)) {
6211                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6212                         ret = false;
6213                 }
6214         }
6215
6216         if (!test_ClosePrinter(tctx, b, &handle)) {
6217                 ret = false;
6218         }
6219
6220         return ret;
6221 }
6222
6223 static bool test_EnumPrinters_old(struct torture_context *tctx,
6224                                   void *private_data)
6225 {
6226         struct test_spoolss_context *ctx =
6227                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6228         struct spoolss_EnumPrinters r;
6229         NTSTATUS status;
6230         uint16_t levels[] = {1, 2, 4, 5};
6231         int i;
6232         bool ret = true;
6233         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6234         struct dcerpc_binding_handle *b = p->binding_handle;
6235
6236         for (i=0;i<ARRAY_SIZE(levels);i++) {
6237                 union spoolss_PrinterInfo *info;
6238                 int j;
6239                 uint32_t needed;
6240                 uint32_t count;
6241
6242                 r.in.flags      = PRINTER_ENUM_LOCAL;
6243                 r.in.server     = "";
6244                 r.in.level      = levels[i];
6245                 r.in.buffer     = NULL;
6246                 r.in.offered    = 0;
6247                 r.out.needed    = &needed;
6248                 r.out.count     = &count;
6249                 r.out.info      = &info;
6250
6251                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6252
6253                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6254                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6255
6256                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6257                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6258                         r.in.buffer = &blob;
6259                         r.in.offered = needed;
6260                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6261                 }
6262
6263                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6264
6265                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6266
6267                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6268
6269                 if (!info) {
6270                         torture_comment(tctx, "No printers returned\n");
6271                         return true;
6272                 }
6273
6274                 for (j=0;j<count;j++) {
6275                         if (r.in.level == 1) {
6276                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
6277                                 char *slash, *name, *full_name;
6278                                 name = unc;
6279                                 if (unc[0] == '\\' && unc[1] == '\\') {
6280                                         unc +=2;
6281                                 }
6282                                 slash = strchr(unc, '\\');
6283                                 if (slash) {
6284                                         slash++;
6285                                         name = slash;
6286                                 }
6287                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6288                                                             dcerpc_server_name(p), name);
6289                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6290                                         ret = false;
6291                                 }
6292                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6293                                         ret = false;
6294                                 }
6295                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6296                                         ret = false;
6297                                 }
6298                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6299                                         ret = false;
6300                                 }
6301                         }
6302                 }
6303         }
6304
6305         return ret;
6306 }
6307
6308 static bool test_EnumPrinters_level(struct torture_context *tctx,
6309                                     struct dcerpc_binding_handle *b,
6310                                     uint32_t flags,
6311                                     const char *servername,
6312                                     uint32_t level,
6313                                     uint32_t *count_p,
6314                                     union spoolss_PrinterInfo **info_p)
6315 {
6316         struct spoolss_EnumPrinters r;
6317         union spoolss_PrinterInfo *info;
6318         uint32_t needed;
6319         uint32_t count;
6320
6321         r.in.flags      = flags;
6322         r.in.server     = servername;
6323         r.in.level      = level;
6324         r.in.buffer     = NULL;
6325         r.in.offered    = 0;
6326         r.out.needed    = &needed;
6327         r.out.count     = &count;
6328         r.out.info      = &info;
6329
6330         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6331                 r.in.server, r.in.level);
6332
6333         torture_assert_ntstatus_ok(tctx,
6334                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6335                 "EnumPrinters failed");
6336         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6337                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6338                 r.in.buffer = &blob;
6339                 r.in.offered = needed;
6340                 torture_assert_ntstatus_ok(tctx,
6341                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6342                         "EnumPrinters failed");
6343         }
6344
6345         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6346
6347         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6348
6349         if (count_p) {
6350                 *count_p = count;
6351         }
6352         if (info_p) {
6353                 *info_p = info;
6354         }
6355
6356         return true;
6357 }
6358
6359 static const char *get_short_printername(struct torture_context *tctx,
6360                                          const char *name)
6361 {
6362         const char *short_name;
6363
6364         if (name[0] == '\\' && name[1] == '\\') {
6365                 name += 2;
6366                 short_name = strchr(name, '\\');
6367                 if (short_name) {
6368                         return talloc_strdup(tctx, short_name+1);
6369                 }
6370         }
6371
6372         return name;
6373 }
6374
6375 static const char *get_full_printername(struct torture_context *tctx,
6376                                         const char *name)
6377 {
6378         const char *full_name = talloc_strdup(tctx, name);
6379         char *p;
6380
6381         if (name && name[0] == '\\' && name[1] == '\\') {
6382                 name += 2;
6383                 p = strchr(name, '\\');
6384                 if (p) {
6385                         return full_name;
6386                 }
6387         }
6388
6389         return NULL;
6390 }
6391
6392 static bool test_OnePrinter_servername(struct torture_context *tctx,
6393                                        struct dcerpc_pipe *p,
6394                                        struct dcerpc_binding_handle *b,
6395                                        const char *servername,
6396                                        const char *printername)
6397 {
6398         union spoolss_PrinterInfo info;
6399         const char *short_name = get_short_printername(tctx, printername);
6400         const char *full_name = get_full_printername(tctx, printername);
6401
6402         if (short_name) {
6403                 struct policy_handle handle;
6404                 torture_assert(tctx,
6405                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6406                         "failed to open printer");
6407
6408                 torture_assert(tctx,
6409                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6410                         "failed to get printer info");
6411
6412                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6413                         "unexpected servername");
6414                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6415                         "unexpected printername");
6416
6417                 if (info.info2.devmode) {
6418                         const char *expected_devicename;
6419                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6420                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6421                                 "unexpected devicemode devicename");
6422                 }
6423
6424                 torture_assert(tctx,
6425                         test_ClosePrinter(tctx, b, &handle),
6426                         "failed to close printer");
6427         }
6428
6429         if (full_name) {
6430                 struct policy_handle handle;
6431
6432                 torture_assert(tctx,
6433                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6434                         "failed to open printer");
6435
6436                 torture_assert(tctx,
6437                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
6438                         "failed to get printer info");
6439
6440                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6441                         "unexpected servername");
6442                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6443                         "unexpected printername");
6444
6445                 if (info.info2.devmode) {
6446                         const char *expected_devicename;
6447                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6448                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6449                                 "unexpected devicemode devicename");
6450                 }
6451
6452                 torture_assert(tctx,
6453                         test_ClosePrinter(tctx, b, &handle),
6454                         "failed to close printer");
6455         }
6456
6457         return true;
6458 }
6459
6460 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6461                                          void *private_data)
6462 {
6463         struct test_spoolss_context *ctx =
6464                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6465         int i;
6466         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6467         struct dcerpc_binding_handle *b = p->binding_handle;
6468         uint32_t count;
6469         union spoolss_PrinterInfo *info;
6470         const char *servername;
6471         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6472
6473         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6474
6475         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6476
6477         torture_assert(tctx,
6478                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6479                 "failed to enumerate printers");
6480
6481         for (i=0; i < count; i++) {
6482
6483                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6484                         "unexpected servername");
6485
6486                 torture_assert(tctx,
6487                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6488                         "failed to check printer");
6489         }
6490
6491         servername = "";
6492
6493         torture_assert(tctx,
6494                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6495                 "failed to enumerate printers");
6496
6497         for (i=0; i < count; i++) {
6498
6499                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6500                         "unexpected servername");
6501
6502                 torture_assert(tctx,
6503                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6504                         "failed to check printer");
6505         }
6506
6507
6508         return true;
6509 }
6510
6511
6512 static bool test_GetPrinterDriver(struct torture_context *tctx,
6513                                   struct dcerpc_binding_handle *b,
6514                                   struct policy_handle *handle,
6515                                   const char *driver_name)
6516 {
6517         struct spoolss_GetPrinterDriver r;
6518         uint32_t needed;
6519
6520         r.in.handle = handle;
6521         r.in.architecture = "W32X86";
6522         r.in.level = 1;
6523         r.in.buffer = NULL;
6524         r.in.offered = 0;
6525         r.out.needed = &needed;
6526
6527         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6528
6529         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6530                 "failed to call GetPrinterDriver");
6531         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6532                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6533                 r.in.buffer = &blob;
6534                 r.in.offered = needed;
6535                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6536                         "failed to call GetPrinterDriver");
6537         }
6538
6539         torture_assert_werr_ok(tctx, r.out.result,
6540                 "failed to call GetPrinterDriver");
6541
6542         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6543
6544         return true;
6545 }
6546
6547 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6548                                          struct dcerpc_binding_handle *b,
6549                                          struct policy_handle *handle,
6550                                          const char *driver_name,
6551                                          const char *architecture,
6552                                          uint32_t level,
6553                                          uint32_t client_major_version,
6554                                          uint32_t client_minor_version,
6555                                          union spoolss_DriverInfo *info_p,
6556                                          WERROR *result_p)
6557
6558 {
6559         struct spoolss_GetPrinterDriver2 r;
6560         uint32_t needed;
6561         uint32_t server_major_version;
6562         uint32_t server_minor_version;
6563
6564         r.in.handle = handle;
6565         r.in.architecture = architecture;
6566         r.in.client_major_version = client_major_version;
6567         r.in.client_minor_version = client_minor_version;
6568         r.in.buffer = NULL;
6569         r.in.offered = 0;
6570         r.in.level = level;
6571         r.out.needed = &needed;
6572         r.out.server_major_version = &server_major_version;
6573         r.out.server_minor_version = &server_minor_version;
6574
6575         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6576                 driver_name, r.in.level);
6577
6578         torture_assert_ntstatus_ok(tctx,
6579                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6580                 "failed to call GetPrinterDriver2");
6581         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6582                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6583                 r.in.buffer = &blob;
6584                 r.in.offered = needed;
6585                 torture_assert_ntstatus_ok(tctx,
6586                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6587                         "failed to call GetPrinterDriver2");
6588         }
6589
6590         if (result_p) {
6591                 *result_p = r.out.result;
6592         }
6593
6594         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6595                 switch (r.in.level) {
6596                 case 101:
6597                 case 8:
6598                         torture_comment(tctx,
6599                                 "level %d not implemented, not considering as an error\n",
6600                                 r.in.level);
6601                         return true;
6602                 default:
6603                         break;
6604                 }
6605         }
6606
6607         torture_assert_werr_ok(tctx, r.out.result,
6608                 "failed to call GetPrinterDriver2");
6609
6610         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6611
6612         if (info_p) {
6613                 *info_p = *r.out.info;
6614         }
6615
6616         return true;
6617 }
6618
6619 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6620                                    struct dcerpc_binding_handle *b,
6621                                    struct policy_handle *handle,
6622                                    const char *driver_name,
6623                                    const char *architecture)
6624 {
6625         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6626         int i;
6627
6628
6629         for (i=0;i<ARRAY_SIZE(levels);i++) {
6630
6631                 torture_assert(tctx,
6632                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6633                         "");
6634         }
6635
6636         return true;
6637 }
6638
6639 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6640                                         void *private_data)
6641 {
6642         struct test_spoolss_context *ctx =
6643                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6644         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6645         int i;
6646         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6647         struct dcerpc_binding_handle *b = p->binding_handle;
6648         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6649
6650         for (i=0;i<ARRAY_SIZE(levels);i++) {
6651
6652                 uint32_t count;
6653                 union spoolss_DriverInfo *info;
6654
6655                 torture_assert(tctx,
6656                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6657                         "failed to enumerate drivers");
6658
6659                 if (!info) {
6660                         torture_comment(tctx, "No printer drivers returned\n");
6661                         break;
6662                 }
6663         }
6664
6665         return true;
6666 }
6667
6668 static bool test_DeletePrinter(struct torture_context *tctx,
6669                                struct dcerpc_binding_handle *b,
6670                                struct policy_handle *handle)
6671 {
6672         struct spoolss_DeletePrinter r;
6673
6674         torture_comment(tctx, "Testing DeletePrinter\n");
6675
6676         r.in.handle = handle;
6677
6678         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6679                 "failed to delete printer");
6680         torture_assert_werr_ok(tctx, r.out.result,
6681                 "failed to delete printer");
6682
6683         return true;
6684 }
6685
6686 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6687                                        struct dcerpc_binding_handle *b,
6688                                        uint32_t flags,
6689                                        uint32_t level,
6690                                        const char *name,
6691                                        bool *found)
6692 {
6693         struct spoolss_EnumPrinters e;
6694         uint32_t count;
6695         union spoolss_PrinterInfo *info;
6696         uint32_t needed;
6697         int i;
6698
6699         *found = false;
6700
6701         e.in.flags = flags;
6702         e.in.server = NULL;
6703         e.in.level = level;
6704         e.in.buffer = NULL;
6705         e.in.offered = 0;
6706         e.out.count = &count;
6707         e.out.info = &info;
6708         e.out.needed = &needed;
6709
6710         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6711                 "failed to enum printers");
6712
6713         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6714                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6715                 e.in.buffer = &blob;
6716                 e.in.offered = needed;
6717
6718                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6719                         "failed to enum printers");
6720         }
6721
6722         torture_assert_werr_ok(tctx, e.out.result,
6723                 "failed to enum printers");
6724
6725         for (i=0; i < count; i++) {
6726
6727                 const char *current = NULL;
6728                 const char *q;
6729
6730                 switch (level) {
6731                 case 1:
6732                         current = info[i].info1.name;
6733                         break;
6734                 }
6735
6736                 if (strequal(current, name)) {
6737                         *found = true;
6738                         break;
6739                 }
6740
6741                 q = strrchr(current, '\\');
6742                 if (q) {
6743                         if (!e.in.server) {
6744                                 torture_warning(tctx,
6745                                         "server returns printername %s incl. servername although we did not set servername", current);
6746                         }
6747                         q++;
6748                         if (strequal(q, name)) {
6749                                 *found = true;
6750                                 break;
6751                         }
6752                 }
6753         }
6754
6755         return true;
6756 }
6757
6758 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6759                                       struct dcerpc_pipe *p,
6760                                       const char *printername,
6761                                       bool ex)
6762 {
6763         WERROR result;
6764         struct spoolss_AddPrinter r;
6765         struct spoolss_AddPrinterEx rex;
6766         struct spoolss_SetPrinterInfoCtr info_ctr;
6767         struct spoolss_SetPrinterInfo1 info1;
6768         struct spoolss_DevmodeContainer devmode_ctr;
6769         struct sec_desc_buf secdesc_ctr;
6770         struct spoolss_UserLevelCtr userlevel_ctr;
6771         struct policy_handle handle;
6772         bool found = false;
6773         struct dcerpc_binding_handle *b = p->binding_handle;
6774
6775         ZERO_STRUCT(devmode_ctr);
6776         ZERO_STRUCT(secdesc_ctr);
6777         ZERO_STRUCT(userlevel_ctr);
6778         ZERO_STRUCT(info1);
6779
6780         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6781                         ex ? "Ex":"", printername);
6782
6783         /* try to add printer to wellknown printer list (level 1) */
6784
6785         userlevel_ctr.level = 1;
6786
6787         info_ctr.info.info1 = &info1;
6788         info_ctr.level = 1;
6789
6790         rex.in.server = NULL;
6791         rex.in.info_ctr = &info_ctr;
6792         rex.in.devmode_ctr = &devmode_ctr;
6793         rex.in.secdesc_ctr = &secdesc_ctr;
6794         rex.in.userlevel_ctr = &userlevel_ctr;
6795         rex.out.handle = &handle;
6796
6797         r.in.server = NULL;
6798         r.in.info_ctr = &info_ctr;
6799         r.in.devmode_ctr = &devmode_ctr;
6800         r.in.secdesc_ctr = &secdesc_ctr;
6801         r.out.handle = &handle;
6802
6803         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6804                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6805                 "failed to add printer");
6806         result = ex ? rex.out.result : r.out.result;
6807         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6808                 "unexpected result code");
6809
6810         info1.name = printername;
6811         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6812
6813         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6814                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6815                 "failed to add printer");
6816         result = ex ? rex.out.result : r.out.result;
6817         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6818                 "unexpected result code");
6819
6820         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6821            better do a real check to see the printer is really there */
6822
6823         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6824                                                         PRINTER_ENUM_NETWORK, 1,
6825                                                         printername,
6826                                                         &found),
6827                         "failed to enum printers");
6828
6829         torture_assert(tctx, found, "failed to find newly added printer");
6830
6831         info1.flags = 0;
6832
6833         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6834                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6835                 "failed to add printer");
6836         result = ex ? rex.out.result : r.out.result;
6837         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6838                 "unexpected result code");
6839
6840         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6841            better do a real check to see the printer has really been removed
6842            from the well known printer list */
6843
6844         found = false;
6845
6846         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6847                                                         PRINTER_ENUM_NETWORK, 1,
6848                                                         printername,
6849                                                         &found),
6850                         "failed to enum printers");
6851 #if 0
6852         torture_assert(tctx, !found, "printer still in well known printer list");
6853 #endif
6854         return true;
6855 }
6856
6857 static bool test_AddPrinter_normal(struct torture_context *tctx,
6858                                    struct dcerpc_pipe *p,
6859                                    struct policy_handle *handle_p,
6860                                    const char *printername,
6861                                    const char *drivername,
6862                                    const char *portname,
6863                                    struct spoolss_DeviceMode *devmode,
6864                                    bool ex)
6865 {
6866         WERROR result;
6867         struct spoolss_AddPrinter r;
6868         struct spoolss_AddPrinterEx rex;
6869         struct spoolss_SetPrinterInfoCtr info_ctr;
6870         struct spoolss_SetPrinterInfo2 info2;
6871         struct spoolss_DevmodeContainer devmode_ctr;
6872         struct sec_desc_buf secdesc_ctr;
6873         struct spoolss_UserLevelCtr userlevel_ctr;
6874         struct policy_handle handle;
6875         bool found = false;
6876         bool existing_printer_deleted = false;
6877         struct dcerpc_binding_handle *b = p->binding_handle;
6878
6879         ZERO_STRUCT(devmode_ctr);
6880         ZERO_STRUCT(secdesc_ctr);
6881         ZERO_STRUCT(userlevel_ctr);
6882
6883         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6884                         ex ? "Ex":"", printername);
6885
6886         devmode_ctr.devmode = devmode;
6887
6888         userlevel_ctr.level = 1;
6889
6890         rex.in.server = NULL;
6891         rex.in.info_ctr = &info_ctr;
6892         rex.in.devmode_ctr = &devmode_ctr;
6893         rex.in.secdesc_ctr = &secdesc_ctr;
6894         rex.in.userlevel_ctr = &userlevel_ctr;
6895         rex.out.handle = &handle;
6896
6897         r.in.server = NULL;
6898         r.in.info_ctr = &info_ctr;
6899         r.in.devmode_ctr = &devmode_ctr;
6900         r.in.secdesc_ctr = &secdesc_ctr;
6901         r.out.handle = &handle;
6902
6903  again:
6904
6905         /* try to add printer to printer list (level 2) */
6906
6907         ZERO_STRUCT(info2);
6908
6909         info_ctr.info.info2 = &info2;
6910         info_ctr.level = 2;
6911
6912         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6913                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6914                 "failed to add printer");
6915         result = ex ? rex.out.result : r.out.result;
6916         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6917                 "unexpected result code");
6918
6919         info2.printername = printername;
6920
6921         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6922                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6923                 "failed to add printer");
6924         result = ex ? rex.out.result : r.out.result;
6925
6926         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6927                 struct policy_handle printer_handle;
6928
6929                 if (existing_printer_deleted) {
6930                         torture_fail(tctx, "already deleted printer still existing?");
6931                 }
6932
6933                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6934                         "failed to open printer handle");
6935
6936                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6937                         "failed to delete printer");
6938
6939                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6940                         "failed to close server handle");
6941
6942                 existing_printer_deleted = true;
6943
6944                 goto again;
6945         }
6946
6947         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6948                 "unexpected result code");
6949
6950         info2.portname = portname;
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_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6957                 "unexpected result code");
6958
6959         info2.drivername = drivername;
6960
6961         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6962                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6963                 "failed to add printer");
6964         result = ex ? rex.out.result : r.out.result;
6965
6966         /* w2k8r2 allows to add printer w/o defining printprocessor */
6967
6968         if (!W_ERROR_IS_OK(result)) {
6969                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6970                         "unexpected result code");
6971
6972                 info2.printprocessor = "winprint";
6973
6974                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6975                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6976                         "failed to add printer");
6977                 result = ex ? rex.out.result : r.out.result;
6978                 torture_assert_werr_ok(tctx, result,
6979                         "failed to add printer");
6980         }
6981
6982         *handle_p = handle;
6983
6984         /* we are paranoid, really check if the printer is there now */
6985
6986         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6987                                                         PRINTER_ENUM_LOCAL, 1,
6988                                                         printername,
6989                                                         &found),
6990                         "failed to enum printers");
6991         torture_assert(tctx, found, "failed to find newly added printer");
6992
6993         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6994                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6995                 "failed to add printer");
6996         result = ex ? rex.out.result : r.out.result;
6997         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6998                 "unexpected result code");
6999
7000         return true;
7001 }
7002
7003 static bool test_printer_info(struct torture_context *tctx,
7004                               void *private_data)
7005 {
7006         struct torture_printer_context *t =
7007                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7008         struct dcerpc_pipe *p = t->spoolss_pipe;
7009         struct dcerpc_binding_handle *b = p->binding_handle;
7010
7011         bool ret = true;
7012
7013         if (torture_setting_bool(tctx, "samba3", false)) {
7014                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7015         }
7016
7017         if (!test_PrinterInfo(tctx, b, &t->handle)) {
7018                 ret = false;
7019         }
7020
7021         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7022                 ret = false;
7023         }
7024
7025         return ret;
7026 }
7027
7028 static bool test_EnumPrinterKey(struct torture_context *tctx,
7029                                 struct dcerpc_binding_handle *b,
7030                                 struct policy_handle *handle,
7031                                 const char *key_name,
7032                                 const char ***array)
7033 {
7034         struct spoolss_EnumPrinterKey r;
7035         uint32_t needed = 0;
7036         union spoolss_KeyNames key_buffer;
7037         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7038         uint32_t _ndr_size;
7039         int i;
7040
7041         r.in.handle = handle;
7042         r.in.key_name = key_name;
7043         r.out.key_buffer = &key_buffer;
7044         r.out.needed = &needed;
7045         r.out._ndr_size = &_ndr_size;
7046
7047         for (i=0; i < ARRAY_SIZE(offered); i++) {
7048
7049                 if (offered[i] < 0 && needed) {
7050                         if (needed <= 4) {
7051                                 continue;
7052                         }
7053                         r.in.offered = needed + offered[i];
7054                 } else {
7055                         r.in.offered = offered[i];
7056                 }
7057
7058                 ZERO_STRUCT(key_buffer);
7059
7060                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7061
7062                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7063                         "failed to call EnumPrinterKey");
7064                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7065
7066                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
7067                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7068                                         _ndr_size, r.in.offered/2));
7069
7070                         r.in.offered = needed;
7071                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7072                                 "failed to call EnumPrinterKey");
7073                 }
7074
7075                 if (offered[i] > 0) {
7076                         torture_assert_werr_ok(tctx, r.out.result,
7077                                 "failed to call EnumPrinterKey");
7078                 }
7079
7080                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7081                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7082                                 _ndr_size, r.in.offered/2));
7083
7084                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7085                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7086
7087                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7088                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7089
7090                 if (key_buffer.string_array) {
7091                         uint32_t calc_needed = 0;
7092                         int s;
7093                         for (s=0; key_buffer.string_array[s]; s++) {
7094                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7095                         }
7096                         if (!key_buffer.string_array[0]) {
7097                                 calc_needed += 2;
7098                         }
7099                         calc_needed += 2;
7100
7101                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7102                                 "EnumPrinterKey unexpected size");
7103                 }
7104         }
7105
7106         if (array) {
7107                 *array = key_buffer.string_array;
7108         }
7109
7110         return true;
7111 }
7112
7113 bool test_printer_all_keys(struct torture_context *tctx,
7114                            struct dcerpc_binding_handle *b,
7115                            struct policy_handle *handle)
7116 {
7117         const char **key_array = NULL;
7118         int i;
7119
7120         torture_comment(tctx, "Testing Printer Keys\n");
7121
7122         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7123                 "failed to call test_EnumPrinterKey");
7124
7125         for (i=0; key_array && key_array[i]; i++) {
7126                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7127                         "failed to call test_EnumPrinterKey");
7128         }
7129         for (i=0; key_array && key_array[i]; i++) {
7130                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7131                         "failed to call test_EnumPrinterDataEx");
7132         }
7133
7134         torture_comment(tctx, "Printer Keys test succeeded\n\n");
7135
7136         return true;
7137 }
7138
7139 static bool test_openprinter_wrap(struct torture_context *tctx,
7140                                   void *private_data)
7141 {
7142         struct torture_printer_context *t =
7143                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7144         struct dcerpc_pipe *p = t->spoolss_pipe;
7145         struct dcerpc_binding_handle *b = p->binding_handle;
7146         const char *printername = t->info2.printername;
7147
7148         return test_openprinter(tctx, b, printername);
7149 }
7150
7151 static bool test_csetprinter(struct torture_context *tctx,
7152                              void *private_data)
7153 {
7154         struct torture_printer_context *t =
7155                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7156         struct dcerpc_pipe *p = t->spoolss_pipe;
7157
7158         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7159         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7160         const char *portname = t->info2.portname;
7161
7162         union spoolss_PrinterInfo info;
7163         struct policy_handle new_handle, new_handle2;
7164         struct dcerpc_binding_handle *b = p->binding_handle;
7165
7166         torture_comment(tctx, "Testing c_setprinter\n");
7167
7168         torture_assert(tctx,
7169                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7170                 "failed to get level 0 printer info");
7171         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7172                 info.info0.c_setprinter);
7173
7174         /* check if c_setprinter on 1st handle increases after a printer has
7175          * been added */
7176
7177         torture_assert(tctx,
7178                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7179                 "failed to add new printer");
7180         torture_assert(tctx,
7181                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7182                 "failed to get level 0 printer info");
7183         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7184                 info.info0.c_setprinter);
7185
7186         /* check if c_setprinter on new handle increases after a printer has
7187          * been added */
7188
7189         torture_assert(tctx,
7190                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7191                 "failed to get level 0 printer info");
7192         torture_comment(tctx, "csetprinter on created handle: %d\n",
7193                 info.info0.c_setprinter);
7194
7195         /* open the new printer and check if c_setprinter increases */
7196
7197         torture_assert(tctx,
7198                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7199                 "failed to open created printer");
7200         torture_assert(tctx,
7201                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7202                 "failed to get level 0 printer info");
7203         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7204                 info.info0.c_setprinter);
7205
7206         /* cleanup */
7207
7208         torture_assert(tctx,
7209                 test_ClosePrinter(tctx, b, &new_handle2),
7210                 "failed to close printer");
7211         torture_assert(tctx,
7212                 test_DeletePrinter(tctx, b, &new_handle),
7213                 "failed to delete new printer");
7214
7215         return true;
7216 }
7217
7218 static bool compose_local_driver_directory(struct torture_context *tctx,
7219                                            const char *environment,
7220                                            const char *local_dir,
7221                                            const char **path)
7222 {
7223         char *p;
7224
7225         p = strrchr(local_dir, '/');
7226         if (!p) {
7227                 return NULL;
7228         }
7229         p++;
7230
7231         if (strequal(environment, "Windows x64")) {
7232                 if (!strequal(p, "x64")) {
7233                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7234                 }
7235         } else if (strequal(environment, "Windows NT x86")) {
7236                 if (!strequal(p, "i386")) {
7237                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7238                 }
7239         } else {
7240                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7241         }
7242
7243         return true;
7244 }
7245
7246 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7247                                                      const char *devicename)
7248 {
7249         struct spoolss_DeviceMode *r;
7250
7251         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7252         if (r == NULL) {
7253                 return NULL;
7254         }
7255
7256         r->devicename           = talloc_strdup(r, devicename);
7257         r->specversion          = DMSPEC_NT4_AND_ABOVE;
7258         r->driverversion        = 0x0600;
7259         r->size                 = 0x00dc;
7260         r->__driverextra_length = 0;
7261         r->fields               = DEVMODE_FORMNAME |
7262                                   DEVMODE_TTOPTION |
7263                                   DEVMODE_PRINTQUALITY |
7264                                   DEVMODE_DEFAULTSOURCE |
7265                                   DEVMODE_COPIES |
7266                                   DEVMODE_SCALE |
7267                                   DEVMODE_PAPERSIZE |
7268                                   DEVMODE_ORIENTATION;
7269         r->orientation          = DMORIENT_PORTRAIT;
7270         r->papersize            = DMPAPER_LETTER;
7271         r->paperlength          = 0;
7272         r->paperwidth           = 0;
7273         r->scale                = 100;
7274         r->copies               = 55;
7275         r->defaultsource        = DMBIN_FORMSOURCE;
7276         r->printquality         = DMRES_HIGH;
7277         r->color                = DMRES_MONOCHROME;
7278         r->duplex               = DMDUP_SIMPLEX;
7279         r->yresolution          = 0;
7280         r->ttoption             = DMTT_SUBDEV;
7281         r->collate              = DMCOLLATE_FALSE;
7282         r->formname             = talloc_strdup(r, "Letter");
7283
7284         return r;
7285 }
7286
7287 static bool test_architecture_buffer(struct torture_context *tctx,
7288                                      void *private_data)
7289 {
7290         struct test_spoolss_context *ctx =
7291                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7292
7293         struct spoolss_OpenPrinterEx r;
7294         struct spoolss_UserLevel1 u1;
7295         struct policy_handle handle;
7296         uint32_t architectures[] = {
7297                 PROCESSOR_ARCHITECTURE_INTEL,
7298                 PROCESSOR_ARCHITECTURE_IA64,
7299                 PROCESSOR_ARCHITECTURE_AMD64
7300         };
7301         uint32_t needed[3];
7302         int i;
7303         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7304         struct dcerpc_binding_handle *b = p->binding_handle;
7305
7306         for (i=0; i < ARRAY_SIZE(architectures); i++) {
7307
7308                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7309
7310                 u1.size = 0;
7311                 u1.client = NULL;
7312                 u1.user = NULL;
7313                 u1.build = 0;
7314                 u1.major = 3;
7315                 u1.minor = 0;
7316                 u1.processor = architectures[i];
7317
7318                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7319                 r.in.datatype           = NULL;
7320                 r.in.devmode_ctr.devmode= NULL;
7321                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
7322                 r.in.level               = 1;
7323                 r.in.userlevel.level1   = &u1;
7324                 r.out.handle            = &handle;
7325
7326                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7327                 torture_assert_werr_ok(tctx, r.out.result, "");
7328
7329                 {
7330                         struct spoolss_EnumPrinters e;
7331                         uint32_t count;
7332                         union spoolss_PrinterInfo *info;
7333
7334                         e.in.flags = PRINTER_ENUM_LOCAL;
7335                         e.in.server = NULL;
7336                         e.in.level = 2;
7337                         e.in.buffer = NULL;
7338                         e.in.offered = 0;
7339                         e.out.count = &count;
7340                         e.out.info = &info;
7341                         e.out.needed = &needed[i];
7342
7343                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7344 #if 0
7345                         torture_comment(tctx, "needed was %d\n", needed[i]);
7346 #endif
7347                 }
7348
7349                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7350         }
7351
7352         for (i=1; i < ARRAY_SIZE(architectures); i++) {
7353                 if (needed[i-1] != needed[i]) {
7354                         torture_fail(tctx,
7355                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7356                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7357                 }
7358         }
7359
7360         return true;
7361 }
7362
7363 static bool test_PrintServer_Forms_Winreg(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_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7372 }
7373
7374 static bool test_PrintServer_Forms(struct torture_context *tctx,
7375                                    void *private_data)
7376 {
7377         struct test_spoolss_context *ctx =
7378                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7379         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7380         struct dcerpc_binding_handle *b = p->binding_handle;
7381
7382         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7383 }
7384
7385 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7386                                        void *private_data)
7387 {
7388         struct test_spoolss_context *ctx =
7389                 talloc_get_type_abort(private_data, struct test_spoolss_context);
7390         struct dcerpc_pipe *p = ctx->spoolss_pipe;
7391         struct dcerpc_binding_handle *b = p->binding_handle;
7392
7393         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7394 }
7395
7396 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7397 {
7398         NTSTATUS status;
7399
7400         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7401
7402         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7403
7404         torture_assert(tctx,
7405                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7406                 "failed to open printserver");
7407         torture_assert(tctx,
7408                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7409                 "failed to get environment");
7410
7411         return true;
7412 }
7413
7414 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7415 {
7416         struct test_spoolss_context *t;
7417
7418         *data = t = talloc_zero(tctx, struct test_spoolss_context);
7419
7420         return torture_rpc_spoolss_setup_common(tctx, t);
7421 }
7422
7423 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7424 {
7425         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7426
7427         return true;
7428 }
7429
7430 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7431 {
7432         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7433         bool ret;
7434
7435         ret = torture_rpc_spoolss_teardown_common(tctx, t);
7436         talloc_free(t);
7437
7438         return ret;
7439 }
7440
7441 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7442 {
7443         struct dcerpc_pipe *p;
7444         struct dcerpc_binding_handle *b;
7445         const char *server_name_slash;
7446         const char *driver_name;
7447         const char *printer_name;
7448         const char *port_name;
7449
7450         torture_assert_ntstatus_ok(tctx,
7451                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7452                 "Error connecting to server");
7453
7454         p = t->spoolss_pipe;
7455         b = p->binding_handle;
7456         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7457
7458         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
7459         t->driver.info8.driver_name             = TORTURE_DRIVER;
7460         t->driver.info8.driver_path             = "pscript5.dll";
7461         t->driver.info8.data_file               = "cups6.ppd";
7462         t->driver.info8.config_file             = "ps5ui.dll";
7463         t->driver.info8.help_file               = "pscript.hlp";
7464         t->driver.info8.default_datatype        = "RAW";
7465         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
7466         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7467         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7468         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7469         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7470         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7471         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7472         t->driver.info8.dependent_files->string[5] = "cups6.ini";
7473         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7474         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7475
7476         t->driver.local.driver_directory= "/usr/share/cups/drivers";
7477
7478         t->info2.drivername             = "Microsoft XPS Document Writer";
7479         t->info2.portname               = "LPT1:";
7480
7481         printer_name = t->info2.printername;
7482         port_name = t->info2.portname;
7483
7484         torture_assert(tctx,
7485                 fillup_printserver_info(tctx, p, &t->driver),
7486                 "failed to fillup printserver info");
7487
7488         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7489
7490         torture_assert(tctx,
7491                 compose_local_driver_directory(tctx, t->driver.remote.environment,
7492                                                t->driver.local.driver_directory,
7493                                                &t->driver.local.driver_directory),
7494                 "failed to compose local driver directory");
7495
7496         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7497                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7498                         t->info2.drivername, t->driver.remote.environment);
7499                 t->have_driver = true;
7500                 goto try_add;
7501         }
7502
7503         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7504                 t->info2.drivername, t->driver.remote.environment);
7505         torture_comment(tctx, "trying to upload own driver\n");
7506
7507         if (!directory_exist(t->driver.local.driver_directory)) {
7508                 torture_warning(tctx, "no local driver is available!");
7509                 t->have_driver = false;
7510                 goto try_add;
7511         }
7512
7513         torture_assert(tctx,
7514                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7515                 "failed to upload printer driver");
7516
7517         torture_assert(tctx,
7518                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7519                 "failed to add driver");
7520
7521         t->added_driver = true;
7522         t->have_driver = true;
7523
7524  try_add:
7525         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7526
7527         if (t->wellknown) {
7528                 torture_assert(tctx,
7529                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7530                         "failed to add wellknown printer");
7531         } else {
7532                 torture_assert(tctx,
7533                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7534                         "failed to add printer");
7535         }
7536
7537         return true;
7538 }
7539
7540 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7541 {
7542         struct torture_printer_context *t;
7543
7544         *data = t = talloc_zero(tctx, struct torture_printer_context);
7545
7546         t->ex                   = false;
7547         t->wellknown            = false;
7548         t->info2.printername    = TORTURE_PRINTER;
7549         t->devmode              = NULL;
7550
7551         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7552 }
7553
7554 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7555 {
7556         struct torture_printer_context *t;
7557
7558         *data = t = talloc_zero(tctx, struct torture_printer_context);
7559
7560         t->ex                   = true;
7561         t->wellknown            = false;
7562         t->info2.printername    = TORTURE_PRINTER_EX;
7563         t->devmode              = NULL;
7564
7565         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7566 }
7567
7568 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7569 {
7570         struct torture_printer_context *t;
7571
7572         *data = t = talloc_zero(tctx, struct torture_printer_context);
7573
7574         t->ex                   = false;
7575         t->wellknown            = true;
7576         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
7577         t->devmode              = NULL;
7578
7579         /* FIXME */
7580         if (t->wellknown) {
7581                 torture_skip(tctx, "skipping AddPrinter level 1");
7582         }
7583
7584         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7585 }
7586
7587 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7588 {
7589         struct torture_printer_context *t;
7590
7591         *data = t = talloc_zero(tctx, struct torture_printer_context);
7592
7593         t->ex                   = true;
7594         t->wellknown            = true;
7595         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7596         t->devmode              = NULL;
7597
7598         /* FIXME */
7599         if (t->wellknown) {
7600                 torture_skip(tctx, "skipping AddPrinterEx level 1");
7601         }
7602
7603         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7604 }
7605
7606 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7607 {
7608         struct torture_printer_context *t;
7609
7610         *data = t = talloc_zero(tctx, struct torture_printer_context);
7611
7612         t->ex                   = true;
7613         t->wellknown            = false;
7614         t->info2.printername    = TORTURE_PRINTER_EX;
7615         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7616
7617         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7618 }
7619
7620 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7621 {
7622         bool found = false;
7623         struct dcerpc_pipe *p = t->spoolss_pipe;
7624         struct dcerpc_binding_handle *b;
7625         const char *printer_name = t->info2.printername;
7626
7627         if (t->added_driver) {
7628                 torture_assert(tctx,
7629                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7630                         "failed to remove printer driver");
7631         }
7632
7633         if (p) {
7634                 b = p->binding_handle;
7635         }
7636
7637         if (!t->wellknown) {
7638                 torture_assert(tctx,
7639                         test_DeletePrinter(tctx, b, &t->handle),
7640                         "failed to delete printer");
7641
7642                 torture_assert(tctx,
7643                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7644                                                    printer_name, &found),
7645                         "failed to enumerate printers");
7646
7647                 torture_assert(tctx, !found, "deleted printer still there");
7648         }
7649
7650         return true;
7651 }
7652
7653 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7654 {
7655         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7656         bool ret;
7657
7658         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7659         talloc_free(t);
7660
7661         return ret;
7662 }
7663
7664 static bool test_print_test(struct torture_context *tctx,
7665                             void *private_data)
7666 {
7667         struct torture_printer_context *t =
7668                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7669         struct dcerpc_pipe *p = t->spoolss_pipe;
7670         struct dcerpc_binding_handle *b = p->binding_handle;
7671
7672         torture_assert(tctx,
7673                 test_PausePrinter(tctx, b, &t->handle),
7674                 "failed to pause printer");
7675
7676         torture_assert(tctx,
7677                 test_DoPrintTest(tctx, b, &t->handle),
7678                 "failed to do print test");
7679
7680         torture_assert(tctx,
7681                 test_ResumePrinter(tctx, b, &t->handle),
7682                 "failed to resume printer");
7683
7684         return true;
7685 }
7686
7687 static bool test_print_test_extended(struct torture_context *tctx,
7688                                      void *private_data)
7689 {
7690         struct torture_printer_context *t =
7691                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7692         struct dcerpc_pipe *p = t->spoolss_pipe;
7693         struct dcerpc_binding_handle *b = p->binding_handle;
7694         bool ret = true;
7695
7696         torture_assert(tctx,
7697                 test_PausePrinter(tctx, b, &t->handle),
7698                 "failed to pause printer");
7699
7700         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7701         if (ret == false) {
7702                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7703                 if (torture_setting_bool(tctx, "samba3", false)) {
7704                         torture_comment(tctx, "non-critical for samba3\n");
7705                         ret = true;
7706                         tctx->last_result = TORTURE_SKIP;
7707                 }
7708         }
7709
7710         torture_assert(tctx,
7711                 test_ResumePrinter(tctx, b, &t->handle),
7712                 "failed to resume printer");
7713
7714         return ret;
7715 }
7716
7717 static bool test_printer_sd(struct torture_context *tctx,
7718                             void *private_data)
7719 {
7720         struct torture_printer_context *t =
7721                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7722         struct dcerpc_pipe *p = t->spoolss_pipe;
7723         struct dcerpc_binding_handle *b = p->binding_handle;
7724
7725         torture_assert(tctx,
7726                 test_PrinterInfo_SD(tctx, b, &t->handle),
7727                 "failed to test security descriptors");
7728
7729         return true;
7730 }
7731
7732 static bool test_printer_dm(struct torture_context *tctx,
7733                             void *private_data)
7734 {
7735         struct torture_printer_context *t =
7736                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7737         struct dcerpc_pipe *p = t->spoolss_pipe;
7738
7739         torture_assert(tctx,
7740                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7741                 "failed to test devicemodes");
7742
7743         return true;
7744 }
7745
7746 static bool test_printer_info_winreg(struct torture_context *tctx,
7747                                      void *private_data)
7748 {
7749         struct torture_printer_context *t =
7750                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7751         struct dcerpc_pipe *p = t->spoolss_pipe;
7752
7753         torture_assert(tctx,
7754                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7755                 "failed to test printer info winreg");
7756
7757         return true;
7758 }
7759
7760 static bool test_printer_change_id(struct torture_context *tctx,
7761                                    void *private_data)
7762 {
7763         struct torture_printer_context *t =
7764                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7765         struct dcerpc_pipe *p = t->spoolss_pipe;
7766
7767         torture_assert(tctx,
7768                 test_ChangeID(tctx, p, &t->handle),
7769                 "failed to test change id");
7770
7771         return true;
7772 }
7773
7774 static bool test_printer_keys(struct torture_context *tctx,
7775                               void *private_data)
7776 {
7777         struct torture_printer_context *t =
7778                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7779         struct dcerpc_pipe *p = t->spoolss_pipe;
7780         struct dcerpc_binding_handle *b = p->binding_handle;
7781
7782         torture_assert(tctx,
7783                 test_printer_all_keys(tctx, b, &t->handle),
7784                 "failed to test printer keys");
7785
7786         return true;
7787 }
7788
7789 static bool test_printer_data_consistency(struct torture_context *tctx,
7790                                           void *private_data)
7791 {
7792         struct torture_printer_context *t =
7793                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7794         struct dcerpc_pipe *p = t->spoolss_pipe;
7795
7796         torture_assert(tctx,
7797                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7798                 "failed to test printer data consistency");
7799
7800         return true;
7801 }
7802
7803 static bool test_printer_data_keys(struct torture_context *tctx,
7804                                    void *private_data)
7805 {
7806         struct torture_printer_context *t =
7807                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7808         struct dcerpc_pipe *p = t->spoolss_pipe;
7809
7810         torture_assert(tctx,
7811                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7812                 "failed to test printer data keys");
7813
7814         return true;
7815 }
7816
7817 static bool test_printer_data_values(struct torture_context *tctx,
7818                                      void *private_data)
7819 {
7820         struct torture_printer_context *t =
7821                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7822         struct dcerpc_pipe *p = t->spoolss_pipe;
7823
7824         torture_assert(tctx,
7825                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7826                 "failed to test printer data values");
7827
7828         return true;
7829 }
7830
7831 static bool test_printer_data_set(struct torture_context *tctx,
7832                                   void *private_data)
7833 {
7834         struct torture_printer_context *t =
7835                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7836         struct dcerpc_pipe *p = t->spoolss_pipe;
7837
7838         torture_assert(tctx,
7839                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7840                 "failed to test printer data set");
7841
7842         return true;
7843 }
7844
7845 static bool test_printer_data_winreg(struct torture_context *tctx,
7846                                      void *private_data)
7847 {
7848         struct torture_printer_context *t =
7849                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7850         struct dcerpc_pipe *p = t->spoolss_pipe;
7851
7852         torture_assert(tctx,
7853                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7854                 "failed to test printer data winreg");
7855
7856         return true;
7857 }
7858
7859 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7860                                         void *private_data)
7861 {
7862         struct torture_printer_context *t =
7863                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7864         struct dcerpc_pipe *p = t->spoolss_pipe;
7865
7866         torture_assert(tctx,
7867                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7868                 "failed to test printer data winreg dsspooler");
7869
7870         return true;
7871 }
7872
7873 static bool test_driver_info_winreg(struct torture_context *tctx,
7874                                     void *private_data)
7875 {
7876         struct torture_printer_context *t =
7877                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7878         struct dcerpc_pipe *p = t->spoolss_pipe;
7879         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7880
7881         if (!t->have_driver) {
7882                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7883         }
7884
7885         torture_assert(tctx,
7886                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7887                 "failed to test driver info winreg");
7888
7889         return true;
7890 }
7891
7892 void torture_tcase_printer(struct torture_tcase *tcase)
7893 {
7894         torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7895         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7896         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7897         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7898         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7899         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7900         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7901         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7902         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7903         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7904         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7905         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7906         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7907         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7908         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7909         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7910         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7911         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7912 }
7913
7914 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7915 {
7916         struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7917         struct torture_tcase *tcase;
7918
7919         tcase = torture_suite_add_tcase(suite, "addprinter");
7920
7921         torture_tcase_set_fixture(tcase,
7922                                   torture_rpc_spoolss_printer_setup,
7923                                   torture_rpc_spoolss_printer_teardown);
7924
7925         torture_tcase_printer(tcase);
7926
7927         tcase = torture_suite_add_tcase(suite, "addprinterex");
7928
7929         torture_tcase_set_fixture(tcase,
7930                                   torture_rpc_spoolss_printerex_setup,
7931                                   torture_rpc_spoolss_printer_teardown);
7932
7933         torture_tcase_printer(tcase);
7934
7935         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7936
7937         torture_tcase_set_fixture(tcase,
7938                                   torture_rpc_spoolss_printerwkn_setup,
7939                                   torture_rpc_spoolss_printer_teardown);
7940
7941         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7942
7943         torture_tcase_set_fixture(tcase,
7944                                   torture_rpc_spoolss_printerexwkn_setup,
7945                                   torture_rpc_spoolss_printer_teardown);
7946
7947 #if 0
7948         /* test is not correct */
7949         tcase = torture_suite_add_tcase(suite, "addprinterdm");
7950
7951         torture_tcase_set_fixture(tcase,
7952                                   torture_rpc_spoolss_printerdm_setup,
7953                                   torture_rpc_spoolss_printer_teardown);
7954
7955         torture_tcase_printer(tcase);
7956 #endif
7957         return suite;
7958 }
7959
7960 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7961 {
7962         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7963         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7964
7965         torture_tcase_set_fixture(tcase,
7966                                   torture_rpc_spoolss_setup,
7967                                   torture_rpc_spoolss_teardown);
7968
7969         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7970         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7971         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7972         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7973         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7974         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7975         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7976         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7977         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7978         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7979         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7980         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7981         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7982         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7983         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7984         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7985         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7986         torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7987         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7988         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7989
7990         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7991
7992         return suite;
7993 }
7994
7995 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7996                                                   struct dcerpc_binding_handle *b,
7997                                                   const char *server,
7998                                                   const char *environment,
7999                                                   const char **dir_p)
8000 {
8001         struct spoolss_GetPrinterDriverDirectory r;
8002         uint32_t needed;
8003
8004         r.in.server             = server;
8005         r.in.environment        = environment;
8006         r.in.level              = 1;
8007         r.in.buffer             = NULL;
8008         r.in.offered            = 0;
8009         r.out.needed            = &needed;
8010
8011         torture_assert_ntstatus_ok(tctx,
8012                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8013                 "failed to query driver directory");
8014
8015         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8016                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8017                 r.in.buffer = &blob;
8018                 r.in.offered = needed;
8019
8020                 torture_assert_ntstatus_ok(tctx,
8021                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8022                         "failed to query driver directory");
8023         }
8024
8025         torture_assert_werr_ok(tctx, r.out.result,
8026                 "failed to query driver directory");
8027
8028         if (dir_p) {
8029                 *dir_p = r.out.info->info1.directory_name;
8030         }
8031
8032         return true;
8033 }
8034
8035 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8036 {
8037         if (info_ctr == NULL) {
8038                 return NULL;
8039         }
8040
8041         switch (info_ctr->level) {
8042         case 1:
8043                 return info_ctr->info.info1->driver_name;
8044         case 2:
8045                 return info_ctr->info.info2->driver_name;
8046         case 3:
8047                 return info_ctr->info.info3->driver_name;
8048         case 4:
8049                 return info_ctr->info.info4->driver_name;
8050         case 6:
8051                 return info_ctr->info.info6->driver_name;
8052         case 8:
8053                 return info_ctr->info.info8->driver_name;
8054         default:
8055                 return NULL;
8056         }
8057 }
8058
8059 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8060 {
8061         if (info_ctr == NULL) {
8062                 return NULL;
8063         }
8064
8065         switch (info_ctr->level) {
8066         case 2:
8067                 return info_ctr->info.info2->architecture;
8068         case 3:
8069                 return info_ctr->info.info3->architecture;
8070         case 4:
8071                 return info_ctr->info.info4->architecture;
8072         case 6:
8073                 return info_ctr->info.info6->architecture;
8074         case 8:
8075                 return info_ctr->info.info8->architecture;
8076         default:
8077                 return NULL;
8078         }
8079 }
8080
8081
8082 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8083                                       struct dcerpc_binding_handle *b,
8084                                       const char *servername,
8085                                       struct spoolss_AddDriverInfoCtr *info_ctr,
8086                                       WERROR expected_result)
8087 {
8088         struct spoolss_AddPrinterDriver r;
8089         const char *drivername = get_driver_from_info(info_ctr);
8090         const char *environment = get_environment_from_info(info_ctr);
8091
8092         r.in.servername = servername;
8093         r.in.info_ctr = info_ctr;
8094
8095         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8096                 drivername, info_ctr->level, environment);
8097
8098         torture_assert_ntstatus_ok(tctx,
8099                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8100                 "spoolss_AddPrinterDriver failed");
8101         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8102                 "spoolss_AddPrinterDriver failed with unexpected result");
8103
8104         return true;
8105
8106 }
8107
8108 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8109                                         struct dcerpc_binding_handle *b,
8110                                         const char *servername,
8111                                         struct spoolss_AddDriverInfoCtr *info_ctr,
8112                                         uint32_t flags,
8113                                         WERROR expected_result)
8114 {
8115         struct spoolss_AddPrinterDriverEx r;
8116         const char *drivername = get_driver_from_info(info_ctr);
8117         const char *environment = get_environment_from_info(info_ctr);
8118
8119         r.in.servername = servername;
8120         r.in.info_ctr = info_ctr;
8121         r.in.flags = flags;
8122
8123         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8124                 drivername, info_ctr->level, environment);
8125
8126         torture_assert_ntstatus_ok(tctx,
8127                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8128                 "AddPrinterDriverEx failed");
8129         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8130                 "AddPrinterDriverEx failed with unexpected result");
8131
8132         return true;
8133 }
8134
8135 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8136         if (path && strlen(path)) {\
8137                 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8138         }
8139
8140 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8141                                                struct dcerpc_binding_handle *b,
8142                                                const char *server_name,
8143                                                struct spoolss_AddDriverInfo8 *r,
8144                                                uint32_t flags,
8145                                                bool ex,
8146                                                const char *remote_driver_dir)
8147 {
8148         struct spoolss_AddDriverInfoCtr info_ctr;
8149         struct spoolss_AddDriverInfo1 info1;
8150
8151         ZERO_STRUCT(info1);
8152
8153         info_ctr.level = 1;
8154         info_ctr.info.info1 = &info1;
8155
8156         if (ex) {
8157                 torture_assert(tctx,
8158                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8159                         "failed to test AddPrinterDriverEx level 1");
8160         } else {
8161                 torture_assert(tctx,
8162                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8163                         "failed to test AddPrinterDriver level 1");
8164         }
8165
8166         info1.driver_name = r->driver_name;
8167
8168         if (ex) {
8169                 torture_assert(tctx,
8170                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8171                         "failed to test AddPrinterDriverEx level 1");
8172         } else {
8173                 torture_assert(tctx,
8174                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8175                         "failed to test AddPrinterDriver level 1");
8176         }
8177
8178         return true;
8179 }
8180
8181 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8182                                                struct dcerpc_binding_handle *b,
8183                                                const char *server_name,
8184                                                struct spoolss_AddDriverInfo8 *r,
8185                                                uint32_t flags,
8186                                                bool ex,
8187                                                const char *remote_driver_dir)
8188 {
8189         struct spoolss_AddDriverInfoCtr info_ctr;
8190         struct spoolss_AddDriverInfo2 info2;
8191         union spoolss_DriverInfo info;
8192
8193         ZERO_STRUCT(info2);
8194
8195         info_ctr.level = 2;
8196         info_ctr.info.info2 = &info2;
8197
8198         if (ex) {
8199                 torture_assert(tctx,
8200                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8201                         "failed to test AddPrinterDriverEx level 2");
8202         } else {
8203                 torture_assert(tctx,
8204                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8205                         "failed to test AddPrinterDriver level 2");
8206         }
8207
8208         info2.driver_name = r->driver_name;
8209
8210         if (ex) {
8211                 torture_assert(tctx,
8212                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8213                         "failed to test AddPrinterDriverEx level 2");
8214         } else {
8215                 torture_assert(tctx,
8216                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8217                         "failed to test AddPrinterDriver level 2");
8218         }
8219
8220         info2.version = r->version;
8221
8222         if (ex) {
8223                 torture_assert(tctx,
8224                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8225                         "failed to test AddPrinterDriverEx level 2");
8226         } else {
8227                 torture_assert(tctx,
8228                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8229                         "failed to test AddPrinterDriver level 2");
8230         }
8231
8232         info2.architecture = r->architecture;
8233
8234         if (ex) {
8235                 torture_assert(tctx,
8236                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8237                         "failed to test AddPrinterDriverEx level 2");
8238         } else {
8239                 torture_assert(tctx,
8240                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8241                         "failed to test AddPrinterDriver level 2");
8242         }
8243
8244         info2.driver_path = r->driver_path;
8245
8246         if (ex) {
8247                 torture_assert(tctx,
8248                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8249                         "failed to test AddPrinterDriverEx level 2");
8250         } else {
8251                 torture_assert(tctx,
8252                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8253                         "failed to test AddPrinterDriver level 2");
8254         }
8255
8256         info2.data_file = r->data_file;
8257
8258         if (ex) {
8259                 torture_assert(tctx,
8260                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8261                         "failed to test AddPrinterDriverEx level 2");
8262         } else {
8263                 torture_assert(tctx,
8264                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8265                         "failed to test AddPrinterDriver level 2");
8266         }
8267
8268         info2.config_file = r->config_file;
8269
8270         if (ex) {
8271                 torture_assert(tctx,
8272                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8273                         "failed to test AddPrinterDriverEx");
8274         }
8275
8276         if (ex) {
8277                 torture_assert(tctx,
8278                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8279                         "failed to test AddPrinterDriverEx level 2");
8280         } else {
8281                 torture_assert(tctx,
8282                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8283                         "failed to test AddPrinterDriver level 2");
8284         }
8285
8286         torture_assert(tctx,
8287                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8288                 "failed to find added printer driver");
8289
8290         if (remote_driver_dir) {
8291                 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8292                 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8293                 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8294         }
8295
8296         return true;
8297 }
8298
8299 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8300                                                struct dcerpc_binding_handle *b,
8301                                                const char *server_name,
8302                                                struct spoolss_AddDriverInfo8 *r,
8303                                                uint32_t flags,
8304                                                bool ex,
8305                                                const char *remote_driver_dir)
8306 {
8307         struct spoolss_AddDriverInfoCtr info_ctr;
8308         struct spoolss_AddDriverInfo3 info3;
8309         union spoolss_DriverInfo info;
8310
8311         info3.driver_name       = r->driver_name;
8312         info3.version           = r->version;
8313         info3.architecture      = r->architecture;
8314         info3.driver_path       = r->driver_path;
8315         info3.data_file         = r->data_file;
8316         info3.config_file       = r->config_file;
8317         info3.help_file         = r->help_file;
8318         info3.monitor_name      = r->monitor_name;
8319         info3.default_datatype  = r->default_datatype;
8320         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8321         info3.dependent_files   = r->dependent_files;
8322
8323         info_ctr.level = 3;
8324         info_ctr.info.info3 = &info3;
8325
8326         if (ex) {
8327                 torture_assert(tctx,
8328                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8329                         "failed to test AddPrinterDriverEx level 3");
8330         } else {
8331                 torture_assert(tctx,
8332                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8333                         "failed to test AddPrinterDriver level 3");
8334         }
8335
8336         torture_assert(tctx,
8337                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8338                 "failed to find added printer driver");
8339
8340         if (remote_driver_dir) {
8341                 int i;
8342                 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8343                 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8344                 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8345                 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8346                 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8347                         ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8348                 }
8349         }
8350
8351         return true;
8352 }
8353
8354 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8355                                                struct dcerpc_binding_handle *b,
8356                                                const char *server_name,
8357                                                struct spoolss_AddDriverInfo8 *r,
8358                                                uint32_t flags,
8359                                                bool ex,
8360                                                const char *remote_driver_dir)
8361 {
8362         struct spoolss_AddDriverInfoCtr info_ctr;
8363         struct spoolss_AddDriverInfo4 info4;
8364         union spoolss_DriverInfo info;
8365
8366         info4.version           = r->version;
8367         info4.driver_name       = r->driver_name;
8368         info4.architecture      = r->architecture;
8369         info4.driver_path       = r->driver_path;
8370         info4.data_file         = r->data_file;
8371         info4.config_file       = r->config_file;
8372         info4.help_file         = r->help_file;
8373         info4.monitor_name      = r->monitor_name;
8374         info4.default_datatype  = r->default_datatype;
8375         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8376         info4.dependent_files   = r->dependent_files;
8377         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8378         info4.previous_names = r->previous_names;
8379
8380         info_ctr.level = 4;
8381         info_ctr.info.info4 = &info4;
8382
8383         if (ex) {
8384                 torture_assert(tctx,
8385                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8386                         "failed to test AddPrinterDriverEx level 4");
8387         } else {
8388                 torture_assert(tctx,
8389                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8390                         "failed to test AddPrinterDriver level 4");
8391         }
8392
8393         torture_assert(tctx,
8394                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8395                 "failed to find added printer driver");
8396
8397         if (remote_driver_dir) {
8398                 int i;
8399                 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8400                 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8401                 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8402                 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8403                 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8404                         ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8405                 }
8406         }
8407
8408         return true;
8409 }
8410
8411 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8412                                                struct dcerpc_binding_handle *b,
8413                                                const char *server_name,
8414                                                struct spoolss_AddDriverInfo8 *r,
8415                                                uint32_t flags,
8416                                                bool ex,
8417                                                const char *remote_driver_dir)
8418 {
8419         struct spoolss_AddDriverInfoCtr info_ctr;
8420         struct spoolss_AddDriverInfo6 info6;
8421         union spoolss_DriverInfo info;
8422
8423         info6.version           = r->version;
8424         info6.driver_name       = r->driver_name;
8425         info6.architecture      = r->architecture;
8426         info6.driver_path       = r->driver_path;
8427         info6.data_file         = r->data_file;
8428         info6.config_file       = r->config_file;
8429         info6.help_file         = r->help_file;
8430         info6.monitor_name      = r->monitor_name;
8431         info6.default_datatype  = r->default_datatype;
8432         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8433         info6.dependent_files   = r->dependent_files;
8434         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8435         info6.previous_names    = r->previous_names;
8436         info6.driver_date       = r->driver_date;
8437         info6.driver_version    = r->driver_version;
8438         info6.manufacturer_name = r->manufacturer_name;
8439         info6.manufacturer_url  = r->manufacturer_url;
8440         info6.hardware_id       = r->hardware_id;
8441         info6.provider          = r->provider;
8442
8443         info_ctr.level = 6;
8444         info_ctr.info.info6 = &info6;
8445
8446         if (ex) {
8447                 torture_assert(tctx,
8448                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8449                         "failed to test AddPrinterDriverEx level 6");
8450         } else {
8451                 torture_assert(tctx,
8452                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8453                         "failed to test AddPrinterDriver level 6");
8454         }
8455
8456         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8457
8458         if (!ex) {
8459                 return true;
8460         }
8461
8462         torture_assert(tctx,
8463                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8464                 "failed to find added printer driver");
8465
8466         if (remote_driver_dir) {
8467                 int i;
8468                 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8469                 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8470                 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8471                 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8472                 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8473                         ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8474                 }
8475         }
8476
8477         torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8478         torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8479
8480         return true;
8481 }
8482
8483 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8484                                                struct dcerpc_binding_handle *b,
8485                                                const char *server_name,
8486                                                struct spoolss_AddDriverInfo8 *r,
8487                                                uint32_t flags,
8488                                                bool ex,
8489                                                const char *remote_driver_dir)
8490 {
8491         struct spoolss_AddDriverInfoCtr info_ctr;
8492         union spoolss_DriverInfo info;
8493
8494         info_ctr.level = 8;
8495         info_ctr.info.info8 = r;
8496
8497         if (ex) {
8498                 torture_assert(tctx,
8499                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8500                         "failed to test AddPrinterDriverEx level 8");
8501         } else {
8502                 torture_assert(tctx,
8503                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8504                         "failed to test AddPrinterDriver level 8");
8505         }
8506
8507         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8508
8509         if (!ex) {
8510                 return true;
8511         }
8512
8513         torture_assert(tctx,
8514                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8515                 "failed to find added printer driver");
8516
8517         if (remote_driver_dir) {
8518                 int i;
8519                 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8520                 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8521                 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8522                 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8523                 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8524                         ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8525                 }
8526         }
8527
8528         torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8529         torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8530
8531         return true;
8532 }
8533
8534 #undef ASSERT_DRIVER_PATH
8535
8536 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8537                                          struct dcerpc_binding_handle *b,
8538                                          const char *server,
8539                                          const char *driver,
8540                                          const char *environment,
8541                                          WERROR expected_result)
8542 {
8543         struct spoolss_DeletePrinterDriver r;
8544
8545         r.in.server = server;
8546         r.in.architecture = environment;
8547         r.in.driver = driver;
8548
8549         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8550
8551         torture_assert_ntstatus_ok(tctx,
8552                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8553                 "DeletePrinterDriver failed");
8554         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8555                 "DeletePrinterDriver failed with unexpected result");
8556
8557         return true;
8558 }
8559
8560 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8561                                            struct dcerpc_binding_handle *b,
8562                                            const char *server,
8563                                            const char *driver,
8564                                            const char *environment,
8565                                            uint32_t delete_flags,
8566                                            uint32_t version,
8567                                            WERROR expected_result)
8568 {
8569         struct spoolss_DeletePrinterDriverEx r;
8570
8571         r.in.server = server;
8572         r.in.architecture = environment;
8573         r.in.driver = driver;
8574         r.in.delete_flags = delete_flags;
8575         r.in.version = version;
8576
8577         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8578
8579         torture_assert_ntstatus_ok(tctx,
8580                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8581                 "DeletePrinterDriverEx failed");
8582         torture_assert_werr_equal(tctx, r.out.result, expected_result,
8583                 "DeletePrinterDriverEx failed with unexpected result");
8584
8585         return true;
8586 }
8587
8588 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8589                                      struct dcerpc_binding_handle *b,
8590                                      const char *server_name,
8591                                      const char *driver,
8592                                      const char *environment)
8593 {
8594         torture_assert(tctx,
8595                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8596                 "failed to delete driver");
8597
8598         torture_assert(tctx,
8599                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8600                 "failed to delete driver");
8601
8602         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8603                 torture_fail(tctx, "deleted driver still enumerated");
8604         }
8605
8606         torture_assert(tctx,
8607                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8608                 "2nd delete failed");
8609
8610         return true;
8611 }
8612
8613 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8614                                        struct dcerpc_binding_handle *b,
8615                                        const char *server_name,
8616                                        const char *driver,
8617                                        const char *environment,
8618                                        uint32_t delete_flags,
8619                                        uint32_t version)
8620 {
8621         torture_assert(tctx,
8622                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8623                 "failed to delete driver");
8624
8625         torture_assert(tctx,
8626                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8627                 "failed to delete driver");
8628
8629         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8630                 torture_fail(tctx, "deleted driver still enumerated");
8631         }
8632
8633         torture_assert(tctx,
8634                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8635                 "2nd delete failed");
8636
8637         return true;
8638 }
8639
8640 static bool test_PrinterDriver_args(struct torture_context *tctx,
8641                                     struct dcerpc_binding_handle *b,
8642                                     const char *server_name,
8643                                     uint32_t level,
8644                                     struct spoolss_AddDriverInfo8 *r,
8645                                     uint32_t add_flags,
8646                                     uint32_t delete_flags,
8647                                     uint32_t delete_version,
8648                                     bool ex,
8649                                     const char *remote_driver_dir)
8650 {
8651         bool ret = true;
8652
8653         switch (level) {
8654         case 1:
8655                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8656                 break;
8657         case 2:
8658                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8659                 break;
8660         case 3:
8661                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8662                 break;
8663         case 4:
8664                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8665                 break;
8666         case 6:
8667                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8668                 break;
8669         case 8:
8670                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8671                 break;
8672         default:
8673                 return false;
8674         }
8675
8676         if (ret == false) {
8677                 return ret;
8678         }
8679
8680         if (level == 1) {
8681                 return ret;
8682         }
8683
8684         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8685
8686         if (!ex && (level == 6 || level == 8)) {
8687                 return ret;
8688         }
8689
8690         {
8691                 struct dcerpc_pipe *p2;
8692                 struct policy_handle hive_handle;
8693                 struct dcerpc_binding_handle *b2;
8694
8695                 torture_assert_ntstatus_ok(tctx,
8696                         torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8697                         "could not open winreg pipe");
8698                 b2 = p2->binding_handle;
8699
8700                 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8701
8702                 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8703
8704                 test_winreg_CloseKey(tctx, b2, &hive_handle);
8705
8706                 talloc_free(p2);
8707         }
8708
8709         if (ex) {
8710                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8711         } else {
8712                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8713         }
8714 }
8715
8716 static bool fillup_printserver_info(struct torture_context *tctx,
8717                                     struct dcerpc_pipe *p,
8718                                     struct torture_driver_context *d)
8719 {
8720         struct policy_handle server_handle;
8721         struct dcerpc_binding_handle *b = p->binding_handle;
8722         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8723
8724         torture_assert(tctx,
8725                 test_OpenPrinter_server(tctx, p, &server_handle),
8726                 "failed to open printserver");
8727         torture_assert(tctx,
8728                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8729                 "failed to get environment");
8730         torture_assert(tctx,
8731                 test_ClosePrinter(tctx, b, &server_handle),
8732                 "failed to close printserver");
8733
8734         torture_assert(tctx,
8735                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8736                         d->local.environment ? d->local.environment : d->remote.environment,
8737                         &d->remote.driver_directory),
8738                 "failed to get driver directory");
8739
8740         return true;
8741 }
8742
8743 static const char *driver_directory_dir(const char *driver_directory)
8744 {
8745         char *p;
8746
8747         p = strrchr(driver_directory, '\\');
8748         if (p) {
8749                 return p+1;
8750         }
8751
8752         return NULL;
8753 }
8754
8755 static const char *driver_directory_share(struct torture_context *tctx,
8756                                           const char *driver_directory)
8757 {
8758         const char *p;
8759         char *tok;
8760
8761         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8762                 driver_directory += 2;
8763         }
8764
8765         p = talloc_strdup(tctx, driver_directory);
8766
8767         torture_assert(tctx,
8768                 next_token_talloc(tctx, &p, &tok, "\\"),
8769                 "cannot explode uri");
8770         torture_assert(tctx,
8771                 next_token_talloc(tctx, &p, &tok, "\\"),
8772                 "cannot explode uri");
8773
8774         return tok;
8775 }
8776
8777 static bool upload_printer_driver_file(struct torture_context *tctx,
8778                                        struct smbcli_state *cli,
8779                                        struct torture_driver_context *d,
8780                                        const char *file_name)
8781 {
8782         XFILE *f;
8783         int fnum;
8784         uint8_t *buf;
8785         int maxwrite = 64512;
8786         off_t nread = 0;
8787         size_t start = 0;
8788         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8789         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8790         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8791
8792         if (!file_name || strlen(file_name) == 0) {
8793                 return true;
8794         }
8795
8796         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8797
8798         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8799         if (fnum == -1) {
8800                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8801         }
8802
8803         f = x_fopen(local_name, O_RDONLY, 0);
8804         if (f == NULL) {
8805                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8806         }
8807
8808         buf = talloc_array(tctx, uint8_t, maxwrite);
8809         if (!buf) {
8810                 return false;
8811         }
8812
8813         while (!x_feof(f)) {
8814                 int n = maxwrite;
8815                 int ret;
8816
8817                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8818                         if((n == 0) && x_feof(f))
8819                                 break; /* Empty local file. */
8820
8821                         torture_warning(tctx,
8822                                 "failed to read file: %s\n", strerror(errno));
8823                         break;
8824                 }
8825
8826                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8827
8828                 if (n != ret) {
8829                         torture_warning(tctx,
8830                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8831                         break;
8832                 }
8833
8834                 nread += n;
8835         }
8836
8837         x_fclose(f);
8838
8839         torture_assert_ntstatus_ok(tctx,
8840                 smbcli_close(cli->tree, fnum),
8841                 "failed to close file");
8842
8843         return true;
8844 }
8845
8846 static bool connect_printer_driver_share(struct torture_context *tctx,
8847                                          const char *server_name,
8848                                          const char *share_name,
8849                                          struct smbcli_state **cli)
8850 {
8851         struct smbcli_options smb_options;
8852         struct smbcli_session_options smb_session_options;
8853
8854         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8855                 share_name, server_name);
8856
8857         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8858         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8859
8860         torture_assert_ntstatus_ok(tctx,
8861                 smbcli_full_connection(tctx, cli, server_name,
8862                                         lpcfg_smb_ports(tctx->lp_ctx),
8863                                         share_name, NULL,
8864                                         lpcfg_socket_options(tctx->lp_ctx),
8865                                         cmdline_credentials,
8866                                         lpcfg_resolve_context(tctx->lp_ctx),
8867                                         tctx->ev,
8868                                         &smb_options,
8869                                         &smb_session_options,
8870                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8871                 "failed to open driver share");
8872
8873         return true;
8874 }
8875
8876 static bool upload_printer_driver(struct torture_context *tctx,
8877                                   const char *server_name,
8878                                   struct torture_driver_context *d)
8879 {
8880         struct smbcli_state *cli;
8881         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8882         int i;
8883
8884         torture_assert(tctx,
8885                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8886                 "failed to connect to driver share");
8887
8888         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8889                 server_name, share_name);
8890
8891         torture_assert(tctx,
8892                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8893                 "failed to upload driver_path");
8894         torture_assert(tctx,
8895                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8896                 "failed to upload data_file");
8897         torture_assert(tctx,
8898                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8899                 "failed to upload config_file");
8900         torture_assert(tctx,
8901                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8902                 "failed to upload help_file");
8903         if (d->info8.dependent_files) {
8904                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8905                         torture_assert(tctx,
8906                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8907                                 "failed to upload dependent_files");
8908                 }
8909         }
8910
8911         talloc_free(cli);
8912
8913         return true;
8914 }
8915
8916 static bool remove_printer_driver_file(struct torture_context *tctx,
8917                                        struct smbcli_state *cli,
8918                                        struct torture_driver_context *d,
8919                                        const char *file_name)
8920 {
8921         const char *remote_name;
8922         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
8923
8924         if (!file_name || strlen(file_name) == 0) {
8925                 return true;
8926         }
8927
8928         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8929
8930         torture_comment(tctx, "Removing %s\n", remote_name);
8931
8932         torture_assert_ntstatus_ok(tctx,
8933                 smbcli_unlink(cli->tree, remote_name),
8934                 "failed to unlink");
8935
8936         return true;
8937 }
8938
8939 static bool remove_printer_driver(struct torture_context *tctx,
8940                                   const char *server_name,
8941                                   struct torture_driver_context *d)
8942 {
8943         struct smbcli_state *cli;
8944         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8945         int i;
8946
8947         torture_assert(tctx,
8948                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8949                 "failed to connect to driver share");
8950
8951         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8952                 server_name, share_name);
8953
8954         torture_assert(tctx,
8955                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8956                 "failed to remove driver_path");
8957         torture_assert(tctx,
8958                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8959                 "failed to remove data_file");
8960         if (!strequal(d->info8.config_file, d->info8.driver_path)) {
8961                 torture_assert(tctx,
8962                         remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8963                         "failed to remove config_file");
8964         }
8965         torture_assert(tctx,
8966                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8967                 "failed to remove help_file");
8968         if (d->info8.dependent_files) {
8969                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8970                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8971                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8972                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8973                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8974                                 continue;
8975                         }
8976                         torture_assert(tctx,
8977                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8978                                 "failed to remove dependent_files");
8979                 }
8980         }
8981
8982         talloc_free(cli);
8983
8984         return true;
8985
8986 }
8987
8988 static bool test_add_driver_arg(struct torture_context *tctx,
8989                                 struct dcerpc_pipe *p,
8990                                 struct torture_driver_context *d)
8991 {
8992         bool ret = true;
8993         struct dcerpc_binding_handle *b = p->binding_handle;
8994         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8995         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8996         int i;
8997         struct spoolss_AddDriverInfo8 info8;
8998         uint32_t add_flags = APD_COPY_NEW_FILES;
8999         uint32_t delete_flags = 0;
9000
9001         ZERO_STRUCT(info8);
9002
9003         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9004                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9005
9006         torture_assert(tctx,
9007                 fillup_printserver_info(tctx, p, d),
9008                 "failed to fillup printserver info");
9009
9010         if (!directory_exist(d->local.driver_directory)) {
9011                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9012         }
9013
9014         torture_assert(tctx,
9015                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9016                 "failed to upload printer driver");
9017
9018         info8 = d->info8;
9019         if (d->info8.dependent_files) {
9020                 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9021                 if (d->info8.dependent_files->string) {
9022                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9023                         }
9024                         info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9025                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9026                                 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9027                         }
9028                 }
9029         }
9030         info8.architecture      = d->local.environment;
9031
9032         for (i=0; i < ARRAY_SIZE(levels); i++) {
9033
9034                 if (torture_setting_bool(tctx, "samba3", false)) {
9035                         switch (levels[i]) {
9036                         case 2:
9037                         case 4:
9038                         case 8:
9039                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9040                                 continue;
9041                         default:
9042                                 break;
9043                         }
9044                 }
9045                 if (torture_setting_bool(tctx, "w2k3", false)) {
9046                         switch (levels[i]) {
9047                         case 8:
9048                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9049                                 continue;
9050                         default:
9051                                 break;
9052                         }
9053                 }
9054
9055                 torture_comment(tctx,
9056                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
9057                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9058
9059                 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);
9060         }
9061
9062         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9063         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9064         if (d->info8.config_file) {
9065                 info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9066         }
9067         if (d->info8.help_file) {
9068                 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9069         }
9070         if (d->info8.dependent_files && d->info8.dependent_files->string) {
9071                 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9072                         info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9073                 }
9074         }
9075
9076         for (i=0; i < ARRAY_SIZE(levels); i++) {
9077
9078                 if (torture_setting_bool(tctx, "samba3", false)) {
9079                         switch (levels[i]) {
9080                         case 2:
9081                         case 4:
9082                         case 8:
9083                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9084                                 continue;
9085                         default:
9086                                 break;
9087                         }
9088                 }
9089                 if (torture_setting_bool(tctx, "w2k3", false)) {
9090                         switch (levels[i]) {
9091                         case 8:
9092                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9093                                 continue;
9094                         default:
9095                                 break;
9096                         }
9097                 }
9098
9099                 torture_comment(tctx,
9100                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9101                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9102
9103                 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);
9104         }
9105
9106         torture_assert(tctx,
9107                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9108                 "failed to remove printer driver");
9109
9110         torture_comment(tctx, "\n");
9111
9112         return ret;
9113 }
9114
9115 static bool test_add_driver_ex_64(struct torture_context *tctx,
9116                                   struct dcerpc_pipe *p)
9117 {
9118         struct torture_driver_context *d;
9119
9120         d = talloc_zero(tctx, struct torture_driver_context);
9121
9122         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9123         d->info8.driver_name            = TORTURE_DRIVER_EX;
9124         d->info8.architecture           = NULL;
9125         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9126         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9127         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9128         d->local.environment            = talloc_strdup(d, "Windows x64");
9129         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9130         d->ex                           = true;
9131
9132         return test_add_driver_arg(tctx, p, d);
9133 }
9134
9135 static bool test_add_driver_ex_32(struct torture_context *tctx,
9136                                   struct dcerpc_pipe *p)
9137 {
9138         struct torture_driver_context *d;
9139
9140         d = talloc_zero(tctx, struct torture_driver_context);
9141
9142         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9143         d->info8.driver_name            = TORTURE_DRIVER_EX;
9144         d->info8.architecture           = NULL;
9145         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9146         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9147         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9148         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9149         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9150         d->ex                           = true;
9151
9152         return test_add_driver_arg(tctx, p, d);
9153 }
9154
9155 static bool test_add_driver_64(struct torture_context *tctx,
9156                                struct dcerpc_pipe *p)
9157 {
9158         struct torture_driver_context *d;
9159
9160         d = talloc_zero(tctx, struct torture_driver_context);
9161
9162         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9163         d->info8.driver_name            = TORTURE_DRIVER;
9164         d->info8.architecture           = NULL;
9165         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9166         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9167         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9168         d->local.environment            = talloc_strdup(d, "Windows x64");
9169         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9170         d->ex                           = false;
9171
9172         return test_add_driver_arg(tctx, p, d);
9173 }
9174
9175 static bool test_add_driver_32(struct torture_context *tctx,
9176                                struct dcerpc_pipe *p)
9177 {
9178         struct torture_driver_context *d;
9179
9180         d = talloc_zero(tctx, struct torture_driver_context);
9181
9182         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9183         d->info8.driver_name            = TORTURE_DRIVER;
9184         d->info8.architecture           = NULL;
9185         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9186         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9187         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9188         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9189         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9190         d->ex                           = false;
9191
9192         return test_add_driver_arg(tctx, p, d);
9193 }
9194
9195 static bool test_add_driver_adobe(struct torture_context *tctx,
9196                                   struct dcerpc_pipe *p)
9197 {
9198         struct torture_driver_context *d;
9199
9200         d = talloc_zero(tctx, struct torture_driver_context);
9201
9202         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
9203         d->info8.driver_name            = TORTURE_DRIVER_ADOBE;
9204         d->info8.architecture           = NULL;
9205         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
9206         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
9207         d->info8.config_file            = talloc_strdup(d, "ADOBEPS4.DRV");
9208 #if 0
9209         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
9210         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
9211 #endif
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_adobe_cupsaddsmb(struct torture_context *tctx,
9220                                              struct dcerpc_pipe *p)
9221 {
9222         struct torture_driver_context *d;
9223         struct spoolss_StringArray *a;
9224
9225         if (!torture_setting_bool(tctx, "samba3", false)) {
9226                 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9227         }
9228
9229         d = talloc_zero(tctx, struct torture_driver_context);
9230
9231         d->info8.version                = SPOOLSS_DRIVER_VERSION_9X;
9232         d->info8.driver_name            = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9233         d->info8.architecture           = NULL;
9234         d->info8.driver_path            = talloc_strdup(d, "ADOBEPS4.DRV");
9235         d->info8.data_file              = talloc_strdup(d, "DEFPRTR2.PPD");
9236         d->info8.config_file            = NULL;
9237         d->info8.help_file              = talloc_strdup(d, "ADOBEPS4.HLP");
9238         d->info8.monitor_name           = talloc_strdup(d, "PSMON.DLL");
9239         d->info8.default_datatype       = talloc_strdup(d, "RAW");
9240
9241         a                               = talloc_zero(d, struct spoolss_StringArray);
9242         a->string                       = talloc_zero_array(a, const char *, 7);
9243         a->string[0]                    = talloc_strdup(a->string, "ADOBEPS4.DRV");
9244         a->string[1]                    = talloc_strdup(a->string, "DEFPRTR2.PPD");
9245         a->string[2]                    = talloc_strdup(a->string, "ADOBEPS4.HLP");
9246         a->string[3]                    = talloc_strdup(a->string, "PSMON.DLL");
9247         a->string[4]                    = talloc_strdup(a->string, "ADFONTS.MFM");
9248         a->string[5]                    = talloc_strdup(a->string, "ICONLIB.DLL");
9249
9250         d->info8.dependent_files        = a;
9251         d->local.environment            = talloc_strdup(d, "Windows 4.0");
9252         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9253         d->ex                           = false;
9254
9255         return test_add_driver_arg(tctx, p, d);
9256 }
9257
9258 static bool test_add_driver_timestamps(struct torture_context *tctx,
9259                                        struct dcerpc_pipe *p)
9260 {
9261         struct torture_driver_context *d;
9262         struct timeval t = timeval_current();
9263
9264         if (torture_setting_bool(tctx, "samba3", false)) {
9265                 torture_skip(tctx, "skipping timestamps test against samba");
9266         }
9267
9268         d = talloc_zero(tctx, struct torture_driver_context);
9269
9270         d->info8.version                = SPOOLSS_DRIVER_VERSION_200X;
9271         d->info8.driver_name            = TORTURE_DRIVER_TIMESTAMPS;
9272         d->info8.architecture           = NULL;
9273         d->info8.driver_path            = talloc_strdup(d, "pscript5.dll");
9274         d->info8.data_file              = talloc_strdup(d, "cups6.ppd");
9275         d->info8.config_file            = talloc_strdup(d, "cupsui6.dll");
9276         d->info8.driver_date            = timeval_to_nttime(&t);
9277         d->local.environment            = talloc_strdup(d, "Windows NT x86");
9278         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9279         d->ex                           = true;
9280
9281         torture_assert(tctx,
9282                 test_add_driver_arg(tctx, p, d),
9283                 "");
9284
9285         unix_to_nt_time(&d->info8.driver_date, 1);
9286
9287         torture_assert(tctx,
9288                 test_add_driver_arg(tctx, p, d),
9289                 "");
9290
9291         return true;
9292 }
9293
9294 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9295 {
9296         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9297
9298         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9299                                                         "driver", &ndr_table_spoolss);
9300         torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9301         torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9302
9303         torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9304         torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9305
9306         torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9307
9308         torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9309
9310         torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9311
9312         return suite;
9313 }