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