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