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