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