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