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