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