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