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