s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[jlayton/samba.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
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 "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
41
42 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
43 #define TORTURE_PRINTER                 "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX              "torture_printer_ex"
46 #define TORTURE_DRIVER                  "torture_driver"
47 #define TORTURE_DRIVER_EX               "torture_driver_ex"
48
49 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
50 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
51 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
52 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
53 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
54 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
55
56 struct test_spoolss_context {
57         struct dcerpc_pipe *spoolss_pipe;
58
59         /* server environment */
60         const char *environment;
61
62         /* print server handle */
63         struct policy_handle server_handle;
64
65         /* for EnumPorts */
66         uint32_t port_count[3];
67         union spoolss_PortInfo *ports[3];
68
69         /* for EnumPrinterDrivers */
70         uint32_t driver_count[8];
71         union spoolss_DriverInfo *drivers[8];
72
73         /* for EnumMonitors */
74         uint32_t monitor_count[3];
75         union spoolss_MonitorInfo *monitors[3];
76
77         /* for EnumPrintProcessors */
78         uint32_t print_processor_count[2];
79         union spoolss_PrintProcessorInfo *print_processors[2];
80
81         /* for EnumPrinters */
82         uint32_t printer_count[6];
83         union spoolss_PrinterInfo *printers[6];
84 };
85
86 struct torture_driver_context {
87         struct {
88                 const char *driver_directory;
89                 const char *environment;
90         } local;
91         struct {
92                 const char *driver_directory;
93                 const char *environment;
94         } remote;
95         struct spoolss_AddDriverInfo8 info8;
96         bool ex;
97 };
98
99 struct torture_printer_context {
100         struct dcerpc_pipe *spoolss_pipe;
101         struct spoolss_SetPrinterInfo2 info2;
102         struct torture_driver_context driver;
103         bool ex;
104         bool wellknown;
105         bool added_driver;
106         bool have_driver;
107         struct spoolss_DeviceMode *devmode;
108         struct policy_handle handle;
109 };
110
111 static bool upload_printer_driver(struct torture_context *tctx,
112                                   const char *server_name,
113                                   struct torture_driver_context *d);
114 static bool remove_printer_driver(struct torture_context *tctx,
115                                   const char *server_name,
116                                   struct torture_driver_context *d);
117 static bool fillup_printserver_info(struct torture_context *tctx,
118                                     struct dcerpc_pipe *p,
119                                     struct torture_driver_context *d);
120 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
121                                                struct dcerpc_binding_handle *b,
122                                                const char *server_name,
123                                                struct spoolss_AddDriverInfo8 *r,
124                                                uint32_t flags,
125                                                bool ex);
126
127 #define COMPARE_STRING(tctx, c,r,e) \
128         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
129
130 /* not every compiler supports __typeof__() */
131 #if (__GNUC__ >= 3)
132 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
133         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
134                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
135         }\
136         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
137                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
138         }\
139 } while(0)
140 #else
141 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
142 #endif
143
144 #define COMPARE_UINT32(tctx, c, r, e) do {\
145         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
146         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
147 } while(0)
148
149 #define COMPARE_UINT64(tctx, c, r, e) do {\
150         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
151         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
152 } while(0)
153
154
155 #define COMPARE_NTTIME(tctx, c, r, e) do {\
156         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
157         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
159
160 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
161         int __i; \
162         if (!c.e && !r.e) { \
163                 break; \
164         } \
165         if (c.e && !r.e) { \
166                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
167         } \
168         if (!c.e && r.e) { \
169                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
170         } \
171         for (__i=0;c.e[__i] != NULL; __i++) { \
172                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
173         } \
174 } while(0)
175
176 #define CHECK_ALIGN(size, n) do {\
177         if (size % n) {\
178                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
179                         size, n, size + n - (size % n));\
180         }\
181 } while(0)
182
183 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
184
185 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
186         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
187         uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
188         uint32_t round_size = DO_ROUND(size, align);\
189         if (round_size != needed) {\
190                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
191                 CHECK_ALIGN(size, align);\
192         }\
193         }\
194 } while(0)
195
196 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
197         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198         uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
199         uint32_t round_size = DO_ROUND(size, align);\
200         if (round_size != needed) {\
201                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
202                 CHECK_ALIGN(size, align);\
203         }\
204         }\
205 } while(0)
206
207 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
208         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209         uint32_t size = ndr_size_##fn(info, level, 0);\
210         uint32_t round_size = DO_ROUND(size, align);\
211         if (round_size != needed) {\
212                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
213                 CHECK_ALIGN(size, align);\
214         }\
215         }\
216 } while(0)
217
218 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
219                                           const union spoolss_PrinterInfo *i,
220                                           uint32_t level,
221                                           union spoolss_SetPrinterInfo *s)
222 {
223         switch (level) {
224         case 0:
225                 s->info0                        = talloc(tctx, struct spoolss_SetPrinterInfo0);
226                 break;
227         case 2:
228                 s->info2                        = talloc(tctx, struct spoolss_SetPrinterInfo2);
229                 s->info2->servername            = i->info2.servername;
230                 s->info2->printername           = i->info2.printername;
231                 s->info2->sharename             = i->info2.sharename;
232                 s->info2->portname              = i->info2.portname;
233                 s->info2->drivername            = i->info2.drivername;
234                 s->info2->comment               = i->info2.comment;
235                 s->info2->location              = i->info2.location;
236                 s->info2->devmode_ptr           = 0;
237                 s->info2->sepfile               = i->info2.sepfile;
238                 s->info2->printprocessor        = i->info2.printprocessor;
239                 s->info2->datatype              = i->info2.datatype;
240                 s->info2->parameters            = i->info2.parameters;
241                 s->info2->secdesc_ptr           = 0;
242                 s->info2->attributes            = i->info2.attributes;
243                 s->info2->priority              = i->info2.priority;
244                 s->info2->defaultpriority       = i->info2.defaultpriority;
245                 s->info2->starttime             = i->info2.starttime;
246                 s->info2->untiltime             = i->info2.untiltime;
247                 s->info2->status                = i->info2.status;
248                 s->info2->cjobs                 = i->info2.cjobs;
249                 s->info2->averageppm            = i->info2.averageppm;
250                 break;
251         case 3:
252         case 4:
253         case 5:
254         case 6:
255         case 7:
256         case 8:
257         case 9:
258         default:
259                 return false;
260         }
261
262         return true;
263 }
264
265 static bool test_OpenPrinter_server(struct torture_context *tctx,
266                                     struct dcerpc_pipe *p,
267                                     struct policy_handle *server_handle)
268 {
269         NTSTATUS status;
270         struct spoolss_OpenPrinter op;
271         struct dcerpc_binding_handle *b = p->binding_handle;
272
273         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
274         op.in.datatype          = NULL;
275         op.in.devmode_ctr.devmode= NULL;
276         op.in.access_mask       = 0;
277         op.out.handle           = server_handle;
278
279         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
280
281         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
282         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
283         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
284
285         return true;
286 }
287
288 static bool test_EnumPorts(struct torture_context *tctx,
289                            void *private_data)
290 {
291         struct test_spoolss_context *ctx =
292                 talloc_get_type_abort(private_data, struct test_spoolss_context);
293         struct dcerpc_pipe *p = ctx->spoolss_pipe;
294         struct dcerpc_binding_handle *b = p->binding_handle;
295         NTSTATUS status;
296         struct spoolss_EnumPorts r;
297         uint16_t levels[] = { 1, 2 };
298         int i, j;
299
300         for (i=0;i<ARRAY_SIZE(levels);i++) {
301                 int level = levels[i];
302                 DATA_BLOB blob;
303                 uint32_t needed;
304                 uint32_t count;
305                 union spoolss_PortInfo *info;
306
307                 r.in.servername = "";
308                 r.in.level = level;
309                 r.in.buffer = NULL;
310                 r.in.offered = 0;
311                 r.out.needed = &needed;
312                 r.out.count = &count;
313                 r.out.info = &info;
314
315                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
316
317                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
318                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
319                 if (W_ERROR_IS_OK(r.out.result)) {
320                         /* TODO: do some more checks here */
321                         continue;
322                 }
323                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
324                         "EnumPorts unexpected return code");
325
326                 blob = data_blob_talloc_zero(ctx, needed);
327                 r.in.buffer = &blob;
328                 r.in.offered = needed;
329
330                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
331                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
332
333                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
334
335                 torture_assert(tctx, info, "EnumPorts returned no info");
336
337                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
338
339                 ctx->port_count[level]  = count;
340                 ctx->ports[level]       = info;
341         }
342
343         for (i=1;i<ARRAY_SIZE(levels);i++) {
344                 int level = levels[i];
345                 int old_level = levels[i-1];
346                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
347                         "EnumPorts invalid value");
348         }
349         /* if the array sizes are not the same we would maybe segfault in the following code */
350
351         for (i=0;i<ARRAY_SIZE(levels);i++) {
352                 int level = levels[i];
353                 for (j=0;j<ctx->port_count[level];j++) {
354                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
355                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
356                         switch (level) {
357                         case 1:
358                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
359                                 break;
360                         case 2:
361                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
362                                 break;
363                         }
364                 }
365         }
366
367         return true;
368 }
369
370 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
371                                             void *private_data)
372 {
373         struct test_spoolss_context *ctx =
374                 talloc_get_type_abort(private_data, struct test_spoolss_context);
375
376         NTSTATUS status;
377         struct dcerpc_pipe *p = ctx->spoolss_pipe;
378         struct dcerpc_binding_handle *b = p->binding_handle;
379         struct spoolss_GetPrintProcessorDirectory r;
380         struct {
381                 uint16_t level;
382                 const char *server;
383         } levels[] = {{
384                         .level  = 1,
385                         .server = NULL
386                 },{
387                         .level  = 1,
388                         .server = ""
389                 },{
390                         .level  = 78,
391                         .server = ""
392                 },{
393                         .level  = 1,
394                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
395                 },{
396                         .level  = 1024,
397                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
398                 }
399         };
400         int i;
401         uint32_t needed;
402
403         for (i=0;i<ARRAY_SIZE(levels);i++) {
404                 int level = levels[i].level;
405                 DATA_BLOB blob;
406
407                 r.in.server             = levels[i].server;
408                 r.in.environment        = ctx->environment;
409                 r.in.level              = level;
410                 r.in.buffer             = NULL;
411                 r.in.offered            = 0;
412                 r.out.needed            = &needed;
413
414                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
415
416                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
417                 torture_assert_ntstatus_ok(tctx, status,
418                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
419                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
420                         "GetPrintProcessorDirectory unexpected return code");
421
422                 blob = data_blob_talloc_zero(tctx, needed);
423                 r.in.buffer = &blob;
424                 r.in.offered = needed;
425
426                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
427                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
428
429                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
430
431                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
432         }
433
434         return true;
435 }
436
437
438 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
439                                            void *private_data)
440 {
441         struct test_spoolss_context *ctx =
442                 talloc_get_type_abort(private_data, struct test_spoolss_context);
443
444         NTSTATUS status;
445         struct dcerpc_pipe *p = ctx->spoolss_pipe;
446         struct dcerpc_binding_handle *b = p->binding_handle;
447         struct spoolss_GetPrinterDriverDirectory r;
448         struct {
449                 uint16_t level;
450                 const char *server;
451         } levels[] = {{
452                         .level  = 1,
453                         .server = NULL
454                 },{
455                         .level  = 1,
456                         .server = ""
457                 },{
458                         .level  = 78,
459                         .server = ""
460                 },{
461                         .level  = 1,
462                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
463                 },{
464                         .level  = 1024,
465                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
466                 }
467         };
468         int i;
469         uint32_t needed;
470
471         for (i=0;i<ARRAY_SIZE(levels);i++) {
472                 int level = levels[i].level;
473                 DATA_BLOB blob;
474
475                 r.in.server             = levels[i].server;
476                 r.in.environment        = ctx->environment;
477                 r.in.level              = level;
478                 r.in.buffer             = NULL;
479                 r.in.offered            = 0;
480                 r.out.needed            = &needed;
481
482                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
483
484                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
485                 torture_assert_ntstatus_ok(tctx, status,
486                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
487                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
488                         "GetPrinterDriverDirectory unexpected return code");
489
490                 blob = data_blob_talloc_zero(tctx, needed);
491                 r.in.buffer = &blob;
492                 r.in.offered = needed;
493
494                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
495                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
496
497                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
498
499                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
500         }
501
502         return true;
503 }
504
505 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
506                                          struct dcerpc_binding_handle *b,
507                                          const char *server_name,
508                                          const char *environment,
509                                          uint32_t level,
510                                          uint32_t *count_p,
511                                          union spoolss_DriverInfo **info_p)
512 {
513         struct spoolss_EnumPrinterDrivers r;
514         uint32_t needed;
515         uint32_t count;
516         union spoolss_DriverInfo *info;
517
518         r.in.server             = server_name;
519         r.in.environment        = environment;
520         r.in.level              = level;
521         r.in.buffer             = NULL;
522         r.in.offered            = 0;
523         r.out.needed            = &needed;
524         r.out.count             = &count;
525         r.out.info              = &info;
526
527         torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
528                 r.in.environment, r.in.level);
529
530         torture_assert_ntstatus_ok(tctx,
531                 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
532                 "EnumPrinterDrivers failed");
533         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
534                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
535                 r.in.buffer = &blob;
536                 r.in.offered = needed;
537
538                 torture_assert_ntstatus_ok(tctx,
539                         dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
540                         "EnumPrinterDrivers failed");
541         }
542
543         torture_assert_werr_ok(tctx, r.out.result,
544                 "EnumPrinterDrivers failed");
545
546         if (count_p) {
547                 *count_p = count;
548         }
549         if (info_p) {
550                 *info_p = info;
551         }
552
553         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
554
555         return true;
556
557 }
558
559 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
560                                             struct dcerpc_binding_handle *b,
561                                             const char *server_name,
562                                             const char *environment,
563                                             uint32_t level,
564                                             const char *driver_name)
565 {
566         uint32_t count;
567         union spoolss_DriverInfo *info;
568         int i;
569
570         torture_assert(tctx,
571                 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
572                 "failed to enumerate printer drivers");
573
574         for (i=0; i < count; i++) {
575                 const char *driver_name_ret;
576                 switch (level) {
577                 case 1:
578                         driver_name_ret = info[i].info1.driver_name;
579                         break;
580                 case 2:
581                         driver_name_ret = info[i].info2.driver_name;
582                         break;
583                 case 3:
584                         driver_name_ret = info[i].info3.driver_name;
585                         break;
586                 case 4:
587                         driver_name_ret = info[i].info4.driver_name;
588                         break;
589                 case 5:
590                         driver_name_ret = info[i].info5.driver_name;
591                         break;
592                 case 6:
593                         driver_name_ret = info[i].info6.driver_name;
594                         break;
595                 case 7:
596                         driver_name_ret = info[i].info7.driver_name;
597                         break;
598                 case 8:
599                         driver_name_ret = info[i].info8.driver_name;
600                         break;
601                 default:
602                         break;
603                 }
604                 if (strequal(driver_name, driver_name_ret)) {
605                         return true;
606                 }
607         }
608
609         return false;
610 }
611
612 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
613                                     void *private_data)
614 {
615         struct test_spoolss_context *ctx =
616                 talloc_get_type_abort(private_data, struct test_spoolss_context);
617         struct dcerpc_pipe *p = ctx->spoolss_pipe;
618         struct dcerpc_binding_handle *b = p->binding_handle;
619         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
620         int i, j, a;
621
622         /* FIXME: gd, come back and fix "" as server, and handle
623          * priority of returned error codes in torture test and samba 3
624          * server */
625         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
626         const char *environments[2];
627
628         environments[0] = SPOOLSS_ARCHITECTURE_ALL;
629         environments[1] = ctx->environment;
630
631         for (a=0;a<ARRAY_SIZE(environments);a++) {
632
633         for (i=0;i<ARRAY_SIZE(levels);i++) {
634                 int level = levels[i];
635                 uint32_t count;
636                 union spoolss_DriverInfo *info;
637
638                 torture_assert(tctx,
639                         test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
640                         "failed to enumerate drivers");
641
642                 ctx->driver_count[level]        = count;
643                 ctx->drivers[level]             = info;
644         }
645
646         for (i=1;i<ARRAY_SIZE(levels);i++) {
647                 int level = levels[i];
648                 int old_level = levels[i-1];
649
650                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
651                         "EnumPrinterDrivers invalid value");
652         }
653
654         for (i=0;i<ARRAY_SIZE(levels);i++) {
655                 int level = levels[i];
656
657                 for (j=0;j<ctx->driver_count[level];j++) {
658                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
659                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
660
661                         switch (level) {
662                         case 1:
663                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
664                                 break;
665                         case 2:
666                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
667                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
668                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
669                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
670                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
671                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
672                                 break;
673                         case 3:
674                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
675                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
676                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
677                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
678                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
679                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
680                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
681                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
682                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
683                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
684                                 break;
685                         case 4:
686                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
687                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
688                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
689                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
690                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
691                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
692                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
693                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
694                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
695                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
696                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
697                                 break;
698                         case 5:
699                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
700                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
701                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
702                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
703                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
704                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
705                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
706                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
707                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
708                                 break;
709                         case 6:
710                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
711                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
712                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
713                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
714                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
715                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
716                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
717                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
718                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
719                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
720                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
721                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
722                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
723                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
724                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
725                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
726                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
727                                 break;
728                         case 8:
729                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
730                                 break;
731                         }
732                 }
733         }
734         }
735
736         return true;
737 }
738
739 static bool test_EnumMonitors(struct torture_context *tctx,
740                               void *private_data)
741 {
742         struct test_spoolss_context *ctx =
743                 talloc_get_type_abort(private_data, struct test_spoolss_context);
744         struct dcerpc_pipe *p = ctx->spoolss_pipe;
745         struct dcerpc_binding_handle *b = p->binding_handle;
746         NTSTATUS status;
747         struct spoolss_EnumMonitors r;
748         uint16_t levels[] = { 1, 2 };
749         int i, j;
750
751         for (i=0;i<ARRAY_SIZE(levels);i++) {
752                 int level = levels[i];
753                 DATA_BLOB blob;
754                 uint32_t needed;
755                 uint32_t count;
756                 union spoolss_MonitorInfo *info;
757
758                 r.in.servername = "";
759                 r.in.level = level;
760                 r.in.buffer = NULL;
761                 r.in.offered = 0;
762                 r.out.needed = &needed;
763                 r.out.count = &count;
764                 r.out.info = &info;
765
766                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
767
768                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
769                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
770                 if (W_ERROR_IS_OK(r.out.result)) {
771                         /* TODO: do some more checks here */
772                         continue;
773                 }
774                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
775                         "EnumMonitors failed");
776
777                 blob = data_blob_talloc_zero(ctx, needed);
778                 r.in.buffer = &blob;
779                 r.in.offered = needed;
780
781                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
782                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
783
784                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
785
786                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
787
788                 ctx->monitor_count[level]       = count;
789                 ctx->monitors[level]            = info;
790         }
791
792         for (i=1;i<ARRAY_SIZE(levels);i++) {
793                 int level = levels[i];
794                 int old_level = levels[i-1];
795                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
796                                          "EnumMonitors invalid value");
797         }
798
799         for (i=0;i<ARRAY_SIZE(levels);i++) {
800                 int level = levels[i];
801                 for (j=0;j<ctx->monitor_count[level];j++) {
802                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
803                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
804                         switch (level) {
805                         case 1:
806                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
807                                 break;
808                         case 2:
809                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
810                                 break;
811                         }
812                 }
813         }
814
815         return true;
816 }
817
818 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
819                                            struct dcerpc_binding_handle *b,
820                                            const char *environment,
821                                            uint32_t level,
822                                            uint32_t *count_p,
823                                            union spoolss_PrintProcessorInfo **info_p)
824 {
825         struct spoolss_EnumPrintProcessors r;
826         DATA_BLOB blob;
827         uint32_t needed;
828         uint32_t count;
829         union spoolss_PrintProcessorInfo *info;
830
831         r.in.servername = "";
832         r.in.environment = environment;
833         r.in.level = level;
834         r.in.buffer = NULL;
835         r.in.offered = 0;
836         r.out.needed = &needed;
837         r.out.count = &count;
838         r.out.info = &info;
839
840         torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
841
842         torture_assert_ntstatus_ok(tctx,
843                 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
844                 "EnumPrintProcessors failed");
845         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
846                 blob = data_blob_talloc_zero(tctx, needed);
847                 r.in.buffer = &blob;
848                 r.in.offered = needed;
849                 torture_assert_ntstatus_ok(tctx,
850                         dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
851                         "EnumPrintProcessors failed");
852         }
853         torture_assert_werr_ok(tctx, r.out.result,
854                 "EnumPrintProcessors failed");
855
856         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
857
858         if (count_p) {
859                 *count_p = count;
860         }
861         if (info_p) {
862                 *info_p = info;
863         }
864
865         return true;
866 }
867
868 static bool test_EnumPrintProcessors(struct torture_context *tctx,
869                                      void *private_data)
870 {
871         struct test_spoolss_context *ctx =
872                 talloc_get_type_abort(private_data, struct test_spoolss_context);
873
874         uint16_t levels[] = { 1 };
875         int i, j;
876         struct dcerpc_pipe *p = ctx->spoolss_pipe;
877         struct dcerpc_binding_handle *b = p->binding_handle;
878
879         for (i=0;i<ARRAY_SIZE(levels);i++) {
880                 int level = levels[i];
881                 union spoolss_PrintProcessorInfo *info;
882                 uint32_t count;
883
884                 torture_assert(tctx,
885                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, level, &count, &info),
886                         "test_EnumPrintProcessors_level failed");
887
888                 ctx->print_processor_count[level]       = count;
889                 ctx->print_processors[level]            = info;
890         }
891
892         for (i=1;i<ARRAY_SIZE(levels);i++) {
893                 int level = levels[i];
894                 int old_level = levels[i-1];
895                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
896                         "EnumPrintProcessors failed");
897         }
898
899         for (i=0;i<ARRAY_SIZE(levels);i++) {
900                 int level = levels[i];
901                 for (j=0;j<ctx->print_processor_count[level];j++) {
902 #if 0
903                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
904                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
905 #endif
906                         switch (level) {
907                         case 1:
908                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
909                                 break;
910                         }
911                 }
912         }
913
914         return true;
915 }
916
917 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
918                                         void *private_data)
919 {
920         struct test_spoolss_context *ctx =
921                 talloc_get_type_abort(private_data, struct test_spoolss_context);
922
923         NTSTATUS status;
924         struct spoolss_EnumPrintProcDataTypes r;
925         uint16_t levels[] = { 1 };
926         int i;
927         struct dcerpc_pipe *p = ctx->spoolss_pipe;
928         struct dcerpc_binding_handle *b = p->binding_handle;
929
930         for (i=0;i<ARRAY_SIZE(levels);i++) {
931                 int level = levels[i];
932                 DATA_BLOB blob;
933                 uint32_t needed;
934                 uint32_t count;
935                 union spoolss_PrintProcDataTypesInfo *info;
936
937                 r.in.servername = "";
938                 r.in.print_processor_name = "winprint";
939                 r.in.level = level;
940                 r.in.buffer = NULL;
941                 r.in.offered = 0;
942                 r.out.needed = &needed;
943                 r.out.count = &count;
944                 r.out.info = &info;
945
946                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
947
948                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
949                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
950                 if (W_ERROR_IS_OK(r.out.result)) {
951                         /* TODO: do some more checks here */
952                         continue;
953                 }
954                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
955                         "EnumPrintProcDataTypes unexpected return code");
956
957                 blob = data_blob_talloc_zero(tctx, needed);
958                 r.in.buffer = &blob;
959                 r.in.offered = needed;
960
961                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
962                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
963
964                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
965
966                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, needed, 4);
967
968         }
969
970         return true;
971 }
972
973
974 static bool test_EnumPrinters(struct torture_context *tctx,
975                               void *private_data)
976 {
977         struct test_spoolss_context *ctx =
978                 talloc_get_type_abort(private_data, struct test_spoolss_context);
979         struct dcerpc_pipe *p = ctx->spoolss_pipe;
980         struct dcerpc_binding_handle *b = p->binding_handle;
981         struct spoolss_EnumPrinters r;
982         NTSTATUS status;
983         uint16_t levels[] = { 0, 1, 2, 4, 5 };
984         int i, j;
985
986         for (i=0;i<ARRAY_SIZE(levels);i++) {
987                 int level = levels[i];
988                 DATA_BLOB blob;
989                 uint32_t needed;
990                 uint32_t count;
991                 union spoolss_PrinterInfo *info;
992
993                 r.in.flags      = PRINTER_ENUM_LOCAL;
994                 r.in.server     = "";
995                 r.in.level      = level;
996                 r.in.buffer     = NULL;
997                 r.in.offered    = 0;
998                 r.out.needed    = &needed;
999                 r.out.count     = &count;
1000                 r.out.info      = &info;
1001
1002                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1003
1004                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1005                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1006                 if (W_ERROR_IS_OK(r.out.result)) {
1007                         /* TODO: do some more checks here */
1008                         continue;
1009                 }
1010                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1011                         "EnumPrinters unexpected return code");
1012
1013                 blob = data_blob_talloc_zero(ctx, needed);
1014                 r.in.buffer = &blob;
1015                 r.in.offered = needed;
1016
1017                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1018                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1019
1020                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1021
1022                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1023
1024                 ctx->printer_count[level]       = count;
1025                 ctx->printers[level]            = info;
1026         }
1027
1028         for (i=1;i<ARRAY_SIZE(levels);i++) {
1029                 int level = levels[i];
1030                 int old_level = levels[i-1];
1031                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1032                                          "EnumPrinters invalid value");
1033         }
1034
1035         for (i=0;i<ARRAY_SIZE(levels);i++) {
1036                 int level = levels[i];
1037                 for (j=0;j<ctx->printer_count[level];j++) {
1038                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1039                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1040                         switch (level) {
1041                         case 0:
1042                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1043                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1044                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1045                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1046                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1047                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1048                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1049                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1050                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1051                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1052                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1053                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1054                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1055                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1056                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1057                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1058                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1059                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1060                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1061                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1062                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1063                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1064                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1065                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1066                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1067                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1068                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1069                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1070                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1071                                 break;
1072                         case 1:
1073                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1074                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1075                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1076                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1077                                 break;
1078                         case 2:
1079                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
1080                                 break;
1081                         case 4:
1082                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1083                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1084                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1085                                 break;
1086                         case 5:
1087                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1088                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1089                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1090                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1091                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1092                                 break;
1093                         }
1094                 }
1095         }
1096
1097         /* TODO:
1098          *      - verify that the port of a printer was in the list returned by EnumPorts
1099          */
1100
1101         return true;
1102 }
1103
1104 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1105                                    struct dcerpc_binding_handle *b,
1106                                    struct policy_handle *handle,
1107                                    const char *driver_name,
1108                                    const char *environment);
1109
1110 bool test_GetPrinter_level(struct torture_context *tctx,
1111                            struct dcerpc_binding_handle *b,
1112                            struct policy_handle *handle,
1113                            uint32_t level,
1114                            union spoolss_PrinterInfo *info)
1115 {
1116         struct spoolss_GetPrinter r;
1117         uint32_t needed;
1118
1119         r.in.handle = handle;
1120         r.in.level = level;
1121         r.in.buffer = NULL;
1122         r.in.offered = 0;
1123         r.out.needed = &needed;
1124
1125         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1126
1127         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1128                 "GetPrinter failed");
1129
1130         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1131                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1132                 r.in.buffer = &blob;
1133                 r.in.offered = needed;
1134
1135                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1136                         "GetPrinter failed");
1137         }
1138
1139         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1140
1141         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1142
1143         if (info && r.out.info) {
1144                 *info = *r.out.info;
1145         }
1146
1147         return true;
1148 }
1149
1150
1151 static bool test_GetPrinter(struct torture_context *tctx,
1152                             struct dcerpc_binding_handle *b,
1153                             struct policy_handle *handle,
1154                             const char *environment)
1155 {
1156         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1157         int i;
1158
1159         for (i=0;i<ARRAY_SIZE(levels);i++) {
1160
1161                 union spoolss_PrinterInfo info;
1162
1163                 ZERO_STRUCT(info);
1164
1165                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1166                         "failed to call GetPrinter");
1167
1168                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1169                         torture_assert(tctx,
1170                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1171                                 "failed to call test_GetPrinterDriver2");
1172                 }
1173         }
1174
1175         return true;
1176 }
1177
1178 static bool test_SetPrinter(struct torture_context *tctx,
1179                             struct dcerpc_binding_handle *b,
1180                             struct policy_handle *handle,
1181                             struct spoolss_SetPrinterInfoCtr *info_ctr,
1182                             struct spoolss_DevmodeContainer *devmode_ctr,
1183                             struct sec_desc_buf *secdesc_ctr,
1184                             enum spoolss_PrinterControl command)
1185 {
1186         struct spoolss_SetPrinter r;
1187
1188         r.in.handle = handle;
1189         r.in.info_ctr = info_ctr;
1190         r.in.devmode_ctr = devmode_ctr;
1191         r.in.secdesc_ctr = secdesc_ctr;
1192         r.in.command = command;
1193
1194         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1195
1196         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1197                 "failed to call SetPrinter");
1198         torture_assert_werr_ok(tctx, r.out.result,
1199                 "failed to call SetPrinter");
1200
1201         return true;
1202 }
1203
1204 static bool test_SetPrinter_errors(struct torture_context *tctx,
1205                                    struct dcerpc_binding_handle *b,
1206                                    struct policy_handle *handle)
1207 {
1208         struct spoolss_SetPrinter r;
1209         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1210         int i;
1211
1212         struct spoolss_SetPrinterInfoCtr info_ctr;
1213         struct spoolss_DevmodeContainer devmode_ctr;
1214         struct sec_desc_buf secdesc_ctr;
1215
1216         info_ctr.level = 0;
1217         info_ctr.info.info0 = NULL;
1218
1219         ZERO_STRUCT(devmode_ctr);
1220         ZERO_STRUCT(secdesc_ctr);
1221
1222         r.in.handle = handle;
1223         r.in.info_ctr = &info_ctr;
1224         r.in.devmode_ctr = &devmode_ctr;
1225         r.in.secdesc_ctr = &secdesc_ctr;
1226         r.in.command = 0;
1227
1228         torture_comment(tctx, "Testing SetPrinter all zero\n");
1229
1230         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1231                 "failed to call SetPrinter");
1232         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1233                 "failed to call SetPrinter");
1234
1235  again:
1236         for (i=0; i < ARRAY_SIZE(levels); i++) {
1237
1238                 struct spoolss_SetPrinterInfo0 info0;
1239                 struct spoolss_SetPrinterInfo1 info1;
1240                 struct spoolss_SetPrinterInfo2 info2;
1241                 struct spoolss_SetPrinterInfo3 info3;
1242                 struct spoolss_SetPrinterInfo4 info4;
1243                 struct spoolss_SetPrinterInfo5 info5;
1244                 struct spoolss_SetPrinterInfo6 info6;
1245                 struct spoolss_SetPrinterInfo7 info7;
1246                 struct spoolss_SetPrinterInfo8 info8;
1247                 struct spoolss_SetPrinterInfo9 info9;
1248
1249
1250                 info_ctr.level = levels[i];
1251                 switch (levels[i]) {
1252                 case 0:
1253                         ZERO_STRUCT(info0);
1254                         info_ctr.info.info0 = &info0;
1255                         break;
1256                 case 1:
1257                         ZERO_STRUCT(info1);
1258                         info_ctr.info.info1 = &info1;
1259                         break;
1260                 case 2:
1261                         ZERO_STRUCT(info2);
1262                         info_ctr.info.info2 = &info2;
1263                         break;
1264                 case 3:
1265                         ZERO_STRUCT(info3);
1266                         info_ctr.info.info3 = &info3;
1267                         break;
1268                 case 4:
1269                         ZERO_STRUCT(info4);
1270                         info_ctr.info.info4 = &info4;
1271                         break;
1272                 case 5:
1273                         ZERO_STRUCT(info5);
1274                         info_ctr.info.info5 = &info5;
1275                         break;
1276                 case 6:
1277                         ZERO_STRUCT(info6);
1278                         info_ctr.info.info6 = &info6;
1279                         break;
1280                 case 7:
1281                         ZERO_STRUCT(info7);
1282                         info_ctr.info.info7 = &info7;
1283                         break;
1284                 case 8:
1285                         ZERO_STRUCT(info8);
1286                         info_ctr.info.info8 = &info8;
1287                         break;
1288                 case 9:
1289                         ZERO_STRUCT(info9);
1290                         info_ctr.info.info9 = &info9;
1291                         break;
1292                 }
1293
1294                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1295                         info_ctr.level, r.in.command);
1296
1297                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1298                         "failed to call SetPrinter");
1299
1300                 switch (r.in.command) {
1301                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1302                         /* is ignored for all levels other then 0 */
1303                         if (info_ctr.level > 0) {
1304                                 /* ignored then */
1305                                 break;
1306                         }
1307                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1308                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1309                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1310                         if (info_ctr.level > 0) {
1311                                 /* is invalid for all levels other then 0 */
1312                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1313                                         "unexpected error code returned");
1314                                 continue;
1315                         } else {
1316                                 torture_assert_werr_ok(tctx, r.out.result,
1317                                         "failed to call SetPrinter with non 0 command");
1318                                 continue;
1319                         }
1320                         break;
1321
1322                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1323                         /* FIXME: gd needs further investigation */
1324                 default:
1325                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1326                                 "unexpected error code returned");
1327                         continue;
1328                 }
1329
1330                 switch (info_ctr.level) {
1331                 case 1:
1332                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1333                                 "unexpected error code returned");
1334                         break;
1335                 case 2:
1336                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1337                                 "unexpected error code returned");
1338                         break;
1339                 case 3:
1340                 case 4:
1341                 case 5:
1342                 case 7:
1343                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1344                                 "unexpected error code returned");
1345                         break;
1346                 case 9:
1347                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1348                                 "unexpected error code returned");
1349                         break;
1350                 default:
1351                         torture_assert_werr_ok(tctx, r.out.result,
1352                                 "failed to call SetPrinter");
1353                         break;
1354                 }
1355         }
1356
1357         if (r.in.command < 5) {
1358                 r.in.command++;
1359                 goto again;
1360         }
1361
1362         return true;
1363 }
1364
1365 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1366 {
1367         if ((r->level == 2) && (r->info.info2)) {
1368                 r->info.info2->secdesc_ptr = 0;
1369                 r->info.info2->devmode_ptr = 0;
1370         }
1371 }
1372
1373 static bool test_PrinterInfo(struct torture_context *tctx,
1374                              struct dcerpc_binding_handle *b,
1375                              struct policy_handle *handle)
1376 {
1377         NTSTATUS status;
1378         struct spoolss_SetPrinter s;
1379         struct spoolss_GetPrinter q;
1380         struct spoolss_GetPrinter q0;
1381         struct spoolss_SetPrinterInfoCtr info_ctr;
1382         union spoolss_PrinterInfo info;
1383         struct spoolss_DevmodeContainer devmode_ctr;
1384         struct sec_desc_buf secdesc_ctr;
1385         uint32_t needed;
1386         bool ret = true;
1387         int i;
1388
1389         torture_skip(tctx, "Printer Info test is currently broken, skipping");
1390
1391         uint32_t status_list[] = {
1392                 /* these do not stick
1393                 PRINTER_STATUS_PAUSED,
1394                 PRINTER_STATUS_ERROR,
1395                 PRINTER_STATUS_PENDING_DELETION, */
1396                 PRINTER_STATUS_PAPER_JAM,
1397                 PRINTER_STATUS_PAPER_OUT,
1398                 PRINTER_STATUS_MANUAL_FEED,
1399                 PRINTER_STATUS_PAPER_PROBLEM,
1400                 PRINTER_STATUS_OFFLINE,
1401                 PRINTER_STATUS_IO_ACTIVE,
1402                 PRINTER_STATUS_BUSY,
1403                 PRINTER_STATUS_PRINTING,
1404                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1405                 PRINTER_STATUS_NOT_AVAILABLE,
1406                 PRINTER_STATUS_WAITING,
1407                 PRINTER_STATUS_PROCESSING,
1408                 PRINTER_STATUS_INITIALIZING,
1409                 PRINTER_STATUS_WARMING_UP,
1410                 PRINTER_STATUS_TONER_LOW,
1411                 PRINTER_STATUS_NO_TONER,
1412                 PRINTER_STATUS_PAGE_PUNT,
1413                 PRINTER_STATUS_USER_INTERVENTION,
1414                 PRINTER_STATUS_OUT_OF_MEMORY,
1415                 PRINTER_STATUS_DOOR_OPEN,
1416                 PRINTER_STATUS_SERVER_UNKNOWN,
1417                 PRINTER_STATUS_POWER_SAVE,
1418                 /* these do not stick
1419                 0x02000000,
1420                 0x04000000,
1421                 0x08000000,
1422                 0x10000000,
1423                 0x20000000,
1424                 0x40000000,
1425                 0x80000000 */
1426         };
1427         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1428         uint32_t attribute_list[] = {
1429                 PRINTER_ATTRIBUTE_QUEUED,
1430                 /* fails with WERR_INVALID_DATATYPE:
1431                 PRINTER_ATTRIBUTE_DIRECT, */
1432                 /* does not stick
1433                 PRINTER_ATTRIBUTE_DEFAULT, */
1434                 PRINTER_ATTRIBUTE_SHARED,
1435                 /* does not stick
1436                 PRINTER_ATTRIBUTE_NETWORK, */
1437                 PRINTER_ATTRIBUTE_HIDDEN,
1438                 PRINTER_ATTRIBUTE_LOCAL,
1439                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1440                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1441                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1442                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1443                 /* does not stick
1444                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1445                 /* fails with WERR_INVALID_DATATYPE:
1446                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1447                 /* these do not stick
1448                 PRINTER_ATTRIBUTE_PUBLISHED,
1449                 PRINTER_ATTRIBUTE_FAX,
1450                 PRINTER_ATTRIBUTE_TS,
1451                 0x00010000,
1452                 0x00020000,
1453                 0x00040000,
1454                 0x00080000,
1455                 0x00100000,
1456                 0x00200000,
1457                 0x00400000,
1458                 0x00800000,
1459                 0x01000000,
1460                 0x02000000,
1461                 0x04000000,
1462                 0x08000000,
1463                 0x10000000,
1464                 0x20000000,
1465                 0x40000000,
1466                 0x80000000 */
1467         };
1468
1469         ZERO_STRUCT(devmode_ctr);
1470         ZERO_STRUCT(secdesc_ctr);
1471
1472         s.in.handle = handle;
1473         s.in.command = 0;
1474         s.in.info_ctr = &info_ctr;
1475         s.in.devmode_ctr = &devmode_ctr;
1476         s.in.secdesc_ctr = &secdesc_ctr;
1477
1478         q.in.handle = handle;
1479         q.out.info = &info;
1480         q0 = q;
1481
1482 #define TESTGETCALL(call, r) \
1483                 r.in.buffer = NULL; \
1484                 r.in.offered = 0;\
1485                 r.out.needed = &needed; \
1486                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1487                 if (!NT_STATUS_IS_OK(status)) { \
1488                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1489                                r.in.level, nt_errstr(status), __location__); \
1490                         ret = false; \
1491                         break; \
1492                 }\
1493                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1494                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1495                         r.in.buffer = &blob; \
1496                         r.in.offered = needed; \
1497                 }\
1498                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1499                 if (!NT_STATUS_IS_OK(status)) { \
1500                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1501                                r.in.level, nt_errstr(status), __location__); \
1502                         ret = false; \
1503                         break; \
1504                 } \
1505                 if (!W_ERROR_IS_OK(r.out.result)) { \
1506                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1507                                r.in.level, win_errstr(r.out.result), __location__); \
1508                         ret = false; \
1509                         break; \
1510                 }
1511
1512
1513 #define TESTSETCALL_EXP(call, r, err) \
1514                 clear_info2(&info_ctr);\
1515                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1516                 if (!NT_STATUS_IS_OK(status)) { \
1517                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1518                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1519                         ret = false; \
1520                         break; \
1521                 } \
1522                 if (!W_ERROR_IS_OK(err)) { \
1523                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1524                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1525                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1526                                 ret = false; \
1527                         } \
1528                         break; \
1529                 } \
1530                 if (!W_ERROR_IS_OK(r.out.result)) { \
1531                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1532                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1533                         ret = false; \
1534                         break; \
1535                 }
1536
1537 #define TESTSETCALL(call, r) \
1538         TESTSETCALL_EXP(call, r, WERR_OK)
1539
1540 #define STRING_EQUAL(s1, s2, field) \
1541                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1542                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1543                                #field, s2, __location__); \
1544                         ret = false; \
1545                         break; \
1546                 }
1547
1548 #define MEM_EQUAL(s1, s2, length, field) \
1549                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1550                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1551                                #field, (const char *)s2, __location__); \
1552                         ret = false; \
1553                         break; \
1554                 }
1555
1556 #define INT_EQUAL(i1, i2, field) \
1557                 if (i1 != i2) { \
1558                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1559                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1560                         ret = false; \
1561                         break; \
1562                 }
1563
1564 #define SD_EQUAL(sd1, sd2, field) \
1565                 if (!security_descriptor_equal(sd1, sd2)) { \
1566                         torture_comment(tctx, "Failed to set %s (%s)\n", \
1567                                #field, __location__); \
1568                         ret = false; \
1569                         break; \
1570                 }
1571
1572 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1573                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1574                 q.in.level = lvl1; \
1575                 TESTGETCALL(GetPrinter, q) \
1576                 info_ctr.level = lvl1; \
1577                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1578                 info_ctr.info.info ## lvl1->field1 = value;\
1579                 TESTSETCALL_EXP(SetPrinter, s, err) \
1580                 info_ctr.info.info ## lvl1->field1 = ""; \
1581                 TESTGETCALL(GetPrinter, q) \
1582                 info_ctr.info.info ## lvl1->field1 = value; \
1583                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1584                 q.in.level = lvl2; \
1585                 TESTGETCALL(GetPrinter, q) \
1586                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1587                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1588         } while (0)
1589
1590 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1591         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1592         } while (0);
1593
1594 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1595                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1596                 q.in.level = lvl1; \
1597                 TESTGETCALL(GetPrinter, q) \
1598                 info_ctr.level = lvl1; \
1599                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1600                 info_ctr.info.info ## lvl1->field1 = value; \
1601                 TESTSETCALL(SetPrinter, s) \
1602                 info_ctr.info.info ## lvl1->field1 = 0; \
1603                 TESTGETCALL(GetPrinter, q) \
1604                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1605                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1606                 q.in.level = lvl2; \
1607                 TESTGETCALL(GetPrinter, q) \
1608                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1609                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1610         } while (0)
1611
1612 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1613         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1614         } while (0)
1615
1616         q0.in.level = 0;
1617         do { TESTGETCALL(GetPrinter, q0) } while (0);
1618
1619         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1620         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1621
1622         /* level 0 printername does not stick */
1623 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1624         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1625         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1626         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1627         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1628 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1629         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1630         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1631         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1632         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1633 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1634         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1635         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1636         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1637         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1638
1639         /* servername can be set but does not stick
1640         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1641         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1642         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1643         */
1644
1645         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1646         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1647         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1648         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1649         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1650
1651         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1652         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1653         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1654         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1655         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1656         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1657         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1658         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1659         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1660         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1661
1662         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1663 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1664                         attribute_list[i],
1665                         (attribute_list[i] | default_attribute)
1666                         ); */
1667                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1668                         attribute_list[i],
1669                         (attribute_list[i] | default_attribute)
1670                         );
1671                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1672                         attribute_list[i],
1673                         (attribute_list[i] | default_attribute)
1674                         );
1675                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1676                         attribute_list[i],
1677                         (attribute_list[i] | default_attribute)
1678                         );
1679 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1680                         attribute_list[i],
1681                         (attribute_list[i] | default_attribute)
1682                         ); */
1683                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1684                         attribute_list[i],
1685                         (attribute_list[i] | default_attribute)
1686                         );
1687                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1688                         attribute_list[i],
1689                         (attribute_list[i] | default_attribute)
1690                         );
1691                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1692                         attribute_list[i],
1693                         (attribute_list[i] | default_attribute)
1694                         );
1695 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1696                         attribute_list[i],
1697                         (attribute_list[i] | default_attribute)
1698                         ); */
1699                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1700                         attribute_list[i],
1701                         (attribute_list[i] | default_attribute)
1702                         );
1703                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1704                         attribute_list[i],
1705                         (attribute_list[i] | default_attribute)
1706                         );
1707                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1708                         attribute_list[i],
1709                         (attribute_list[i] | default_attribute)
1710                         );
1711         }
1712
1713         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1714                 /* level 2 sets do not stick
1715                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1716                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1717                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1718                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1719                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1720                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1721         }
1722
1723         /* priorities need to be between 0 and 99
1724            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1725         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1726         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1727         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1728         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1729         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1730         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1731         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1732         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1733
1734         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1735         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1736
1737         /* does not stick
1738         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1739         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1740
1741         /* does not stick
1742         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1743         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1744
1745         /* FIXME: gd also test devmode and secdesc behavior */
1746
1747         {
1748                 /* verify composition of level 1 description field */
1749                 const char *description;
1750                 const char *tmp;
1751
1752                 q0.in.level = 1;
1753                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1754
1755                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1756
1757                 q0.in.level = 2;
1758                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1759
1760                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1761                         q0.out.info->info2.printername,
1762                         q0.out.info->info2.drivername,
1763                         q0.out.info->info2.location);
1764
1765                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1766         }
1767
1768         return ret;
1769 }
1770
1771 static bool test_security_descriptor_equal(struct torture_context *tctx,
1772                                            const struct security_descriptor *sd1,
1773                                            const struct security_descriptor *sd2)
1774 {
1775         if (sd1 == sd2) {
1776                 return true;
1777         }
1778
1779         if (!sd1 || !sd2) {
1780                 torture_comment(tctx, "%s\n", __location__);
1781                 return false;
1782         }
1783
1784         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1785         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1786
1787         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1788         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1789
1790         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1791                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1792                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1793                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1794                 return false;
1795         }
1796         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1797                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1798                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1799                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1800                 return false;
1801         }
1802
1803         return true;
1804 }
1805
1806 static bool test_sd_set_level(struct torture_context *tctx,
1807                               struct dcerpc_binding_handle *b,
1808                               struct policy_handle *handle,
1809                               uint32_t level,
1810                               struct security_descriptor *sd)
1811 {
1812         struct spoolss_SetPrinterInfoCtr info_ctr;
1813         struct spoolss_DevmodeContainer devmode_ctr;
1814         struct sec_desc_buf secdesc_ctr;
1815         union spoolss_SetPrinterInfo sinfo;
1816
1817         ZERO_STRUCT(devmode_ctr);
1818         ZERO_STRUCT(secdesc_ctr);
1819
1820         switch (level) {
1821         case 2: {
1822                 union spoolss_PrinterInfo info;
1823                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1824                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1825
1826                 info_ctr.level = 2;
1827                 info_ctr.info = sinfo;
1828
1829                 break;
1830         }
1831         case 3: {
1832                 struct spoolss_SetPrinterInfo3 info3;
1833
1834                 info3.sec_desc_ptr = 0;
1835
1836                 info_ctr.level = 3;
1837                 info_ctr.info.info3 = &info3;
1838
1839                 break;
1840         }
1841         default:
1842                 return false;
1843         }
1844
1845         secdesc_ctr.sd = sd;
1846
1847         torture_assert(tctx,
1848                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1849
1850         return true;
1851 }
1852
1853 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1854                                  struct dcerpc_binding_handle *b,
1855                                  struct policy_handle *handle)
1856 {
1857         union spoolss_PrinterInfo info;
1858         struct security_descriptor *sd1, *sd2;
1859         int i;
1860
1861         /* just compare level 2 and level 3 */
1862
1863         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1864
1865         sd1 = info.info2.secdesc;
1866
1867         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1868
1869         sd2 = info.info3.secdesc;
1870
1871         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1872                 "SD level 2 != SD level 3");
1873
1874
1875         /* query level 2, set level 2, query level 2 */
1876
1877         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1878
1879         sd1 = info.info2.secdesc;
1880
1881         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1882
1883         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1884
1885         sd2 = info.info2.secdesc;
1886         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1887                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1888                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1889         }
1890
1891         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1892                 "SD level 2 != SD level 2 after SD has been set via level 2");
1893
1894
1895         /* query level 2, set level 3, query level 2 */
1896
1897         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1898
1899         sd1 = info.info2.secdesc;
1900
1901         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1902
1903         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1904
1905         sd2 = info.info2.secdesc;
1906
1907         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1908                 "SD level 2 != SD level 2 after SD has been set via level 3");
1909
1910         /* set modified sd level 3, query level 2 */
1911
1912         for (i=0; i < 93; i++) {
1913                 struct security_ace a;
1914                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1915                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1916                 a.flags = 0;
1917                 a.size = 0; /* autogenerated */
1918                 a.access_mask = 0;
1919                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1920                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1921         }
1922
1923         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1924
1925         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1926         sd2 = info.info2.secdesc;
1927
1928         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1929                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1930                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1931         }
1932
1933         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1934                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1935
1936
1937         return true;
1938 }
1939
1940 /*
1941  * wrapper call that saves original sd, runs tests, and restores sd
1942  */
1943
1944 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1945                                 struct dcerpc_binding_handle *b,
1946                                 struct policy_handle *handle)
1947 {
1948         union spoolss_PrinterInfo info;
1949         struct security_descriptor *sd;
1950         bool ret = true;
1951
1952         torture_comment(tctx, "Testing Printer Security Descriptors\n");
1953
1954         /* save original sd */
1955
1956         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1957                 "failed to get initial security descriptor");
1958
1959         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1960
1961         /* run tests */
1962
1963         ret = test_PrinterInfo_SDs(tctx, b, handle);
1964
1965         /* restore original sd */
1966
1967         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1968                 "failed to restore initial security descriptor");
1969
1970         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1971                 ret ? "succeeded" : "failed");
1972
1973
1974         return ret;
1975 }
1976
1977 static bool test_devmode_set_level(struct torture_context *tctx,
1978                                    struct dcerpc_binding_handle *b,
1979                                    struct policy_handle *handle,
1980                                    uint32_t level,
1981                                    struct spoolss_DeviceMode *devmode)
1982 {
1983         struct spoolss_SetPrinterInfoCtr info_ctr;
1984         struct spoolss_DevmodeContainer devmode_ctr;
1985         struct sec_desc_buf secdesc_ctr;
1986         union spoolss_SetPrinterInfo sinfo;
1987
1988         ZERO_STRUCT(devmode_ctr);
1989         ZERO_STRUCT(secdesc_ctr);
1990
1991         switch (level) {
1992         case 2: {
1993                 union spoolss_PrinterInfo info;
1994                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1995                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1996
1997                 info_ctr.level = 2;
1998                 info_ctr.info = sinfo;
1999
2000                 break;
2001         }
2002         case 8: {
2003                 struct spoolss_SetPrinterInfo8 info8;
2004
2005                 info8.devmode_ptr = 0;
2006
2007                 info_ctr.level = 8;
2008                 info_ctr.info.info8 = &info8;
2009
2010                 break;
2011         }
2012         default:
2013                 return false;
2014         }
2015
2016         devmode_ctr.devmode = devmode;
2017
2018         torture_assert(tctx,
2019                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2020
2021         return true;
2022 }
2023
2024
2025 static bool test_devicemode_equal(struct torture_context *tctx,
2026                                   const struct spoolss_DeviceMode *d1,
2027                                   const struct spoolss_DeviceMode *d2)
2028 {
2029         if (d1 == d2) {
2030                 return true;
2031         }
2032
2033         if (!d1 || !d2) {
2034                 torture_comment(tctx, "%s\n", __location__);
2035                 return false;
2036         }
2037         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2038         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2039         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2040         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2041         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2042         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2043         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2044         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2045         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2046         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2047         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2048         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2049         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2050         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2051         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2052         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2053         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2054         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2055         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2056         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2057         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2058         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2059         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2060         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2061         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2062         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2063         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2064         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2065         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2066         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2067         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2068         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2069         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2070         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2071         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2072
2073         return true;
2074 }
2075
2076 static bool test_devicemode_full(struct torture_context *tctx,
2077                                  struct dcerpc_binding_handle *b,
2078                                  struct policy_handle *handle)
2079 {
2080         struct spoolss_SetPrinter s;
2081         struct spoolss_GetPrinter q;
2082         struct spoolss_GetPrinter q0;
2083         struct spoolss_SetPrinterInfoCtr info_ctr;
2084         struct spoolss_SetPrinterInfo8 info8;
2085         union spoolss_PrinterInfo info;
2086         struct spoolss_DevmodeContainer devmode_ctr;
2087         struct sec_desc_buf secdesc_ctr;
2088         uint32_t needed;
2089         bool ret = true;
2090         NTSTATUS status;
2091
2092 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2093                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2094                 q.in.level = lvl1; \
2095                 TESTGETCALL(GetPrinter, q) \
2096                 info_ctr.level = lvl1; \
2097                 if (lvl1 == 2) {\
2098                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2099                 } else if (lvl1 == 8) {\
2100                         info_ctr.info.info ## lvl1 = &info8; \
2101                 }\
2102                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2103                 devmode_ctr.devmode->field1 = value; \
2104                 TESTSETCALL(SetPrinter, s) \
2105                 TESTGETCALL(GetPrinter, q) \
2106                 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2107                 q.in.level = lvl2; \
2108                 TESTGETCALL(GetPrinter, q) \
2109                 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2110         } while (0)
2111
2112 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2113         TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2114         } while (0)
2115
2116         ZERO_STRUCT(devmode_ctr);
2117         ZERO_STRUCT(secdesc_ctr);
2118         ZERO_STRUCT(info8);
2119
2120         s.in.handle = handle;
2121         s.in.command = 0;
2122         s.in.info_ctr = &info_ctr;
2123         s.in.devmode_ctr = &devmode_ctr;
2124         s.in.secdesc_ctr = &secdesc_ctr;
2125
2126         q.in.handle = handle;
2127         q.out.info = &info;
2128         q0 = q;
2129
2130 #if 0
2131         const char *devicename;/* [charset(UTF16)] */
2132         enum spoolss_DeviceModeSpecVersion specversion;
2133         uint16_t driverversion;
2134         uint16_t size;
2135         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2136         uint32_t fields;
2137 #endif
2138
2139         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
2140         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
2141         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
2142         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
2143         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
2144         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
2145         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
2146         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
2147         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
2148         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
2149         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
2150         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
2151         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
2152 #if 0
2153         const char *formname;/* [charset(UTF16)] */
2154 #endif
2155         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
2156         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
2157         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
2158         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
2159         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
2160         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
2161         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
2162         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
2163         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
2164         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
2165         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
2166         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
2167         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
2168         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
2169
2170         return ret;
2171 }
2172
2173 static bool call_OpenPrinterEx(struct torture_context *tctx,
2174                                struct dcerpc_pipe *p,
2175                                const char *name,
2176                                struct spoolss_DeviceMode *devmode,
2177                                struct policy_handle *handle);
2178
2179 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2180                                       struct dcerpc_pipe *p,
2181                                       struct policy_handle *handle,
2182                                       const char *name)
2183 {
2184         union spoolss_PrinterInfo info;
2185         struct spoolss_DeviceMode *devmode;
2186         struct spoolss_DeviceMode *devmode2;
2187         struct policy_handle handle_devmode;
2188         struct dcerpc_binding_handle *b = p->binding_handle;
2189
2190         /* simply compare level8 and level2 devmode */
2191
2192         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2193
2194         devmode = info.info8.devmode;
2195
2196         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2197
2198         devmode2 = info.info2.devmode;
2199
2200         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2201                 "DM level 8 != DM level 2");
2202
2203
2204         /* set devicemode level 8 and see if it persists */
2205
2206         devmode->copies = 93;
2207         devmode->formname = talloc_strdup(tctx, "Legal");
2208
2209         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2210
2211         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2212
2213         devmode2 = info.info8.devmode;
2214
2215         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2216                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2217
2218         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2219
2220         devmode2 = info.info2.devmode;
2221
2222         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2223                 "modified DM level 8 != DM level 2");
2224
2225
2226         /* set devicemode level 2 and see if it persists */
2227
2228         devmode->copies = 39;
2229         devmode->formname = talloc_strdup(tctx, "Executive");
2230
2231         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2232
2233         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2234
2235         devmode2 = info.info8.devmode;
2236
2237         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2238                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2239
2240         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2241
2242         devmode2 = info.info2.devmode;
2243
2244         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2245                 "modified DM level 8 != DM level 2");
2246
2247
2248         /* check every single bit in public part of devicemode */
2249
2250         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2251                 "failed to set every single devicemode component");
2252
2253
2254         /* change formname upon open and see if it persists in getprinter calls */
2255
2256         devmode->formname = talloc_strdup(tctx, "A4");
2257         devmode->copies = 42;
2258
2259         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2260                 "failed to open printer handle");
2261
2262         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2263
2264         devmode2 = info.info8.devmode;
2265
2266         if (strequal(devmode->devicename, devmode2->devicename)) {
2267                 torture_warning(tctx, "devicenames are the same\n");
2268         } else {
2269                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2270                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2271         }
2272
2273         if (strequal(devmode->formname, devmode2->formname)) {
2274                 torture_warning(tctx, "formname are the same\n");
2275         } else {
2276                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2277                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2278         }
2279
2280         if (devmode->copies == devmode2->copies) {
2281                 torture_warning(tctx, "copies are the same\n");
2282         } else {
2283                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2284                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2285         }
2286
2287         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2288
2289         devmode2 = info.info2.devmode;
2290
2291         if (strequal(devmode->devicename, devmode2->devicename)) {
2292                 torture_warning(tctx, "devicenames are the same\n");
2293         } else {
2294                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2295                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2296         }
2297
2298         if (strequal(devmode->formname, devmode2->formname)) {
2299                 torture_warning(tctx, "formname is the same\n");
2300         } else {
2301                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2302                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2303         }
2304
2305         if (devmode->copies == devmode2->copies) {
2306                 torture_warning(tctx, "copies are the same\n");
2307         } else {
2308                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2309                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2310         }
2311
2312         test_ClosePrinter(tctx, b, &handle_devmode);
2313
2314         return true;
2315 }
2316
2317 /*
2318  * wrapper call that saves original devmode, runs tests, and restores devmode
2319  */
2320
2321 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2322                                      struct dcerpc_pipe *p,
2323                                      struct policy_handle *handle,
2324                                      const char *name,
2325                                      struct spoolss_DeviceMode *addprinter_devmode)
2326 {
2327         union spoolss_PrinterInfo info;
2328         struct spoolss_DeviceMode *devmode;
2329         bool ret = true;
2330         struct dcerpc_binding_handle *b = p->binding_handle;
2331
2332         torture_comment(tctx, "Testing Printer Devicemodes\n");
2333
2334         /* save original devmode */
2335
2336         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2337                 "failed to get initial global devicemode");
2338
2339         devmode = info.info8.devmode;
2340
2341         if (addprinter_devmode) {
2342                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2343                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
2344                 }
2345         }
2346
2347         /* run tests */
2348
2349         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2350
2351         /* restore original devmode */
2352
2353         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2354                 "failed to restore initial global device mode");
2355
2356         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2357                 ret ? "succeeded" : "failed");
2358
2359
2360         return ret;
2361 }
2362
2363 bool test_ClosePrinter(struct torture_context *tctx,
2364                        struct dcerpc_binding_handle *b,
2365                        struct policy_handle *handle)
2366 {
2367         NTSTATUS status;
2368         struct spoolss_ClosePrinter r;
2369
2370         r.in.handle = handle;
2371         r.out.handle = handle;
2372
2373         torture_comment(tctx, "Testing ClosePrinter\n");
2374
2375         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2376         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2377         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2378
2379         return true;
2380 }
2381
2382 static bool test_GetForm_args(struct torture_context *tctx,
2383                               struct dcerpc_binding_handle *b,
2384                               struct policy_handle *handle,
2385                               const char *form_name,
2386                               uint32_t level,
2387                               union spoolss_FormInfo *info_p)
2388 {
2389         NTSTATUS status;
2390         struct spoolss_GetForm r;
2391         uint32_t needed;
2392
2393         r.in.handle = handle;
2394         r.in.form_name = form_name;
2395         r.in.level = level;
2396         r.in.buffer = NULL;
2397         r.in.offered = 0;
2398         r.out.needed = &needed;
2399
2400         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2401
2402         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2403         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2404
2405         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2406                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2407                 r.in.buffer = &blob;
2408                 r.in.offered = needed;
2409                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2410                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2411
2412                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2413
2414                 torture_assert(tctx, r.out.info, "No form info returned");
2415         }
2416
2417         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2418
2419         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2420
2421         if (info_p) {
2422                 *info_p = *r.out.info;
2423         }
2424
2425         return true;
2426 }
2427
2428 static bool test_GetForm(struct torture_context *tctx,
2429                          struct dcerpc_binding_handle *b,
2430                          struct policy_handle *handle,
2431                          const char *form_name,
2432                          uint32_t level)
2433 {
2434         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2435 }
2436
2437 static bool test_EnumForms(struct torture_context *tctx,
2438                            struct dcerpc_binding_handle *b,
2439                            struct policy_handle *handle,
2440                            bool print_server,
2441                            uint32_t level,
2442                            uint32_t *count_p,
2443                            union spoolss_FormInfo **info_p)
2444 {
2445         struct spoolss_EnumForms r;
2446         uint32_t needed;
2447         uint32_t count;
2448         union spoolss_FormInfo *info;
2449
2450         r.in.handle = handle;
2451         r.in.level = level;
2452         r.in.buffer = NULL;
2453         r.in.offered = 0;
2454         r.out.needed = &needed;
2455         r.out.count = &count;
2456         r.out.info = &info;
2457
2458         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2459
2460         torture_assert_ntstatus_ok(tctx,
2461                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2462                 "EnumForms failed");
2463
2464         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2465                 torture_skip(tctx, "EnumForms level 2 not supported");
2466         }
2467
2468         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2469                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2470         }
2471
2472         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2473                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2474                 r.in.buffer = &blob;
2475                 r.in.offered = needed;
2476
2477                 torture_assert_ntstatus_ok(tctx,
2478                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2479                         "EnumForms failed");
2480
2481                 torture_assert(tctx, info, "No forms returned");
2482         }
2483
2484         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2485
2486         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2487
2488         if (info_p) {
2489                 *info_p = info;
2490         }
2491         if (count_p) {
2492                 *count_p = count;
2493         }
2494
2495         return true;
2496 }
2497
2498 static bool test_EnumForms_all(struct torture_context *tctx,
2499                                struct dcerpc_binding_handle *b,
2500                                struct policy_handle *handle,
2501                                bool print_server)
2502 {
2503         uint32_t levels[] = { 1, 2 };
2504         int i, j;
2505
2506         for (i=0; i<ARRAY_SIZE(levels); i++) {
2507
2508                 uint32_t count = 0;
2509                 union spoolss_FormInfo *info = NULL;
2510
2511                 torture_assert(tctx,
2512                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2513                         "failed to enum forms");
2514
2515                 for (j = 0; j < count; j++) {
2516                         if (!print_server) {
2517                                 torture_assert(tctx,
2518                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2519                                         "failed to get form");
2520                         }
2521                 }
2522         }
2523
2524         return true;
2525 }
2526
2527 static bool test_EnumForms_find_one(struct torture_context *tctx,
2528                                     struct dcerpc_binding_handle *b,
2529                                     struct policy_handle *handle,
2530                                     bool print_server,
2531                                     const char *form_name)
2532 {
2533         union spoolss_FormInfo *info;
2534         uint32_t count;
2535         bool found = false;
2536         int i;
2537
2538         torture_assert(tctx,
2539                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2540                 "failed to enumerate forms");
2541
2542         for (i=0; i<count; i++) {
2543                 if (strequal(form_name, info[i].info1.form_name)) {
2544                         found = true;
2545                         break;
2546                 }
2547         }
2548
2549         return found;
2550 }
2551
2552 static bool test_DeleteForm(struct torture_context *tctx,
2553                             struct dcerpc_binding_handle *b,
2554                             struct policy_handle *handle,
2555                             const char *form_name,
2556                             WERROR expected_result)
2557 {
2558         struct spoolss_DeleteForm r;
2559
2560         r.in.handle = handle;
2561         r.in.form_name = form_name;
2562
2563         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2564
2565         torture_assert_ntstatus_ok(tctx,
2566                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2567                 "DeleteForm failed");
2568         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2569                 "DeleteForm gave unexpected result");
2570         if (W_ERROR_IS_OK(r.out.result)) {
2571                 torture_assert_ntstatus_ok(tctx,
2572                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2573                         "2nd DeleteForm failed");
2574                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2575                         "2nd DeleteForm failed");
2576         }
2577
2578         return true;
2579 }
2580
2581 static bool test_AddForm(struct torture_context *tctx,
2582                          struct dcerpc_binding_handle *b,
2583                          struct policy_handle *handle,
2584                          uint32_t level,
2585                          union spoolss_AddFormInfo *info,
2586                          WERROR expected_result)
2587 {
2588         struct spoolss_AddForm r;
2589
2590         if (level != 1) {
2591                 torture_skip(tctx, "only level 1 supported");
2592         }
2593
2594         r.in.handle     = handle;
2595         r.in.level      = level;
2596         r.in.info       = *info;
2597
2598         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2599                 r.in.info.info1->form_name, r.in.level,
2600                 r.in.info.info1->flags);
2601
2602         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2603                 "AddForm failed");
2604         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2605                 "AddForm gave unexpected result");
2606
2607         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2608                 "2nd AddForm failed");
2609         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2610                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2611                         "2nd AddForm gave unexpected result");
2612         } else {
2613                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2614                         "2nd AddForm gave unexpected result");
2615         }
2616
2617         return true;
2618 }
2619
2620 static bool test_SetForm(struct torture_context *tctx,
2621                          struct dcerpc_binding_handle *b,
2622                          struct policy_handle *handle,
2623                          const char *form_name,
2624                          uint32_t level,
2625                          union spoolss_AddFormInfo *info)
2626 {
2627         struct spoolss_SetForm r;
2628
2629         r.in.handle     = handle;
2630         r.in.form_name  = form_name;
2631         r.in.level      = level;
2632         r.in.info       = *info;
2633
2634         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2635                 form_name, r.in.level);
2636
2637         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2638                 "SetForm failed");
2639
2640         torture_assert_werr_ok(tctx, r.out.result,
2641                 "SetForm failed");
2642
2643         return true;
2644 }
2645
2646 static bool test_GetForm_winreg(struct torture_context *tctx,
2647                                 struct dcerpc_binding_handle *b,
2648                                 struct policy_handle *handle,
2649                                 const char *key_name,
2650                                 const char *form_name,
2651                                 enum winreg_Type *w_type,
2652                                 uint32_t *w_size,
2653                                 uint32_t *w_length,
2654                                 uint8_t **w_data);
2655
2656 static bool test_Forms_args(struct torture_context *tctx,
2657                             struct dcerpc_binding_handle *b,
2658                             struct policy_handle *handle,
2659                             bool print_server,
2660                             const char *printer_name,
2661                             struct dcerpc_binding_handle *winreg_handle,
2662                             struct policy_handle *hive_handle,
2663                             const char *form_name,
2664                             struct spoolss_AddFormInfo1 *info1,
2665                             WERROR expected_add_result,
2666                             WERROR expected_delete_result)
2667 {
2668         union spoolss_FormInfo info;
2669         union spoolss_AddFormInfo add_info;
2670
2671         enum winreg_Type w_type;
2672         uint32_t w_size;
2673         uint32_t w_length;
2674         uint8_t *w_data;
2675
2676         add_info.info1 = info1;
2677
2678         torture_assert(tctx,
2679                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2680                 "failed to add form");
2681
2682         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2683
2684                 torture_assert(tctx,
2685                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2686                         "failed to get form via winreg");
2687
2688                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2689                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2690                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2691                 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2692                 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2693                 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2694                 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2695                 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2696                 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2697                 /* skip index here */
2698                 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2699         }
2700
2701         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2702                 torture_assert(tctx,
2703                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2704                         "failed to get added form");
2705
2706                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2707                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2708                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2709                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2710                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2711                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2712                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2713
2714                 if (winreg_handle && hive_handle) {
2715                         torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2716                         torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2717                         torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2718                         torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2719                         torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2720                         torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2721                         /* skip index here */
2722                         torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2723                 }
2724
2725                 add_info.info1->size.width = 1234;
2726
2727                 torture_assert(tctx,
2728                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2729                         "failed to set form");
2730                 torture_assert(tctx,
2731                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2732                         "failed to get setted form");
2733
2734                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2735         }
2736
2737         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2738                 torture_assert(tctx,
2739                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2740                         "Newly added form not found in enum call");
2741         }
2742
2743         torture_assert(tctx,
2744                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2745                 "failed to delete form");
2746
2747         return true;
2748 }
2749
2750 static bool test_Forms(struct torture_context *tctx,
2751                        struct dcerpc_binding_handle *b,
2752                        struct policy_handle *handle,
2753                        bool print_server,
2754                        const char *printer_name,
2755                        struct dcerpc_binding_handle *winreg_handle,
2756                        struct policy_handle *hive_handle)
2757 {
2758         const struct spoolss_FormSize size = {
2759                 .width  = 50,
2760                 .height = 25
2761         };
2762         const struct spoolss_FormArea area = {
2763                 .left   = 5,
2764                 .top    = 10,
2765                 .right  = 45,
2766                 .bottom = 15
2767         };
2768         int i;
2769
2770         struct {
2771                 struct spoolss_AddFormInfo1 info1;
2772                 WERROR expected_add_result;
2773                 WERROR expected_delete_result;
2774         } forms[] = {
2775                 {
2776                         .info1 = {
2777                                 .flags          = SPOOLSS_FORM_USER,
2778                                 .form_name      = "testform_user",
2779                                 .size           = size,
2780                                 .area           = area,
2781                         },
2782                         .expected_add_result    = WERR_OK,
2783                         .expected_delete_result = WERR_OK
2784                 },
2785 /*
2786                 weird, we can add a builtin form but we can never remove it
2787                 again - gd
2788
2789                 {
2790                         .info1 = {
2791                                 .flags          = SPOOLSS_FORM_BUILTIN,
2792                                 .form_name      = "testform_builtin",
2793                                 .size           = size,
2794                                 .area           = area,
2795                         },
2796                         .expected_add_result    = WERR_OK,
2797                         .expected_delete_result = WERR_INVALID_PARAM,
2798                 },
2799 */
2800                 {
2801                         .info1 = {
2802                                 .flags          = SPOOLSS_FORM_PRINTER,
2803                                 .form_name      = "testform_printer",
2804                                 .size           = size,
2805                                 .area           = area,
2806                         },
2807                         .expected_add_result    = WERR_OK,
2808                         .expected_delete_result = WERR_OK
2809                 },
2810                 {
2811                         .info1 = {
2812                                 .flags          = SPOOLSS_FORM_USER,
2813                                 .form_name      = "Letter",
2814                                 .size           = size,
2815                                 .area           = area,
2816                         },
2817                         .expected_add_result    = WERR_FILE_EXISTS,
2818                         .expected_delete_result = WERR_INVALID_PARAM
2819                 },
2820                 {
2821                         .info1 = {
2822                                 .flags          = SPOOLSS_FORM_BUILTIN,
2823                                 .form_name      = "Letter",
2824                                 .size           = size,
2825                                 .area           = area,
2826                         },
2827                         .expected_add_result    = WERR_FILE_EXISTS,
2828                         .expected_delete_result = WERR_INVALID_PARAM
2829                 },
2830                 {
2831                         .info1 = {
2832                                 .flags          = SPOOLSS_FORM_PRINTER,
2833                                 .form_name      = "Letter",
2834                                 .size           = size,
2835                                 .area           = area,
2836                         },
2837                         .expected_add_result    = WERR_FILE_EXISTS,
2838                         .expected_delete_result = WERR_INVALID_PARAM
2839                 },
2840                 {
2841                         .info1 = {
2842                                 .flags          = 12345,
2843                                 .form_name      = "invalid_flags",
2844                                 .size           = size,
2845                                 .area           = area,
2846                         },
2847                         .expected_add_result    = WERR_INVALID_PARAM,
2848                         .expected_delete_result = WERR_INVALID_FORM_NAME
2849                 }
2850
2851         };
2852
2853         for (i=0; i < ARRAY_SIZE(forms); i++) {
2854                 torture_assert(tctx,
2855                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2856                                         winreg_handle, hive_handle,
2857                                         forms[i].info1.form_name,
2858                                         &forms[i].info1,
2859                                         forms[i].expected_add_result,
2860                                         forms[i].expected_delete_result),
2861                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2862         }
2863
2864         return true;
2865 }
2866
2867 static bool test_EnumPorts_old(struct torture_context *tctx,
2868                                void *private_data)
2869 {
2870         struct test_spoolss_context *ctx =
2871                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2872
2873         NTSTATUS status;
2874         struct spoolss_EnumPorts r;
2875         uint32_t needed;
2876         uint32_t count;
2877         union spoolss_PortInfo *info;
2878         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2879         struct dcerpc_binding_handle *b = p->binding_handle;
2880
2881         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2882                                           dcerpc_server_name(p));
2883         r.in.level = 2;
2884         r.in.buffer = NULL;
2885         r.in.offered = 0;
2886         r.out.needed = &needed;
2887         r.out.count = &count;
2888         r.out.info = &info;
2889
2890         torture_comment(tctx, "Testing EnumPorts\n");
2891
2892         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2893
2894         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2895
2896         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2897                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2898                 r.in.buffer = &blob;
2899                 r.in.offered = needed;
2900
2901                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2902                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2903                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2904
2905                 torture_assert(tctx, info, "No ports returned");
2906         }
2907
2908         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2909
2910         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2911
2912         return true;
2913 }
2914
2915 static bool test_AddPort(struct torture_context *tctx,
2916                          void *private_data)
2917 {
2918         struct test_spoolss_context *ctx =
2919                 talloc_get_type_abort(private_data, struct test_spoolss_context);
2920
2921         NTSTATUS status;
2922         struct spoolss_AddPort r;
2923         struct dcerpc_pipe *p = ctx->spoolss_pipe;
2924         struct dcerpc_binding_handle *b = p->binding_handle;
2925
2926         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2927                                            dcerpc_server_name(p));
2928         r.in.unknown = 0;
2929         r.in.monitor_name = "foo";
2930
2931         torture_comment(tctx, "Testing AddPort\n");
2932
2933         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2934
2935         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2936
2937         /* win2k3 returns WERR_NOT_SUPPORTED */
2938
2939 #if 0
2940
2941         if (!W_ERROR_IS_OK(r.out.result)) {
2942                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2943                 return false;
2944         }
2945
2946 #endif
2947
2948         return true;
2949 }
2950
2951 static bool test_GetJob_args(struct torture_context *tctx,
2952                              struct dcerpc_binding_handle *b,
2953                              struct policy_handle *handle,
2954                              uint32_t job_id,
2955                              uint32_t level,
2956                              union spoolss_JobInfo *info_p)
2957 {
2958         NTSTATUS status;
2959         struct spoolss_GetJob r;
2960         union spoolss_JobInfo info;
2961         uint32_t needed;
2962
2963         r.in.handle = handle;
2964         r.in.job_id = job_id;
2965         r.in.level = level;
2966         r.in.buffer = NULL;
2967         r.in.offered = 0;
2968         r.out.needed = &needed;
2969         r.out.info = &info;
2970
2971         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2972
2973         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2974         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2975         if (level == 0) {
2976                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2977         }
2978
2979         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2980                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2981                 r.in.buffer = &blob;
2982                 r.in.offered = needed;
2983
2984                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2985                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2986         }
2987
2988         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2989         torture_assert(tctx, r.out.info, "No job info returned");
2990
2991         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
2992
2993         if (info_p) {
2994                 *info_p = *r.out.info;
2995         }
2996
2997         return true;
2998 }
2999
3000 static bool test_GetJob(struct torture_context *tctx,
3001                         struct dcerpc_binding_handle *b,
3002                         struct policy_handle *handle,
3003                         uint32_t job_id)
3004 {
3005         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3006         uint32_t i;
3007
3008         for (i=0; i < ARRAY_SIZE(levels); i++) {
3009                 torture_assert(tctx,
3010                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3011                         "GetJob failed");
3012         }
3013
3014         return true;
3015 }
3016
3017 static bool test_SetJob(struct torture_context *tctx,
3018                         struct dcerpc_binding_handle *b,
3019                         struct policy_handle *handle,
3020                         uint32_t job_id,
3021                         struct spoolss_JobInfoContainer *ctr,
3022                         enum spoolss_JobControl command)
3023 {
3024         NTSTATUS status;
3025         struct spoolss_SetJob r;
3026
3027         r.in.handle     = handle;
3028         r.in.job_id     = job_id;
3029         r.in.ctr        = ctr;
3030         r.in.command    = command;
3031
3032         switch (command) {
3033         case SPOOLSS_JOB_CONTROL_PAUSE:
3034                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3035                 break;
3036         case SPOOLSS_JOB_CONTROL_RESUME:
3037                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3038                 break;
3039         case SPOOLSS_JOB_CONTROL_CANCEL:
3040                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3041                 break;
3042         case SPOOLSS_JOB_CONTROL_RESTART:
3043                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3044                 break;
3045         case SPOOLSS_JOB_CONTROL_DELETE:
3046                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3047                 break;
3048         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3049                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3050                 break;
3051         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3052                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3053                 break;
3054         case SPOOLSS_JOB_CONTROL_RETAIN:
3055                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3056                 break;
3057         case SPOOLSS_JOB_CONTROL_RELEASE:
3058                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3059                 break;
3060         default:
3061                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3062                 break;
3063         }
3064
3065         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3066         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3067         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3068
3069         return true;
3070 }
3071
3072 static bool test_AddJob(struct torture_context *tctx,
3073                         struct dcerpc_binding_handle *b,
3074                         struct policy_handle *handle)
3075 {
3076         NTSTATUS status;
3077         struct spoolss_AddJob r;
3078         uint32_t needed;
3079
3080         r.in.level = 0;
3081         r.in.handle = handle;
3082         r.in.offered = 0;
3083         r.out.needed = &needed;
3084         r.in.buffer = r.out.buffer = NULL;
3085
3086         torture_comment(tctx, "Testing AddJob\n");
3087
3088         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3089         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3090
3091         r.in.level = 1;
3092
3093         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3094         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3095
3096         return true;
3097 }
3098
3099
3100 static bool test_EnumJobs_args(struct torture_context *tctx,
3101                                struct dcerpc_binding_handle *b,
3102                                struct policy_handle *handle,
3103                                uint32_t level,
3104                                uint32_t *count_p,
3105                                union spoolss_JobInfo **info_p)
3106 {
3107         NTSTATUS status;
3108         struct spoolss_EnumJobs r;
3109         uint32_t needed;
3110         uint32_t count;
3111         union spoolss_JobInfo *info;
3112
3113         r.in.handle = handle;
3114         r.in.firstjob = 0;
3115         r.in.numjobs = 0xffffffff;
3116         r.in.level = level;
3117         r.in.buffer = NULL;
3118         r.in.offered = 0;
3119         r.out.needed = &needed;
3120         r.out.count = &count;
3121         r.out.info = &info;
3122
3123         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3124
3125         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3126
3127         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3128
3129         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3130                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3131                 r.in.buffer = &blob;
3132                 r.in.offered = needed;
3133
3134                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3135
3136                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3137                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3138                 torture_assert(tctx, info, "No jobs returned");
3139
3140                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3141
3142         } else {
3143                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3144         }
3145
3146         if (count_p) {
3147                 *count_p = count;
3148         }
3149         if (info_p) {
3150                 *info_p = info;
3151         }
3152
3153         return true;
3154 }
3155
3156 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3157                                          struct dcerpc_binding_handle *b,
3158                                          struct policy_handle *handle,
3159                                          uint32_t *job_id)
3160 {
3161         NTSTATUS status;
3162         struct spoolss_StartDocPrinter s;
3163         struct spoolss_DocumentInfo1 info1;
3164         struct spoolss_StartPagePrinter sp;
3165         struct spoolss_WritePrinter w;
3166         struct spoolss_EndPagePrinter ep;
3167         struct spoolss_EndDocPrinter e;
3168         int i;
3169         uint32_t num_written;
3170
3171         torture_comment(tctx, "Testing StartDocPrinter\n");
3172
3173         s.in.handle             = handle;
3174         s.in.level              = 1;
3175         s.in.info.info1         = &info1;
3176         s.out.job_id            = job_id;
3177         info1.document_name     = "TorturePrintJob";
3178         info1.output_file       = NULL;
3179         info1.datatype          = "RAW";
3180
3181         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3182         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3183         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3184
3185         for (i=1; i < 4; i++) {
3186                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3187
3188                 sp.in.handle            = handle;
3189
3190                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3191                 torture_assert_ntstatus_ok(tctx, status,
3192                                            "dcerpc_spoolss_StartPagePrinter failed");
3193                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3194
3195                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3196
3197                 w.in.handle             = handle;
3198                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3199                 w.out.num_written       = &num_written;
3200
3201                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3202                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3203                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3204
3205                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3206
3207                 ep.in.handle            = handle;
3208
3209                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3210                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3211                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3212         }
3213
3214         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3215
3216         e.in.handle = handle;
3217
3218         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3219         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3220         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3221
3222         return true;
3223 }
3224
3225 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3226                                         struct dcerpc_binding_handle *b,
3227                                         struct policy_handle *handle,
3228                                         uint32_t num_jobs,
3229                                         uint32_t *job_ids)
3230 {
3231         uint32_t count;
3232         union spoolss_JobInfo *info = NULL;
3233         int i;
3234
3235         torture_assert(tctx,
3236                 test_AddJob(tctx, b, handle),
3237                 "AddJob failed");
3238
3239         torture_assert(tctx,
3240                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3241                 "EnumJobs level 1 failed");
3242
3243         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3244
3245         for (i=0; i < num_jobs; i++) {
3246                 union spoolss_JobInfo ginfo;
3247                 const char *document_name;
3248                 const char *new_document_name = "any_other_docname";
3249                 struct spoolss_JobInfoContainer ctr;
3250                 struct spoolss_SetJobInfo1 info1;
3251
3252                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3253
3254                 torture_assert(tctx,
3255                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3256                         "failed to call test_GetJob");
3257
3258                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3259
3260                 document_name = ginfo.info1.document_name;
3261
3262                 info1.job_id            = ginfo.info1.job_id;
3263                 info1.printer_name      = ginfo.info1.printer_name;
3264                 info1.server_name       = ginfo.info1.server_name;
3265                 info1.user_name         = ginfo.info1.user_name;
3266                 info1.document_name     = new_document_name;
3267                 info1.data_type         = ginfo.info1.data_type;
3268                 info1.text_status       = ginfo.info1.text_status;
3269                 info1.status            = ginfo.info1.status;
3270                 info1.priority          = ginfo.info1.priority;
3271                 info1.position          = ginfo.info1.position;
3272                 info1.total_pages       = ginfo.info1.total_pages;
3273                 info1.pages_printed     = ginfo.info1.pages_printed;
3274                 info1.submitted         = ginfo.info1.submitted;
3275
3276                 ctr.level = 1;
3277                 ctr.info.info1 = &info1;
3278
3279                 torture_assert(tctx,
3280                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3281                         "failed to call test_SetJob level 1");
3282
3283                 torture_assert(tctx,
3284                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3285                         "failed to call test_GetJob");
3286
3287                 if (strequal(ginfo.info1.document_name, document_name)) {
3288                         torture_warning(tctx,
3289                                 talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
3290                                         document_name, new_document_name));
3291                 }
3292         }
3293
3294         for (i=0; i < num_jobs; i++) {
3295                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3296                         torture_warning(tctx, "failed to pause printjob\n");
3297                 }
3298                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3299                         torture_warning(tctx, "failed to resume printjob\n");
3300                 }
3301         }
3302
3303         return true;
3304 }
3305
3306 static bool test_DoPrintTest(struct torture_context *tctx,
3307                              struct dcerpc_binding_handle *b,
3308                              struct policy_handle *handle)
3309 {
3310         bool ret = true;
3311         uint32_t num_jobs = 8;
3312         uint32_t *job_ids;
3313         int i;
3314
3315         torture_comment(tctx, "Testing real print operations\n");
3316
3317         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3318
3319         for (i=0; i < num_jobs; i++) {
3320                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3321         }
3322
3323         for (i=0; i < num_jobs; i++) {
3324                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3325         }
3326
3327         if (ret == true) {
3328                 torture_comment(tctx, "real print operations test succeeded\n\n");
3329         }
3330
3331         return ret;
3332 }
3333
3334 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3335                                       struct dcerpc_binding_handle *b,
3336                                       struct policy_handle *handle)
3337 {
3338         bool ret = true;
3339         uint32_t num_jobs = 8;
3340         uint32_t *job_ids;
3341         int i;
3342         torture_comment(tctx, "Testing real print operations (extended)\n");
3343
3344         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3345
3346         for (i=0; i < num_jobs; i++) {
3347                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3348         }
3349
3350         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3351
3352         for (i=0; i < num_jobs; i++) {
3353                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3354         }
3355
3356         if (ret == true) {
3357                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3358         }
3359
3360         return ret;
3361 }
3362
3363 static bool test_PausePrinter(struct torture_context *tctx,
3364                               struct dcerpc_binding_handle *b,
3365                               struct policy_handle *handle)
3366 {
3367         NTSTATUS status;
3368         struct spoolss_SetPrinter r;
3369         struct spoolss_SetPrinterInfoCtr info_ctr;
3370         struct spoolss_DevmodeContainer devmode_ctr;
3371         struct sec_desc_buf secdesc_ctr;
3372
3373         info_ctr.level = 0;
3374         info_ctr.info.info0 = NULL;
3375
3376         ZERO_STRUCT(devmode_ctr);
3377         ZERO_STRUCT(secdesc_ctr);
3378
3379         r.in.handle             = handle;
3380         r.in.info_ctr           = &info_ctr;
3381         r.in.devmode_ctr        = &devmode_ctr;
3382         r.in.secdesc_ctr        = &secdesc_ctr;
3383         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3384
3385         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3386
3387         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3388
3389         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3390
3391         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3392
3393         return true;
3394 }
3395
3396 static bool test_ResumePrinter(struct torture_context *tctx,
3397                                struct dcerpc_binding_handle *b,
3398                                struct policy_handle *handle)
3399 {
3400         NTSTATUS status;
3401         struct spoolss_SetPrinter r;
3402         struct spoolss_SetPrinterInfoCtr info_ctr;
3403         struct spoolss_DevmodeContainer devmode_ctr;
3404         struct sec_desc_buf secdesc_ctr;
3405
3406         info_ctr.level = 0;
3407         info_ctr.info.info0 = NULL;
3408
3409         ZERO_STRUCT(devmode_ctr);
3410         ZERO_STRUCT(secdesc_ctr);
3411
3412         r.in.handle             = handle;
3413         r.in.info_ctr           = &info_ctr;
3414         r.in.devmode_ctr        = &devmode_ctr;
3415         r.in.secdesc_ctr        = &secdesc_ctr;
3416         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3417
3418         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3419
3420         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3421
3422         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3423
3424         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3425
3426         return true;
3427 }
3428
3429 static bool test_GetPrinterData(struct torture_context *tctx,
3430                                 struct dcerpc_binding_handle *b,
3431                                 struct policy_handle *handle,
3432                                 const char *value_name,
3433                                 enum winreg_Type *type_p,
3434                                 uint8_t **data_p,
3435                                 uint32_t *needed_p)
3436 {
3437         NTSTATUS status;
3438         struct spoolss_GetPrinterData r;
3439         uint32_t needed;
3440         enum winreg_Type type;
3441         union spoolss_PrinterData data;
3442
3443         r.in.handle = handle;
3444         r.in.value_name = value_name;
3445         r.in.offered = 0;
3446         r.out.needed = &needed;
3447         r.out.type = &type;
3448         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3449
3450         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3451
3452         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3453         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3454
3455         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3456                 r.in.offered = needed;
3457                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3458                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3459                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3460         }
3461
3462         torture_assert_werr_ok(tctx, r.out.result,
3463                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3464
3465         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3466
3467         if (type_p) {
3468                 *type_p = type;
3469         }
3470
3471         if (data_p) {
3472                 *data_p = r.out.data;
3473         }
3474
3475         if (needed_p) {
3476                 *needed_p = needed;
3477         }
3478
3479         return true;
3480 }
3481
3482 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3483                                   struct dcerpc_pipe *p,
3484                                   struct policy_handle *handle,
3485                                   const char *key_name,
3486                                   const char *value_name,
3487                                   enum winreg_Type *type_p,
3488                                   uint8_t **data_p,
3489                                   uint32_t *needed_p)
3490 {
3491         NTSTATUS status;
3492         struct spoolss_GetPrinterDataEx r;
3493         enum winreg_Type type;
3494         uint32_t needed;
3495         union spoolss_PrinterData data;
3496         struct dcerpc_binding_handle *b = p->binding_handle;
3497
3498         r.in.handle = handle;
3499         r.in.key_name = key_name;
3500         r.in.value_name = value_name;
3501         r.in.offered = 0;
3502         r.out.type = &type;
3503         r.out.needed = &needed;
3504         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3505
3506         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3507                 r.in.key_name, r.in.value_name);
3508
3509         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3510         if (!NT_STATUS_IS_OK(status)) {
3511                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3512                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3513                 }
3514                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3515         }
3516
3517         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3518                 r.in.offered = needed;
3519                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3520                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3521                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3522         }
3523
3524         torture_assert_werr_ok(tctx, r.out.result,
3525                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3526
3527         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3528
3529         if (type_p) {
3530                 *type_p = type;
3531         }
3532
3533         if (data_p) {
3534                 *data_p = r.out.data;
3535         }
3536
3537         if (needed_p) {
3538                 *needed_p = needed;
3539         }
3540
3541         return true;
3542 }
3543
3544 static bool test_get_environment(struct torture_context *tctx,
3545                                  struct dcerpc_binding_handle *b,
3546                                  struct policy_handle *handle,
3547                                  const char **architecture)
3548 {
3549         DATA_BLOB blob;
3550         enum winreg_Type type;
3551         uint8_t *data;
3552         uint32_t needed;
3553
3554         torture_assert(tctx,
3555                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3556                 "failed to get Architecture");
3557
3558         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3559
3560         blob = data_blob_const(data, needed);
3561         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3562
3563         return true;
3564 }
3565
3566 static bool test_GetPrinterData_list(struct torture_context *tctx,
3567                                      void *private_data)
3568 {
3569         struct test_spoolss_context *ctx =
3570                 talloc_get_type_abort(private_data, struct test_spoolss_context);
3571         struct dcerpc_pipe *p = ctx->spoolss_pipe;
3572         struct dcerpc_binding_handle *b = p->binding_handle;
3573         const char *list[] = {
3574                 "W3SvcInstalled",
3575                 "BeepEnabled",
3576                 "EventLog",
3577                 /* "NetPopup", not on w2k8 */
3578                 /* "NetPopupToComputer", not on w2k8 */
3579                 "MajorVersion",
3580                 "MinorVersion",
3581                 "DefaultSpoolDirectory",
3582                 "Architecture",
3583                 "DsPresent",
3584                 "OSVersion",
3585                 /* "OSVersionEx", not on s3 */
3586                 "DNSMachineName"
3587         };
3588         int i;
3589
3590         for (i=0; i < ARRAY_SIZE(list); i++) {
3591                 enum winreg_Type type, type_ex;
3592                 uint8_t *data, *data_ex;
3593                 uint32_t needed, needed_ex;
3594
3595                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3596                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3597                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3598                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3599                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3600                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3601                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3602         }
3603
3604         return true;
3605 }
3606
3607 static bool test_EnumPrinterData(struct torture_context *tctx,
3608                                  struct dcerpc_pipe *p,
3609                                  struct policy_handle *handle,
3610                                  uint32_t enum_index,
3611                                  uint32_t value_offered,
3612                                  uint32_t data_offered,
3613                                  enum winreg_Type *type_p,
3614                                  uint32_t *value_needed_p,
3615                                  uint32_t *data_needed_p,
3616                                  const char **value_name_p,
3617                                  uint8_t **data_p,
3618                                  WERROR *result_p)
3619 {
3620         struct spoolss_EnumPrinterData r;
3621         uint32_t data_needed;
3622         uint32_t value_needed;
3623         enum winreg_Type type;
3624         struct dcerpc_binding_handle *b = p->binding_handle;
3625
3626         r.in.handle = handle;
3627         r.in.enum_index = enum_index;
3628         r.in.value_offered = value_offered;
3629         r.in.data_offered = data_offered;
3630         r.out.data_needed = &data_needed;
3631         r.out.value_needed = &value_needed;
3632         r.out.type = &type;
3633         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3634         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3635
3636         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3637
3638         torture_assert_ntstatus_ok(tctx,
3639                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3640                 "EnumPrinterData failed");
3641
3642         if (type_p) {
3643                 *type_p = type;
3644         }
3645         if (value_needed_p) {
3646                 *value_needed_p = value_needed;
3647         }
3648         if (data_needed_p) {
3649                 *data_needed_p = data_needed;
3650         }
3651         if (value_name_p) {
3652                 *value_name_p = r.out.value_name;
3653         }
3654         if (data_p) {
3655                 *data_p = r.out.data;
3656         }
3657         if (result_p) {
3658                 *result_p = r.out.result;
3659         }
3660
3661         return true;
3662 }
3663
3664
3665 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3666                                      struct dcerpc_pipe *p,
3667                                      struct policy_handle *handle)
3668 {
3669         uint32_t enum_index = 0;
3670         enum winreg_Type type;
3671         uint32_t value_needed;
3672         uint32_t data_needed;
3673         uint8_t *data;
3674         const char *value_name;
3675         WERROR result;
3676
3677         torture_comment(tctx, "Testing EnumPrinterData\n");
3678
3679         do {
3680                 torture_assert(tctx,
3681                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3682                                              &type, &value_needed, &data_needed,
3683                                              &value_name, &data, &result),
3684                         "EnumPrinterData failed");
3685
3686                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3687                         break;
3688                 }
3689
3690                 torture_assert(tctx,
3691                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3692                                              &type, &value_needed, &data_needed,
3693                                              &value_name, &data, &result),
3694                         "EnumPrinterData failed");
3695
3696                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3697                         break;
3698                 }
3699
3700                 enum_index++;
3701
3702         } while (W_ERROR_IS_OK(result));
3703
3704         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3705
3706         return true;
3707 }
3708
3709 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3710                                    struct dcerpc_binding_handle *b,
3711                                    struct policy_handle *handle,
3712                                    const char *key_name,
3713                                    uint32_t *count_p,
3714                                    struct spoolss_PrinterEnumValues **info_p)
3715 {
3716         struct spoolss_EnumPrinterDataEx r;
3717         struct spoolss_PrinterEnumValues *info;
3718         uint32_t needed;
3719         uint32_t count;
3720
3721         r.in.handle = handle;
3722         r.in.key_name = key_name;
3723         r.in.offered = 0;
3724         r.out.needed = &needed;
3725         r.out.count = &count;
3726         r.out.info = &info;
3727
3728         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3729
3730         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3731                 "EnumPrinterDataEx failed");
3732         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3733                 r.in.offered = needed;
3734                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3735                         "EnumPrinterDataEx failed");
3736         }
3737
3738         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3739
3740         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3741
3742         if (count_p) {
3743                 *count_p = count;
3744         }
3745         if (info_p) {
3746                 *info_p = info;
3747         }
3748
3749         return true;
3750 }
3751
3752 static bool test_SetPrinterData(struct torture_context *tctx,
3753                                 struct dcerpc_binding_handle *b,
3754                                 struct policy_handle *handle,
3755                                 const char *value_name,
3756                                 enum winreg_Type type,
3757                                 uint8_t *data,
3758                                 uint32_t offered);
3759 static bool test_DeletePrinterData(struct torture_context *tctx,
3760                                    struct dcerpc_binding_handle *b,
3761                                    struct policy_handle *handle,
3762                                    const char *value_name);
3763
3764 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3765                                              struct dcerpc_pipe *p,
3766                                              struct policy_handle *handle)
3767 {
3768         uint32_t count;
3769         struct spoolss_PrinterEnumValues *info;
3770         int i;
3771         uint32_t value_needed, data_needed;
3772         uint32_t value_offered, data_offered;
3773         WERROR result;
3774         struct dcerpc_binding_handle *b = p->binding_handle;
3775
3776         enum winreg_Type type;
3777         DATA_BLOB blob;
3778
3779         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3780
3781         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3782         type = REG_SZ;
3783
3784         torture_assert(tctx,
3785                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3786                 "SetPrinterData failed");
3787
3788         blob = data_blob_string_const("torture_data2");
3789
3790         torture_assert(tctx,
3791                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3792                 "SetPrinterData failed");
3793
3794         blob = data_blob_talloc(tctx, NULL, 4);
3795         SIVAL(blob.data, 0, 0x11223344);
3796
3797         torture_assert(tctx,
3798                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3799                 "SetPrinterData failed");
3800
3801         torture_assert(tctx,
3802                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3803                 "failed to call EnumPrinterDataEx");
3804
3805         /* get the max sizes for value and data */
3806
3807         torture_assert(tctx,
3808                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3809                                      NULL, &value_needed, &data_needed,
3810                                      NULL, NULL, &result),
3811                 "EnumPrinterData failed");
3812         torture_assert_werr_ok(tctx, result, "unexpected result");
3813
3814         /* check if the reply from the EnumPrinterData really matches max values */
3815
3816         for (i=0; i < count; i++) {
3817                 if (info[i].value_name_len > value_needed) {
3818                         torture_fail(tctx,
3819                                 talloc_asprintf(tctx,
3820                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3821                                 info[i].value_name_len, value_needed));
3822                 }
3823                 if (info[i].data_length > data_needed) {
3824                         torture_fail(tctx,
3825                                 talloc_asprintf(tctx,
3826                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3827                                 info[i].data_length, data_needed));
3828                 }
3829         }
3830
3831         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3832          * sort or not sort the replies by value name, we should be able to do
3833          * the following entry comparison */
3834
3835         data_offered = data_needed;
3836         value_offered = value_needed;
3837
3838         for (i=0; i < count; i++) {
3839
3840                 const char *value_name;
3841                 uint8_t *data;
3842
3843                 torture_assert(tctx,
3844                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3845                                              &type, &value_needed, &data_needed,
3846                                              &value_name, &data, &result),
3847                         "EnumPrinterData failed");
3848
3849                 if (i -1 == count) {
3850                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3851                                 "unexpected result");
3852                         break;
3853                 } else {
3854                         torture_assert_werr_ok(tctx, result, "unexpected result");
3855                 }
3856
3857                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3858                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3859                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3860                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3861                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3862         }
3863
3864         torture_assert(tctx,
3865                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3866                 "DeletePrinterData failed");
3867         torture_assert(tctx,
3868                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3869                 "DeletePrinterData failed");
3870         torture_assert(tctx,
3871                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3872                 "DeletePrinterData failed");
3873
3874         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3875
3876         return true;
3877 }
3878
3879 static bool test_DeletePrinterData(struct torture_context *tctx,
3880                                    struct dcerpc_binding_handle *b,
3881                                    struct policy_handle *handle,
3882                                    const char *value_name)
3883 {
3884         NTSTATUS status;
3885         struct spoolss_DeletePrinterData r;
3886
3887         r.in.handle = handle;
3888         r.in.value_name = value_name;
3889
3890         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3891                 r.in.value_name);
3892
3893         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3894
3895         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3896         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3897
3898         return true;
3899 }
3900
3901 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3902                                      struct dcerpc_binding_handle *b,
3903                                      struct policy_handle *handle,
3904                                      const char *key_name,
3905                                      const char *value_name)
3906 {
3907         struct spoolss_DeletePrinterDataEx r;
3908
3909         r.in.handle = handle;
3910         r.in.key_name = key_name;
3911         r.in.value_name = value_name;
3912
3913         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3914                 r.in.key_name, r.in.value_name);
3915
3916         torture_assert_ntstatus_ok(tctx,
3917                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3918                 "DeletePrinterDataEx failed");
3919         torture_assert_werr_ok(tctx, r.out.result,
3920                 "DeletePrinterDataEx failed");
3921
3922         return true;
3923 }
3924
3925 static bool test_DeletePrinterKey(struct torture_context *tctx,
3926                                   struct dcerpc_binding_handle *b,
3927                                   struct policy_handle *handle,
3928                                   const char *key_name)
3929 {
3930         struct spoolss_DeletePrinterKey r;
3931
3932         r.in.handle = handle;
3933         r.in.key_name = key_name;
3934
3935         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3936
3937         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3938                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3939                 return true;
3940         }
3941
3942         torture_assert_ntstatus_ok(tctx,
3943                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3944                 "DeletePrinterKey failed");
3945         torture_assert_werr_ok(tctx, r.out.result,
3946                 "DeletePrinterKey failed");
3947
3948         return true;
3949 }
3950
3951 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3952                                  struct dcerpc_binding_handle *b,
3953                                  struct policy_handle *handle)
3954 {
3955         struct winreg_OpenHKLM r;
3956
3957         r.in.system_name = NULL;
3958         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3959         r.out.handle = handle;
3960
3961         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3962
3963         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3964         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3965
3966         return true;
3967 }
3968
3969 static void init_winreg_String(struct winreg_String *name, const char *s)
3970 {
3971         name->name = s;
3972         if (s) {
3973                 name->name_len = 2 * (strlen_m(s) + 1);
3974                 name->name_size = name->name_len;
3975         } else {
3976                 name->name_len = 0;
3977                 name->name_size = 0;
3978         }
3979 }
3980
3981 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3982                                      struct dcerpc_binding_handle *b,
3983                                      struct policy_handle *hive_handle,
3984                                      const char *keyname,
3985                                      uint32_t options,
3986                                      struct policy_handle *key_handle)
3987 {
3988         struct winreg_OpenKey r;
3989
3990         r.in.parent_handle = hive_handle;
3991         init_winreg_String(&r.in.keyname, keyname);
3992         r.in.options = options;
3993         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3994         r.out.handle = key_handle;
3995
3996         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3997
3998         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3999         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4000
4001         return true;
4002 }
4003
4004 static bool test_winreg_OpenKey(struct torture_context *tctx,
4005                                 struct dcerpc_binding_handle *b,
4006                                 struct policy_handle *hive_handle,
4007                                 const char *keyname,
4008                                 struct policy_handle *key_handle)
4009 {
4010         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4011                                         REG_OPTION_NON_VOLATILE, key_handle);
4012 }
4013
4014 static bool test_winreg_CloseKey(struct torture_context *tctx,
4015                                  struct dcerpc_binding_handle *b,
4016                                  struct policy_handle *handle)
4017 {
4018         struct winreg_CloseKey r;
4019
4020         r.in.handle = handle;
4021         r.out.handle = handle;
4022
4023         torture_comment(tctx, "Testing winreg_CloseKey\n");
4024
4025         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4026         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4027
4028         return true;
4029 }
4030
4031 bool test_winreg_QueryValue(struct torture_context *tctx,
4032                             struct dcerpc_binding_handle *b,
4033                             struct policy_handle *handle,
4034                             const char *value_name,
4035                             enum winreg_Type *type_p,
4036                             uint32_t *data_size_p,
4037                             uint32_t *data_length_p,
4038                             uint8_t **data_p)
4039 {
4040         struct winreg_QueryValue r;
4041         enum winreg_Type type = REG_NONE;
4042         uint32_t data_size = 0;
4043         uint32_t data_length = 0;
4044         struct winreg_String valuename;
4045         uint8_t *data = NULL;
4046
4047         init_winreg_String(&valuename, value_name);
4048
4049         data = talloc_zero_array(tctx, uint8_t, 0);
4050
4051         r.in.handle = handle;
4052         r.in.value_name = &valuename;
4053         r.in.type = &type;
4054         r.in.data_size = &data_size;
4055         r.in.data_length = &data_length;
4056         r.in.data = data;
4057         r.out.type = &type;
4058         r.out.data = data;
4059         r.out.data_size = &data_size;
4060         r.out.data_length = &data_length;
4061
4062         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4063
4064         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4065         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4066                 *r.in.data_size = *r.out.data_size;
4067                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4068                 r.in.data = data;
4069                 r.out.data = data;
4070                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4071         }
4072         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4073
4074         if (type_p) {
4075                 *type_p = *r.out.type;
4076         }
4077         if (data_size_p) {
4078                 *data_size_p = *r.out.data_size;
4079         }
4080         if (data_length_p) {
4081                 *data_length_p = *r.out.data_length;
4082         }
4083         if (data_p) {
4084                 *data_p = r.out.data;
4085         }
4086
4087         return true;
4088 }
4089
4090 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4091                                           struct dcerpc_binding_handle *b,
4092                                           struct policy_handle *handle,
4093                                           const char *printer_name,
4094                                           const char *key_name,
4095                                           const char *value_name,
4096                                           enum winreg_Type *w_type,
4097                                           uint32_t *w_size,
4098                                           uint32_t *w_length,
4099                                           uint8_t **w_data)
4100 {
4101         const char *printer_key;
4102         struct policy_handle key_handle;
4103
4104         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4105                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4106
4107         torture_assert(tctx,
4108                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4109
4110         torture_assert(tctx,
4111                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4112
4113         torture_assert(tctx,
4114                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4115
4116         return true;
4117 }
4118
4119 static bool test_GetForm_winreg(struct torture_context *tctx,
4120                                 struct dcerpc_binding_handle *b,
4121                                 struct policy_handle *handle,
4122                                 const char *key_name,
4123                                 const char *form_name,
4124                                 enum winreg_Type *w_type,
4125                                 uint32_t *w_size,
4126                                 uint32_t *w_length,
4127                                 uint8_t **w_data)
4128 {
4129         struct policy_handle key_handle;
4130
4131         torture_assert(tctx,
4132                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4133
4134         torture_assert(tctx,
4135                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4136
4137         torture_assert(tctx,
4138                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4139
4140         return true;
4141 }
4142
4143 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4144                                       struct dcerpc_binding_handle *b,
4145                                       struct policy_handle *handle,
4146                                       const char *symlink_keyname,
4147                                       const char *symlink_destination)
4148 {
4149         /* check if the first key is a symlink to the second key */
4150
4151         enum winreg_Type w_type;
4152         uint32_t w_size;
4153         uint32_t w_length;
4154         uint8_t *w_data;
4155         struct policy_handle key_handle;
4156         DATA_BLOB blob;
4157         const char *str;
4158
4159         if (torture_setting_bool(tctx, "samba3", false)) {
4160                 torture_skip(tctx, "skip winreg symlink test against samba");
4161         }
4162
4163         torture_assert(tctx,
4164                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4165                         "failed to open key link");
4166
4167         torture_assert(tctx,
4168                 test_winreg_QueryValue(tctx, b, &key_handle,
4169                                        "SymbolicLinkValue",
4170                                        &w_type, &w_size, &w_length, &w_data),
4171                 "failed to query for 'SymbolicLinkValue' attribute");
4172
4173         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4174
4175         blob = data_blob(w_data, w_size);
4176         str = reg_val_data_string(tctx, REG_SZ, blob);
4177
4178         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4179
4180         torture_assert(tctx,
4181                 test_winreg_CloseKey(tctx, b, &key_handle),
4182                 "failed to close key link");
4183
4184         return true;
4185 }
4186
4187 static const char *strip_unc(const char *unc)
4188 {
4189         char *name;
4190
4191         if (!unc) {
4192                 return NULL;
4193         }
4194
4195         if (unc[0] == '\\' && unc[1] == '\\') {
4196                 unc +=2;
4197         }
4198
4199         name = strchr(unc, '\\');
4200         if (name) {
4201                 return name+1;
4202         }
4203
4204         return unc;
4205 }
4206
4207 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4208                                        struct dcerpc_binding_handle *b,
4209                                        struct policy_handle *handle,
4210                                        const char *printer_name,
4211                                        struct dcerpc_binding_handle *winreg_handle,
4212                                        struct policy_handle *hive_handle)
4213 {
4214         union spoolss_PrinterInfo info;
4215         const char *keys[] = {
4216                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4217                 TOP_LEVEL_PRINT_PRINTERS_KEY
4218         };
4219         int i;
4220         const char *printername, *sharename;
4221
4222         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4223
4224         torture_assert(tctx,
4225                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4226                 "failed to get printer info level 2");
4227
4228         printername = strip_unc(info.info2.printername);
4229         sharename = strip_unc(info.info2.sharename);
4230
4231 #define test_sz(wname, iname) \
4232 do {\
4233         DATA_BLOB blob;\
4234         const char *str;\
4235         enum winreg_Type w_type;\
4236         uint32_t w_size;\
4237         uint32_t w_length;\
4238         uint8_t *w_data;\
4239         torture_assert(tctx,\
4240                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4241                                        &w_type, &w_size, &w_length, &w_data),\
4242                 "failed to query winreg");\
4243         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4244         blob = data_blob(w_data, w_size);\
4245         str = reg_val_data_string(tctx, REG_SZ, blob);\
4246         if (w_size == 2 && iname == NULL) {\
4247                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4248         } else {\
4249                 torture_assert_str_equal(tctx, str, iname,\
4250                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4251         }\
4252 } while(0);
4253
4254 #define test_dword(wname, iname) \
4255 do {\
4256         uint32_t value;\
4257         enum winreg_Type w_type;\
4258         uint32_t w_size;\
4259         uint32_t w_length;\
4260         uint8_t *w_data;\
4261         torture_assert(tctx,\
4262                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4263                                        &w_type, &w_size, &w_length, &w_data),\
4264                 "failed to query winreg");\
4265         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4266         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4267         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4268         value = IVAL(w_data, 0);\
4269         torture_assert_int_equal(tctx, value, iname,\
4270                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4271 } while(0);
4272
4273 #define test_dm(wname, iname) \
4274 do {\
4275         DATA_BLOB blob;\
4276         struct spoolss_DeviceMode dm;\
4277         enum ndr_err_code ndr_err;\
4278         enum winreg_Type w_type;\
4279         uint32_t w_size;\
4280         uint32_t w_length;\
4281         uint8_t *w_data;\
4282         torture_assert(tctx,\
4283                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4284                                        &w_type, &w_size, &w_length, &w_data),\
4285                 "failed to query winreg");\
4286         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4287         blob = data_blob(w_data, w_size);\
4288         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4289                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4290         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4291         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4292                 "dm unequal");\
4293 } while(0);
4294
4295 #define test_sd(wname, iname) \
4296 do {\
4297         DATA_BLOB blob;\
4298         struct security_descriptor sd;\
4299         enum ndr_err_code ndr_err;\
4300         enum winreg_Type w_type;\
4301         uint32_t w_size;\
4302         uint32_t w_length;\
4303         uint8_t *w_data;\
4304         torture_assert(tctx,\
4305                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4306                                        &w_type, &w_size, &w_length, &w_data),\
4307                 "failed to query winreg");\
4308         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4309         blob = data_blob(w_data, w_size);\
4310         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4311                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4312         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4313         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4314                 "sd unequal");\
4315 } while(0);
4316
4317 #define test_multi_sz(wname, iname) \
4318 do {\
4319         DATA_BLOB blob;\
4320         const char **array;\
4321         enum winreg_Type w_type;\
4322         uint32_t w_size;\
4323         uint32_t w_length;\
4324         uint8_t *w_data;\
4325         int i;\
4326         torture_assert(tctx,\
4327                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4328                                        &w_type, &w_size, &w_length, &w_data),\
4329                 "failed to query winreg");\
4330         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4331         blob = data_blob(w_data, w_size);\
4332         torture_assert(tctx, \
4333                 pull_reg_multi_sz(tctx, &blob, &array),\
4334                 "failed to pull multi sz");\
4335         for (i=0; array[i] != NULL; i++) {\
4336                 torture_assert_str_equal(tctx, array[i], iname[i],\
4337                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4338         }\
4339 } while(0);
4340
4341
4342         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4343                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4344                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4345         {
4346                 torture_warning(tctx, "failed to check for winreg symlink");
4347         }
4348
4349
4350         for (i=0; i < ARRAY_SIZE(keys); i++) {
4351
4352                 const char *printer_key;
4353                 struct policy_handle key_handle;
4354
4355                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4356                         keys[i], printer_name);
4357
4358                 torture_assert(tctx,
4359                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4360
4361                 test_sz("Name", printername);
4362                 test_sz("Share Name", sharename);
4363                 test_sz("Port", info.info2.portname);
4364                 test_sz("Printer Driver", info.info2.drivername);
4365                 test_sz("Description", info.info2.comment);
4366                 test_sz("Location", info.info2.location);
4367                 test_sz("Separator File", info.info2.sepfile);
4368                 test_sz("Print Processor", info.info2.printprocessor);
4369                 test_sz("Datatype", info.info2.datatype);
4370                 test_sz("Parameters", info.info2.parameters);
4371                 /* winreg: 0, spoolss not */
4372 /*              test_dword("Attributes", info.info2.attributes); */
4373                 test_dword("Priority", info.info2.priority);
4374                 test_dword("Default Priority", info.info2.defaultpriority);
4375                 /* winreg: 60, spoolss: 0 */
4376 /*              test_dword("StartTime", info.info2.starttime); */
4377 /*              test_dword("UntilTime", info.info2.untiltime); */
4378                 /* winreg != spoolss */
4379 /*              test_dword("Status", info.info2.status); */
4380                 test_dm("Default DevMode", info.info2.devmode);
4381                 test_sd("Security", info.info2.secdesc);
4382
4383                 torture_assert(tctx,
4384                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4385         }
4386
4387 #undef test_dm
4388 #undef test_sd
4389
4390         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4391
4392         return true;
4393 }
4394
4395 static bool test_PrintProcessors(struct torture_context *tctx,
4396                                  struct dcerpc_binding_handle *b,
4397                                  const char *environment,
4398                                  struct dcerpc_binding_handle *winreg_handle,
4399                                  struct policy_handle *hive_handle)
4400 {
4401         union spoolss_PrintProcessorInfo *info;
4402         uint32_t count;
4403         int i;
4404
4405         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4406
4407         torture_assert(tctx,
4408                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info),
4409                 "failed to enum print processors level 1");
4410
4411         for (i=0; i < count; i++) {
4412
4413                 const char *processor_key;
4414                 struct policy_handle key_handle;
4415
4416                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4417                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4418                                                 environment,
4419                                                 info[i].info1.print_processor_name);
4420
4421                 torture_assert(tctx,
4422                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4423
4424                 /* nothing to check in there so far */
4425
4426                 torture_assert(tctx,
4427                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4428         }
4429
4430         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4431
4432         return true;
4433 }
4434
4435 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4436                                          struct dcerpc_binding_handle *b,
4437                                          struct policy_handle *handle,
4438                                          const char *driver_name,
4439                                          const char *architecture,
4440                                          uint32_t level,
4441                                          uint32_t client_major_version,
4442                                          uint32_t client_minor_version,
4443                                          union spoolss_DriverInfo *info_p,
4444                                          WERROR *result);
4445
4446 static const char *strip_path(const char *path)
4447 {
4448         char *p;
4449
4450         if (path == NULL) {
4451                 return NULL;
4452         }
4453
4454         p = strrchr(path, '\\');
4455         if (p) {
4456                 return p+1;
4457         }
4458
4459         return path;
4460 }
4461
4462 static const char **strip_paths(const char **path_array)
4463 {
4464         int i;
4465
4466         if (path_array == NULL) {
4467                 return NULL;
4468         }
4469
4470         for (i=0; path_array[i] != NULL; i++) {
4471                 path_array[i] = strip_path(path_array[i]);
4472         }
4473
4474         return path_array;
4475 }
4476
4477 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4478 {
4479         time_t t;
4480         struct tm *tm;
4481         t = nt_time_to_unix(nt);
4482         tm = localtime(&t);
4483
4484         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4485                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4486 }
4487
4488 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4489 {
4490         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4491                 (unsigned)((v >> 48) & 0xFFFF),
4492                 (unsigned)((v >> 32) & 0xFFFF),
4493                 (unsigned)((v >> 16) & 0xFFFF),
4494                 (unsigned)(v & 0xFFFF));
4495 }
4496
4497 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4498                                       struct dcerpc_binding_handle *b,
4499                                       struct policy_handle *handle,
4500                                       const char *printer_name,
4501                                       const char *driver_name,
4502                                       const char *environment,
4503                                       struct dcerpc_binding_handle *winreg_handle,
4504                                       struct policy_handle *hive_handle)
4505 {
4506         WERROR result;
4507         union spoolss_DriverInfo info;
4508         const char *driver_key;
4509         struct policy_handle key_handle;
4510
4511         const char *driver_path;
4512         const char *data_file;
4513         const char *config_file;
4514         const char *help_file;
4515         const char **dependent_files;
4516
4517         const char *driver_date;
4518         const char *inbox_driver_date;
4519
4520         const char *driver_version;
4521         const char *inbox_driver_version;
4522
4523         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4524
4525         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4526                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4527                                      environment,
4528                                      3,
4529                                      driver_name);
4530
4531         torture_assert(tctx,
4532                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4533                 "failed to open driver key");
4534
4535         if (torture_setting_bool(tctx, "samba3", false)) {
4536                 goto try_level3;
4537         }
4538
4539         torture_assert(tctx,
4540                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4541                 "failed to get driver info level 8");
4542
4543         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4544                 goto try_level6;
4545         }
4546
4547         driver_path     = strip_path(info.info8.driver_path);
4548         data_file       = strip_path(info.info8.data_file);
4549         config_file     = strip_path(info.info8.config_file);
4550         help_file       = strip_path(info.info8.help_file);
4551         dependent_files = strip_paths(info.info8.dependent_files);
4552
4553         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4554         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4555
4556         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4557         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4558
4559         test_sz("Configuration File",           config_file);
4560         test_sz("Data File",                    data_file);
4561         test_sz("Datatype",                     info.info8.default_datatype);
4562         test_sz("Driver",                       driver_path);
4563         test_sz("DriverDate",                   driver_date);
4564         test_sz("DriverVersion",                driver_version);
4565         test_sz("HardwareID",                   info.info8.hardware_id);
4566         test_sz("Help File",                    help_file);
4567         test_sz("InfPath",                      info.info8.inf_path);
4568         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4569         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4570         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4571         test_sz("Monitor",                      info.info8.monitor_name);
4572         test_sz("OEM URL",                      info.info8.manufacturer_url);
4573         test_sz("Print Processor",              info.info8.print_processor);
4574         test_sz("Provider",                     info.info8.provider);
4575         test_sz("VendorSetup",                  info.info8.vendor_setup);
4576         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4577         test_multi_sz("Dependent Files",        dependent_files);
4578         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4579         test_multi_sz("Previous Names",         info.info8.previous_names);
4580 /*      test_dword("Attributes",                ?); */
4581         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4582         test_dword("Version",                   info.info8.version);
4583 /*      test_dword("TempDir",                   ?); */
4584
4585  try_level6:
4586
4587         torture_assert(tctx,
4588                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4589                 "failed to get driver info level 6");
4590
4591         driver_path     = strip_path(info.info6.driver_path);
4592         data_file       = strip_path(info.info6.data_file);
4593         config_file     = strip_path(info.info6.config_file);
4594         help_file       = strip_path(info.info6.help_file);
4595         dependent_files = strip_paths(info.info6.dependent_files);
4596
4597         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4598
4599         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4600
4601         test_sz("Configuration File",           config_file);
4602         test_sz("Data File",                    data_file);
4603         test_sz("Datatype",                     info.info6.default_datatype);
4604         test_sz("Driver",                       driver_path);
4605         test_sz("DriverDate",                   driver_date);
4606         test_sz("DriverVersion",                driver_version);
4607         test_sz("HardwareID",                   info.info6.hardware_id);
4608         test_sz("Help File",                    help_file);
4609         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4610         test_sz("Monitor",                      info.info6.monitor_name);
4611         test_sz("OEM URL",                      info.info6.manufacturer_url);
4612         test_sz("Provider",                     info.info6.provider);
4613         test_multi_sz("Dependent Files",        dependent_files);
4614         test_multi_sz("Previous Names",         info.info6.previous_names);
4615 /*      test_dword("Attributes",                ?); */
4616         test_dword("Version",                   info.info6.version);
4617 /*      test_dword("TempDir",                   ?); */
4618
4619  try_level3:
4620
4621         torture_assert(tctx,
4622                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4623                 "failed to get driver info level 3");
4624
4625         driver_path     = strip_path(info.info3.driver_path);
4626         data_file       = strip_path(info.info3.data_file);
4627         config_file     = strip_path(info.info3.config_file);
4628         help_file       = strip_path(info.info3.help_file);
4629         dependent_files = strip_paths(info.info3.dependent_files);
4630
4631         test_sz("Configuration File",           config_file);
4632         test_sz("Data File",                    data_file);
4633         test_sz("Datatype",                     info.info3.default_datatype);
4634         test_sz("Driver",                       driver_path);
4635         test_sz("Help File",                    help_file);
4636         test_sz("Monitor",                      info.info3.monitor_name);
4637         test_multi_sz("Dependent Files",        dependent_files);
4638 /*      test_dword("Attributes",                ?); */
4639         test_dword("Version",                   info.info3.version);
4640 /*      test_dword("TempDir",                   ?); */
4641
4642
4643         torture_assert(tctx,
4644                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4645
4646         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4647
4648         return true;
4649 }
4650
4651 #undef test_sz
4652 #undef test_dword
4653
4654 static bool test_SetPrinterData(struct torture_context *tctx,
4655                                 struct dcerpc_binding_handle *b,
4656                                 struct policy_handle *handle,
4657                                 const char *value_name,
4658                                 enum winreg_Type type,
4659                                 uint8_t *data,
4660                                 uint32_t offered)
4661 {
4662         struct spoolss_SetPrinterData r;
4663
4664         r.in.handle = handle;
4665         r.in.value_name = value_name;
4666         r.in.type = type;
4667         r.in.data = data;
4668         r.in.offered = offered;
4669
4670         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4671                 r.in.value_name);
4672
4673         torture_assert_ntstatus_ok(tctx,
4674                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4675                 "SetPrinterData failed");
4676         torture_assert_werr_ok(tctx, r.out.result,
4677                 "SetPrinterData failed");
4678
4679         return true;
4680 }
4681
4682 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4683                                        struct dcerpc_binding_handle *b,
4684                                        struct policy_handle *handle,
4685                                        const char *printer_name,
4686                                        struct dcerpc_binding_handle *winreg_handle,
4687                                        struct policy_handle *hive_handle)
4688 {
4689         const char *values[] = {
4690                 "spootyfoot",
4691                 "spooty\\foot",
4692 #if 0
4693         /* FIXME: not working with s3 atm. */
4694                 "spooty,foot",
4695                 "spooty,fo,ot",
4696 #endif
4697                 "spooty foot",
4698 #if 0
4699         /* FIXME: not working with s3 atm. */
4700                 "spooty\\fo,ot",
4701                 "spooty,fo\\ot"
4702 #endif
4703         };
4704         int i;
4705
4706         for (i=0; i < ARRAY_SIZE(values); i++) {
4707
4708                 enum winreg_Type type;
4709                 DATA_BLOB blob;
4710                 uint8_t *data;
4711                 uint32_t needed;
4712
4713                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4714                 type = REG_SZ;
4715
4716                 torture_assert(tctx,
4717                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4718                         "SetPrinterData failed");
4719
4720                 torture_assert(tctx,
4721                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4722                         "GetPrinterData failed");
4723
4724                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4725                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4726                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4727
4728                 if (winreg_handle && hive_handle) {
4729
4730                         enum winreg_Type w_type;
4731                         uint32_t w_size;
4732                         uint32_t w_length;
4733                         uint8_t *w_data;
4734
4735                         torture_assert(tctx,
4736                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4737                                         printer_name, "PrinterDriverData", values[i],
4738                                         &w_type, &w_size, &w_length, &w_data), "");
4739
4740                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4741                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4742                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4743                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4744                 }
4745
4746                 torture_assert(tctx,
4747                         test_DeletePrinterData(tctx, b, handle, values[i]),
4748                         "DeletePrinterData failed");
4749         }
4750
4751         return true;
4752 }
4753
4754
4755 static bool test_EnumPrinterKey(struct torture_context *tctx,
4756                                 struct dcerpc_binding_handle *b,
4757                                 struct policy_handle *handle,
4758                                 const char *key_name,
4759                                 const char ***array);
4760
4761 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4762                                   struct dcerpc_binding_handle *b,
4763                                   struct policy_handle *handle,
4764                                   const char *key_name,
4765                                   const char *value_name,
4766                                   enum winreg_Type type,
4767                                   uint8_t *data,
4768                                   uint32_t offered)
4769 {
4770         NTSTATUS status;
4771         struct spoolss_SetPrinterDataEx r;
4772
4773         r.in.handle = handle;
4774         r.in.key_name = key_name;
4775         r.in.value_name = value_name;
4776         r.in.type = type;
4777         r.in.data = data;
4778         r.in.offered = offered;
4779
4780         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4781                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4782
4783         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4784
4785         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4786         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4787
4788         return true;
4789 }
4790
4791 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4792                                        struct dcerpc_pipe *p,
4793                                        struct policy_handle *handle)
4794 {
4795         struct dcerpc_binding_handle *b = p->binding_handle;
4796         const char *value_name = "dog";
4797         const char *keys[] = {
4798                 "torturedataex",
4799                 "torture data ex",
4800                 "torturedataex_with_subkey\\subkey",
4801                 "torturedataex_with_subkey\\subkey:0",
4802                 "torturedataex_with_subkey\\subkey:1",
4803                 "torturedataex_with_subkey\\subkey\\subsubkey",
4804                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4805                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4806                 "torture,data",
4807                 "torture,data,ex",
4808                 "torture,data\\ex",
4809                 "torture\\data,ex",
4810                 "torture/data",
4811                 "torture/data ex",
4812                 "torture/data ex/sub",
4813                 "torture//data",
4814                 "torture//data ex",
4815                 "torture//data ex/sub",
4816                 "torture//data ex//sub",
4817         };
4818         int i;
4819
4820         for (i=0; i < ARRAY_SIZE(keys); i++) {
4821
4822                 char *c;
4823                 const char *key;
4824                 enum winreg_Type type;
4825                 DATA_BLOB blob_in, blob_out;
4826                 const char **subkeys;
4827                 uint32_t ecount;
4828                 struct spoolss_PrinterEnumValues *einfo;
4829                 uint32_t needed;
4830
4831                 if (torture_setting_bool(tctx, "samba3", false)) {
4832                         char *q;
4833                         q = strrchr(keys[i], '\\');
4834                         if (q) {
4835                                 torture_comment(tctx, "skipping keyname '%s' including '\\' character against Samba3\n",
4836                                                 keys[i]);
4837                                 continue;
4838                         }
4839                 }
4840
4841                 blob_in = data_blob_talloc(tctx, NULL, 42);
4842
4843                 generate_random_buffer(blob_in.data, blob_in.length);
4844
4845                 torture_assert(tctx,
4846                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4847                         "failed to call SetPrinterDataEx");
4848
4849                 torture_assert(tctx,
4850                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4851                         "failed to call GetPrinterDataEx");
4852
4853                 blob_out.length = needed;
4854                 torture_assert(tctx,
4855                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4856                         "failed to call EnumPrinterDataEx");
4857
4858                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4859                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4860                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4861
4862                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4863                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4864                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4865                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4866                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4867                 if (einfo[0].data_length > 0) {
4868                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4869                 }
4870
4871                 key = talloc_strdup(tctx, keys[i]);
4872
4873                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4874                         return false;
4875                 }
4876
4877                 c = strchr(key, '\\');
4878                 if (c) {
4879                         int k;
4880
4881                         /* we have subkeys */
4882
4883                         *c = 0;
4884
4885                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4886                                 return false;
4887                         }
4888
4889                         for (k=0; subkeys && subkeys[k]; k++) {
4890
4891                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4892
4893                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4894                                         return false;
4895                                 }
4896                         }
4897
4898                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4899                                 return false;
4900                         }
4901
4902                 } else {
4903                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4904                                 return false;
4905                         }
4906                 }
4907         }
4908
4909         return true;
4910 }
4911
4912 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
4913                                          struct dcerpc_pipe *p,
4914                                          struct policy_handle *handle)
4915 {
4916         struct dcerpc_binding_handle *b = p->binding_handle;
4917         const char *key = "torturedataex";
4918         const char *values[] = {
4919                 "torture_value",
4920                 "torture value",
4921                 "torture,value",
4922                 "torture/value",
4923                 "torture\\value",
4924                 "torture\\\\value"
4925         };
4926         int i;
4927
4928         for (i=0; i < ARRAY_SIZE(values); i++) {
4929
4930                 enum winreg_Type type;
4931                 DATA_BLOB blob_in, blob_out;
4932                 uint32_t ecount;
4933                 struct spoolss_PrinterEnumValues *einfo;
4934                 uint32_t needed;
4935
4936                 if (torture_setting_bool(tctx, "samba3", false)) {
4937                         char *q;
4938                         q = strrchr(values[i], ',');
4939                         if (q) {
4940                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
4941                                                 values[i]);
4942                                 continue;
4943                         }
4944                 }
4945
4946                 blob_in = data_blob_talloc(tctx, NULL, 42);
4947
4948                 generate_random_buffer(blob_in.data, blob_in.length);
4949
4950                 torture_assert(tctx,
4951                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
4952                         "failed to call SetPrinterDataEx");
4953
4954                 torture_assert(tctx,
4955                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
4956                         "failed to call GetPrinterDataEx");
4957
4958                 blob_out.length = needed;
4959                 torture_assert(tctx,
4960                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
4961                         "failed to call EnumPrinterDataEx");
4962
4963                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4964                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4965                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4966
4967                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4968                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
4969                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
4970                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4971                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4972                 if (einfo[0].data_length > 0) {
4973                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4974                 }
4975
4976                 torture_assert(tctx,
4977                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
4978                         "failed to call DeletePrinterDataEx");
4979         }
4980
4981         return true;
4982 }
4983
4984
4985 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4986                                          struct dcerpc_pipe *p,
4987                                          struct policy_handle *handle,
4988                                          const char *printername,
4989                                          struct dcerpc_binding_handle *winreg_handle,
4990                                          struct policy_handle *hive_handle)
4991 {
4992         struct dcerpc_binding_handle *b = p->binding_handle;
4993         const char *value_name = "dog";
4994         const char *key_name = "torturedataex";
4995         enum winreg_Type types[] = {
4996                 REG_SZ,
4997                 REG_MULTI_SZ,
4998                 REG_DWORD,
4999                 REG_BINARY
5000         };
5001         const char *str = "abcdefghi";
5002         int t, s;
5003
5004         for (t=0; t < ARRAY_SIZE(types); t++) {
5005         for (s=0; s < strlen(str); s++) {
5006
5007                 enum winreg_Type type;
5008                 const char *string = talloc_strndup(tctx, str, s);
5009                 const char *array[2];
5010                 DATA_BLOB blob = data_blob_string_const(string);
5011                 DATA_BLOB data;
5012                 uint8_t *data_out;
5013                 uint32_t needed, offered = 0;
5014                 uint32_t ecount;
5015                 struct spoolss_PrinterEnumValues *einfo;
5016
5017                 array[0] = talloc_strdup(tctx, string);
5018                 array[1] = NULL;
5019
5020                 if (types[t] == REG_DWORD) {
5021                         s = 0xffff;
5022                 }
5023
5024                 if (torture_setting_bool(tctx, "samba3", false)) {
5025                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
5026                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
5027                                 continue;
5028                         }
5029                 }
5030
5031                 switch (types[t]) {
5032                 case REG_BINARY:
5033                         data = blob;
5034                         offered = blob.length;
5035                         break;
5036                 case REG_DWORD:
5037                         data = data_blob_talloc(tctx, NULL, 4);
5038                         SIVAL(data.data, 0, 0x12345678);
5039                         offered = 4;
5040                         break;
5041                 case REG_SZ:
5042                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5043                         type = REG_SZ;
5044                         offered = data.length;
5045                         /*strlen_m_term(data.string)*2;*/
5046                         break;
5047                 case REG_MULTI_SZ:
5048                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5049                         type = REG_MULTI_SZ;
5050                         offered = data.length;
5051                         break;
5052                 default:
5053                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5054                 }
5055
5056                 torture_assert(tctx,
5057                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5058                         "failed to call SetPrinterDataEx");
5059
5060                 torture_assert(tctx,
5061                         test_GetPrinterDataEx(tctx, p, handle, key_name, value_name, &type, &data_out, &needed),
5062                         "failed to call GetPrinterDataEx");
5063
5064                 torture_assert(tctx,
5065                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5066                         "failed to call EnumPrinterDataEx");
5067
5068                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5069                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5070                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5071
5072                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5073                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5074                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5075                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5076                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5077                 if (einfo[0].data_length > 0) {
5078                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5079                 }
5080
5081                 if (winreg_handle && hive_handle) {
5082                         enum winreg_Type w_type;
5083                         uint32_t w_size;
5084                         uint32_t w_length;
5085                         uint8_t *w_data;
5086
5087                         torture_assert(tctx,
5088                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5089                                         printername, key_name, value_name,
5090                                         &w_type, &w_size, &w_length, &w_data), "");
5091
5092                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5093                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5094                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5095                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5096                 }
5097
5098                 torture_assert(tctx,
5099                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5100                         "failed to call DeletePrinterDataEx");
5101         }
5102         }
5103
5104         return true;
5105 }
5106
5107 static bool test_PrinterData_winreg(struct torture_context *tctx,
5108                                     struct dcerpc_pipe *p,
5109                                     struct policy_handle *handle,
5110                                     const char *printer_name)
5111 {
5112         struct dcerpc_binding_handle *b = p->binding_handle;
5113         struct dcerpc_pipe *p2;
5114         bool ret = true;
5115         struct policy_handle hive_handle;
5116         struct dcerpc_binding_handle *b2;
5117
5118         torture_assert_ntstatus_ok(tctx,
5119                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5120                 "could not open winreg pipe");
5121         b2 = p2->binding_handle;
5122
5123         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5124
5125         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5126         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5127
5128         test_winreg_CloseKey(tctx, b2, &hive_handle);
5129
5130         talloc_free(p2);
5131
5132         return ret;
5133 }
5134
5135 static bool test_Forms_winreg(struct torture_context *tctx,
5136                               struct dcerpc_binding_handle *b,
5137                               struct policy_handle *handle,
5138                               bool print_server,
5139                               const char *printer_name)
5140 {
5141         struct dcerpc_pipe *p2;
5142         bool ret = true;
5143         struct policy_handle hive_handle;
5144         struct dcerpc_binding_handle *b2;
5145
5146         torture_assert_ntstatus_ok(tctx,
5147                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5148                 "could not open winreg pipe");
5149         b2 = p2->binding_handle;
5150
5151         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5152
5153         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5154
5155         test_winreg_CloseKey(tctx, b2, &hive_handle);
5156
5157         talloc_free(p2);
5158
5159         return ret;
5160 }
5161
5162 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5163                                     struct dcerpc_pipe *p,
5164                                     struct policy_handle *handle,
5165                                     const char *printer_name)
5166 {
5167         struct dcerpc_binding_handle *b = p->binding_handle;
5168         struct dcerpc_pipe *p2;
5169         bool ret = true;
5170         struct policy_handle hive_handle;
5171         struct dcerpc_binding_handle *b2;
5172
5173         torture_assert_ntstatus_ok(tctx,
5174                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5175                 "could not open winreg pipe");
5176         b2 = p2->binding_handle;
5177
5178         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5179
5180         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5181
5182         test_winreg_CloseKey(tctx, b2, &hive_handle);
5183
5184         talloc_free(p2);
5185
5186         return ret;
5187 }
5188
5189 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5190                                    struct dcerpc_pipe *p,
5191                                    struct policy_handle *handle,
5192                                    const char *printer_name,
5193                                    const char *driver_name,
5194                                    const char *environment)
5195 {
5196         struct dcerpc_binding_handle *b = p->binding_handle;
5197         struct dcerpc_pipe *p2;
5198         bool ret = true;
5199         struct policy_handle hive_handle;
5200         struct dcerpc_binding_handle *b2;
5201
5202         torture_assert_ntstatus_ok(tctx,
5203                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5204                 "could not open winreg pipe");
5205         b2 = p2->binding_handle;
5206
5207         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5208
5209         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
5210
5211         test_winreg_CloseKey(tctx, b2, &hive_handle);
5212
5213         talloc_free(p2);
5214
5215         return ret;
5216 }
5217
5218 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5219                                         struct dcerpc_binding_handle *b,
5220                                         const char *environment)
5221 {
5222         struct dcerpc_pipe *p2;
5223         bool ret = true;
5224         struct policy_handle hive_handle;
5225         struct dcerpc_binding_handle *b2;
5226
5227         torture_assert_ntstatus_ok(tctx,
5228                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5229                 "could not open winreg pipe");
5230         b2 = p2->binding_handle;
5231
5232         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5233
5234         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5235
5236         test_winreg_CloseKey(tctx, b2, &hive_handle);
5237
5238         talloc_free(p2);
5239
5240         return ret;
5241 }
5242
5243 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5244                                        struct dcerpc_pipe *p,
5245                                        struct policy_handle *handle,
5246                                        const char *printer_name)
5247 {
5248         struct spoolss_SetPrinterInfoCtr info_ctr;
5249         struct spoolss_DevmodeContainer devmode_ctr;
5250         struct sec_desc_buf secdesc_ctr;
5251         union spoolss_SetPrinterInfo sinfo;
5252         union spoolss_PrinterInfo info;
5253         struct dcerpc_binding_handle *b = p->binding_handle;
5254         const char *pname;
5255
5256         ZERO_STRUCT(info_ctr);
5257         ZERO_STRUCT(devmode_ctr);
5258         ZERO_STRUCT(secdesc_ctr);
5259
5260         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5261
5262         torture_assert(tctx,
5263                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5264                 "failed to query Printer level 2");
5265
5266         torture_assert(tctx,
5267                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5268                 "failed to convert");
5269
5270         info_ctr.level = 2;
5271         info_ctr.info = sinfo;
5272
5273 #define TEST_SZ(wname, iname) \
5274 do {\
5275         enum winreg_Type type;\
5276         uint8_t *data;\
5277         uint32_t needed;\
5278         DATA_BLOB blob;\
5279         const char *str;\
5280         torture_assert(tctx,\
5281                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5282                 "failed to query");\
5283         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5284         blob = data_blob_const(data, needed);\
5285         torture_assert(tctx,\
5286                 pull_reg_sz(tctx, &blob, &str),\
5287                 "failed to pull REG_SZ");\
5288         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5289 } while(0);
5290
5291
5292 #define TEST_SET_SZ(wname, iname, val) \
5293 do {\
5294         enum winreg_Type type;\
5295         uint8_t *data;\
5296         uint32_t needed;\
5297         DATA_BLOB blob;\
5298         const char *str;\
5299         sinfo.info2->iname = val;\
5300         torture_assert(tctx,\
5301                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5302                 "failed to call SetPrinter");\
5303         torture_assert(tctx,\
5304                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5305                 "failed to query");\
5306         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5307         blob = data_blob_const(data, needed);\
5308         torture_assert(tctx,\
5309                 pull_reg_sz(tctx, &blob, &str),\
5310                 "failed to pull REG_SZ");\
5311         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5312 } while(0);
5313
5314 #define TEST_SET_DWORD(wname, iname, val) \
5315 do {\
5316         enum winreg_Type type;\
5317         uint8_t *data;\
5318         uint32_t needed;\
5319         uint32_t value;\
5320         sinfo.info2->iname = val;\
5321         torture_assert(tctx,\
5322                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5323                 "failed to call SetPrinter");\
5324         torture_assert(tctx,\
5325                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5326                 "failed to query");\
5327         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5328         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5329         value = IVAL(data, 0); \
5330         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5331 } while(0);
5332
5333         TEST_SET_SZ("description", comment, "newval");
5334         TEST_SET_SZ("location", location, "newval");
5335 /*      TEST_SET_DWORD("priority", priority, 25); */
5336
5337         torture_assert(tctx,
5338                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5339                 "failed to query Printer level 2");
5340
5341         TEST_SZ("description", info.info2.comment);
5342 /*      TEST_SZ("driverName", info.info2.drivername); */
5343         TEST_SZ("location", info.info2.location);
5344
5345         pname = strrchr(info.info2.printername, '\\');
5346         if (pname == NULL) {
5347                 pname = info.info2.printername;
5348         } else {
5349                 pname++;
5350         }
5351 /*      TEST_SZ("printerName", pname); */
5352         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5353         /* TEST_SZ("printShareName", info.info2.sharename); */
5354
5355         /* FIXME gd: complete the list */
5356
5357 #undef TEST_SZ
5358 #undef TEST_SET_SZ
5359 #undef TEST_DWORD
5360
5361         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5362
5363         return true;
5364 }
5365
5366 static bool test_print_processors_winreg(struct torture_context *tctx,
5367                                          void *private_data)
5368 {
5369         struct test_spoolss_context *ctx =
5370                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5371         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5372         struct dcerpc_binding_handle *b = p->binding_handle;
5373
5374         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5375 }
5376
5377 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5378                                          struct dcerpc_binding_handle *b,
5379                                          struct policy_handle *handle,
5380                                          uint32_t *change_id)
5381 {
5382         enum winreg_Type type;
5383         uint8_t *data;
5384         uint32_t needed;
5385
5386         torture_assert(tctx,
5387                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5388                 "failed to call GetPrinterData");
5389
5390         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5391         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5392
5393         *change_id = IVAL(data, 0);
5394
5395         return true;
5396 }
5397
5398 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5399                                            struct dcerpc_pipe *p,
5400                                            struct policy_handle *handle,
5401                                            uint32_t *change_id)
5402 {
5403         enum winreg_Type type;
5404         uint8_t *data;
5405         uint32_t needed;
5406
5407         torture_assert(tctx,
5408                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5409                 "failed to call GetPrinterData");
5410
5411         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5412         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5413
5414         *change_id = IVAL(data, 0);
5415
5416         return true;
5417 }
5418
5419 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5420                                          struct dcerpc_binding_handle *b,
5421                                          struct policy_handle *handle,
5422                                          uint32_t *change_id)
5423 {
5424         union spoolss_PrinterInfo info;
5425
5426         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5427                 "failed to query Printer level 0");
5428
5429         *change_id = info.info0.change_id;
5430
5431         return true;
5432 }
5433
5434 static bool test_ChangeID(struct torture_context *tctx,
5435                           struct dcerpc_pipe *p,
5436                           struct policy_handle *handle)
5437 {
5438         uint32_t change_id, change_id_ex, change_id_info;
5439         uint32_t change_id2, change_id_ex2, change_id_info2;
5440         union spoolss_PrinterInfo info;
5441         const char *comment;
5442         struct dcerpc_binding_handle *b = p->binding_handle;
5443
5444         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5445
5446         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5447                 "failed to query for ChangeID");
5448         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5449                 "failed to query for ChangeID");
5450         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5451                 "failed to query for ChangeID");
5452
5453         torture_assert_int_equal(tctx, change_id, change_id_ex,
5454                 "change_ids should all be equal");
5455         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5456                 "change_ids should all be equal");
5457
5458
5459         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5460
5461         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5462                 "failed to query for ChangeID");
5463         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5464                 "failed to query Printer level 2");
5465         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5466                 "failed to query for ChangeID");
5467         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5468                 "failed to query for ChangeID");
5469         torture_assert_int_equal(tctx, change_id, change_id_ex,
5470                 "change_id should not have changed");
5471         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5472                 "change_id should not have changed");
5473
5474
5475         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5476
5477         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5478                 "failed to query for ChangeID");
5479         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5480                 "failed to query for ChangeID");
5481         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5482                 "failed to query for ChangeID");
5483         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5484                 "failed to query Printer level 2");
5485         comment = talloc_strdup(tctx, info.info2.comment);
5486
5487         {
5488                 struct spoolss_SetPrinterInfoCtr info_ctr;
5489                 struct spoolss_DevmodeContainer devmode_ctr;
5490                 struct sec_desc_buf secdesc_ctr;
5491                 union spoolss_SetPrinterInfo sinfo;
5492
5493                 ZERO_STRUCT(info_ctr);
5494                 ZERO_STRUCT(devmode_ctr);
5495                 ZERO_STRUCT(secdesc_ctr);
5496
5497
5498                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5499                 sinfo.info2->comment    = "torture_comment";
5500
5501                 info_ctr.level = 2;
5502                 info_ctr.info = sinfo;
5503
5504                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5505                         "failed to call SetPrinter");
5506
5507                 sinfo.info2->comment    = comment;
5508
5509                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5510                         "failed to call SetPrinter");
5511
5512         }
5513
5514         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5515                 "failed to query for ChangeID");
5516         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5517                 "failed to query for ChangeID");
5518         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5519                 "failed to query for ChangeID");
5520
5521         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5522                 "change_ids should all be equal");
5523         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5524                 "change_ids should all be equal");
5525
5526         torture_assert(tctx, (change_id < change_id2),
5527                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5528                 change_id2, change_id));
5529         torture_assert(tctx, (change_id_ex < change_id_ex2),
5530                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5531                 change_id_ex2, change_id_ex));
5532         torture_assert(tctx, (change_id_info < change_id_info2),
5533                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5534                 change_id_info2, change_id_info));
5535
5536         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5537
5538         return true;
5539 }
5540
5541 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5542                                        struct dcerpc_pipe *p,
5543                                        struct policy_handle *handle)
5544 {
5545         NTSTATUS status;
5546         struct dcerpc_binding *b;
5547         struct dcerpc_pipe *p2;
5548         struct spoolss_ClosePrinter cp;
5549
5550         /* only makes sense on SMB */
5551         if (p->conn->transport.transport != NCACN_NP) {
5552                 return true;
5553         }
5554
5555         torture_comment(tctx, "Testing close on secondary pipe\n");
5556
5557         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5558         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5559
5560         status = dcerpc_secondary_connection(p, &p2, b);
5561         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5562
5563         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5564         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5565
5566         cp.in.handle = handle;
5567         cp.out.handle = handle;
5568
5569         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5570         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5571                         "ERROR: Allowed close on secondary connection");
5572
5573         talloc_free(p2);
5574
5575         return true;
5576 }
5577
5578 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5579                                      struct dcerpc_binding_handle *b, const char *name)
5580 {
5581         NTSTATUS status;
5582         struct spoolss_OpenPrinter op;
5583         struct spoolss_OpenPrinterEx opEx;
5584         struct policy_handle handle;
5585         bool ret = true;
5586
5587         op.in.printername       = name;
5588         op.in.datatype          = NULL;
5589         op.in.devmode_ctr.devmode= NULL;
5590         op.in.access_mask       = 0;
5591         op.out.handle           = &handle;
5592
5593         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5594
5595         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5596         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5597         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5598                 "unexpected result");
5599
5600         if (W_ERROR_IS_OK(op.out.result)) {
5601                 ret &=test_ClosePrinter(tctx, b, &handle);
5602         }
5603
5604         opEx.in.printername             = name;
5605         opEx.in.datatype                = NULL;
5606         opEx.in.devmode_ctr.devmode     = NULL;
5607         opEx.in.access_mask             = 0;
5608         opEx.in.level                   = 1;
5609         opEx.in.userlevel.level1        = NULL;
5610         opEx.out.handle                 = &handle;
5611
5612         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5613
5614         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5615         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5616         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5617                 "unexpected result");
5618
5619         if (W_ERROR_IS_OK(opEx.out.result)) {
5620                 ret &=test_ClosePrinter(tctx, b, &handle);
5621         }
5622
5623         return ret;
5624 }
5625
5626 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5627                                           void *private_data)
5628 {
5629         struct test_spoolss_context *ctx =
5630                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5631
5632         const char *badnames[] = {
5633                 "__INVALID_PRINTER__",
5634                 "\\\\__INVALID_HOST__",
5635                 "",
5636                 "\\\\\\",
5637                 "\\\\\\__INVALID_PRINTER__"
5638         };
5639         const char *badname;
5640         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5641         const char *server_name = dcerpc_server_name(p);
5642         struct dcerpc_binding_handle *b = p->binding_handle;
5643         int i;
5644
5645         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5646                 torture_assert(tctx,
5647                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5648                         "");
5649         }
5650
5651         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5652         torture_assert(tctx,
5653                 test_OpenPrinter_badname(tctx, b, badname),
5654                 "");
5655
5656         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5657         torture_assert(tctx,
5658                 test_OpenPrinter_badname(tctx, b, badname),
5659                 "");
5660
5661         return true;
5662 }
5663
5664 static bool test_OpenPrinter(struct torture_context *tctx,
5665                              struct dcerpc_pipe *p,
5666                              const char *name,
5667                              const char *environment)
5668 {
5669         NTSTATUS status;
5670         struct spoolss_OpenPrinter r;
5671         struct policy_handle handle;
5672         bool ret = true;
5673         struct dcerpc_binding_handle *b = p->binding_handle;
5674
5675         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5676         r.in.datatype           = NULL;
5677         r.in.devmode_ctr.devmode= NULL;
5678         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5679         r.out.handle            = &handle;
5680
5681         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5682
5683         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5684
5685         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5686
5687         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5688
5689         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5690                 ret = false;
5691         }
5692
5693         if (!torture_setting_bool(tctx, "samba3", false)) {
5694                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5695                         ret = false;
5696                 }
5697         }
5698
5699         if (!test_ClosePrinter(tctx, b, &handle)) {
5700                 ret = false;
5701         }
5702
5703         return ret;
5704 }
5705
5706 static bool call_OpenPrinterEx(struct torture_context *tctx,
5707                                struct dcerpc_pipe *p,
5708                                const char *name,
5709                                struct spoolss_DeviceMode *devmode,
5710                                struct policy_handle *handle)
5711 {
5712         struct spoolss_OpenPrinterEx r;
5713         struct spoolss_UserLevel1 userlevel1;
5714         NTSTATUS status;
5715         struct dcerpc_binding_handle *b = p->binding_handle;
5716
5717         if (name && name[0]) {
5718                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5719                                                    dcerpc_server_name(p), name);
5720         } else {
5721                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5722                                                    dcerpc_server_name(p));
5723         }
5724
5725         r.in.datatype           = NULL;
5726         r.in.devmode_ctr.devmode= devmode;
5727         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5728         r.in.level              = 1;
5729         r.in.userlevel.level1   = &userlevel1;
5730         r.out.handle = handle;
5731
5732         userlevel1.size = 1234;
5733         userlevel1.client = "hello";
5734         userlevel1.user = "spottyfoot!";
5735         userlevel1.build = 1;
5736         userlevel1.major = 2;
5737         userlevel1.minor = 3;
5738         userlevel1.processor = 4;
5739
5740         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5741
5742         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5743
5744         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5745
5746         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5747
5748         return true;
5749 }
5750
5751 static bool test_printer_rename(struct torture_context *tctx,
5752                                 void *private_data)
5753 {
5754         struct torture_printer_context *t =
5755                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5756         struct dcerpc_pipe *p = t->spoolss_pipe;
5757
5758         bool ret = true;
5759         union spoolss_PrinterInfo info;
5760         union spoolss_SetPrinterInfo sinfo;
5761         struct spoolss_SetPrinterInfoCtr info_ctr;
5762         struct spoolss_DevmodeContainer devmode_ctr;
5763         struct sec_desc_buf secdesc_ctr;
5764         const char *printer_name;
5765         const char *printer_name_orig;
5766         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5767         struct policy_handle new_handle;
5768         const char *q;
5769         struct dcerpc_binding_handle *b = p->binding_handle;
5770
5771         ZERO_STRUCT(devmode_ctr);
5772         ZERO_STRUCT(secdesc_ctr);
5773
5774         torture_comment(tctx, "Testing Printer rename operations\n");
5775
5776         torture_assert(tctx,
5777                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5778                 "failed to call GetPrinter level 2");
5779
5780         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5781
5782         q = strrchr(info.info2.printername, '\\');
5783         if (q) {
5784                 torture_warning(tctx,
5785                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5786         }
5787
5788         torture_assert(tctx,
5789                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5790
5791         sinfo.info2->printername = printer_name_new;
5792
5793         info_ctr.level = 2;
5794         info_ctr.info = sinfo;
5795
5796         torture_assert(tctx,
5797                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5798                 "failed to call SetPrinter level 2");
5799
5800         torture_assert(tctx,
5801                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5802                 "failed to call GetPrinter level 2");
5803
5804         printer_name = talloc_strdup(tctx, info.info2.printername);
5805
5806         q = strrchr(info.info2.printername, '\\');
5807         if (q) {
5808                 torture_warning(tctx,
5809                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5810                 q++;
5811                 printer_name = q;
5812         }
5813
5814         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5815                 "new printer name was not set");
5816
5817         /* samba currently cannot fully rename printers */
5818         if (!torture_setting_bool(tctx, "samba3", false)) {
5819                 torture_assert(tctx,
5820                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5821                         "still can open printer with oldname after rename");
5822         } else {
5823                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5824         }
5825
5826         torture_assert(tctx,
5827                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5828                 "failed to open printer with new name");
5829
5830         torture_assert(tctx,
5831                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5832                 "failed to call GetPrinter level 2");
5833
5834         /* FIXME: we openend with servername! */
5835         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5836                 dcerpc_server_name(p), printer_name_new);
5837
5838         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5839                 "new printer name was not set");
5840
5841         torture_assert(tctx,
5842                 test_ClosePrinter(tctx, b, &new_handle),
5843                 "failed to close printer");
5844
5845         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5846
5847         return ret;
5848 }
5849
5850
5851 static bool test_OpenPrinterEx(struct torture_context *tctx,
5852                                struct dcerpc_pipe *p,
5853                                const char *name,
5854                                const char *environment)
5855 {
5856         struct policy_handle handle;
5857         bool ret = true;
5858         struct dcerpc_binding_handle *b = p->binding_handle;
5859
5860         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5861                 return false;
5862         }
5863
5864         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5865                 ret = false;
5866         }
5867
5868         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5869                 ret = false;
5870         }
5871
5872         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5873                 ret = false;
5874         }
5875
5876         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5877                 ret = false;
5878         }
5879
5880         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5881                 ret = false;
5882         }
5883
5884         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5885                 ret = false;
5886         }
5887
5888         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5889                 ret = false;
5890         }
5891
5892         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5893                 ret = false;
5894         }
5895
5896         if (!test_printer_all_keys(tctx, b, &handle)) {
5897                 ret = false;
5898         }
5899
5900         if (!test_PausePrinter(tctx, b, &handle)) {
5901                 ret = false;
5902         }
5903
5904         if (!test_DoPrintTest(tctx, b, &handle)) {
5905                 ret = false;
5906         }
5907
5908         if (!test_ResumePrinter(tctx, b, &handle)) {
5909                 ret = false;
5910         }
5911
5912         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5913                 ret = false;
5914         }
5915
5916         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5917                 ret = false;
5918         }
5919
5920         if (!torture_setting_bool(tctx, "samba3", false)) {
5921                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5922                         ret = false;
5923                 }
5924         }
5925
5926         if (!test_ClosePrinter(tctx, b, &handle)) {
5927                 ret = false;
5928         }
5929
5930         return ret;
5931 }
5932
5933 static bool test_EnumPrinters_old(struct torture_context *tctx,
5934                                   void *private_data)
5935 {
5936         struct test_spoolss_context *ctx =
5937                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5938         struct spoolss_EnumPrinters r;
5939         NTSTATUS status;
5940         uint16_t levels[] = {1, 2, 4, 5};
5941         int i;
5942         bool ret = true;
5943         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5944         struct dcerpc_binding_handle *b = p->binding_handle;
5945
5946         for (i=0;i<ARRAY_SIZE(levels);i++) {
5947                 union spoolss_PrinterInfo *info;
5948                 int j;
5949                 uint32_t needed;
5950                 uint32_t count;
5951
5952                 r.in.flags      = PRINTER_ENUM_LOCAL;
5953                 r.in.server     = "";
5954                 r.in.level      = levels[i];
5955                 r.in.buffer     = NULL;
5956                 r.in.offered    = 0;
5957                 r.out.needed    = &needed;
5958                 r.out.count     = &count;
5959                 r.out.info      = &info;
5960
5961                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5962
5963                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5964                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5965
5966                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5967                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5968                         r.in.buffer = &blob;
5969                         r.in.offered = needed;
5970                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5971                 }
5972
5973                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5974
5975                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5976
5977                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
5978
5979                 if (!info) {
5980                         torture_comment(tctx, "No printers returned\n");
5981                         return true;
5982                 }
5983
5984                 for (j=0;j<count;j++) {
5985                         if (r.in.level == 1) {
5986                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5987                                 char *slash, *name;
5988                                 name = unc;
5989                                 if (unc[0] == '\\' && unc[1] == '\\') {
5990                                         unc +=2;
5991                                 }
5992                                 slash = strchr(unc, '\\');
5993                                 if (slash) {
5994                                         slash++;
5995                                         name = slash;
5996                                 }
5997                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment)) {
5998                                         ret = false;
5999                                 }
6000                                 if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
6001                                         ret = false;
6002                                 }
6003                         }
6004                 }
6005         }
6006
6007         return ret;
6008 }
6009
6010 static bool test_GetPrinterDriver(struct torture_context *tctx,
6011                                   struct dcerpc_binding_handle *b,
6012                                   struct policy_handle *handle,
6013                                   const char *driver_name)
6014 {
6015         struct spoolss_GetPrinterDriver r;
6016         uint32_t needed;
6017
6018         r.in.handle = handle;
6019         r.in.architecture = "W32X86";
6020         r.in.level = 1;
6021         r.in.buffer = NULL;
6022         r.in.offered = 0;
6023         r.out.needed = &needed;
6024
6025         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6026
6027         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6028                 "failed to call GetPrinterDriver");
6029         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6030                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6031                 r.in.buffer = &blob;
6032                 r.in.offered = needed;
6033                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6034                         "failed to call GetPrinterDriver");
6035         }
6036
6037         torture_assert_werr_ok(tctx, r.out.result,
6038                 "failed to call GetPrinterDriver");
6039
6040         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6041
6042         return true;
6043 }
6044
6045 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6046                                          struct dcerpc_binding_handle *b,
6047                                          struct policy_handle *handle,
6048                                          const char *driver_name,
6049                                          const char *architecture,
6050                                          uint32_t level,
6051                                          uint32_t client_major_version,
6052                                          uint32_t client_minor_version,
6053                                          union spoolss_DriverInfo *info_p,
6054                                          WERROR *result_p)
6055
6056 {
6057         struct spoolss_GetPrinterDriver2 r;
6058         uint32_t needed;
6059         uint32_t server_major_version;
6060         uint32_t server_minor_version;
6061
6062         r.in.handle = handle;
6063         r.in.architecture = architecture;
6064         r.in.client_major_version = client_major_version;
6065         r.in.client_minor_version = client_minor_version;
6066         r.in.buffer = NULL;
6067         r.in.offered = 0;
6068         r.in.level = level;
6069         r.out.needed = &needed;
6070         r.out.server_major_version = &server_major_version;
6071         r.out.server_minor_version = &server_minor_version;
6072
6073         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6074                 driver_name, r.in.level);
6075
6076         torture_assert_ntstatus_ok(tctx,
6077                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6078                 "failed to call GetPrinterDriver2");
6079         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6080                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6081                 r.in.buffer = &blob;
6082                 r.in.offered = needed;
6083                 torture_assert_ntstatus_ok(tctx,
6084                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6085                         "failed to call GetPrinterDriver2");
6086         }
6087
6088         if (result_p) {
6089                 *result_p = r.out.result;
6090         }
6091
6092         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6093                 switch (r.in.level) {
6094                 case 101:
6095                 case 8:
6096                         torture_comment(tctx,
6097                                 "level %d not implemented, not considering as an error\n",
6098                                 r.in.level);
6099                         return true;
6100                 default:
6101                         break;
6102                 }
6103         }
6104
6105         torture_assert_werr_ok(tctx, r.out.result,
6106                 "failed to call GetPrinterDriver2");
6107
6108         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6109
6110         if (info_p) {
6111                 *info_p = *r.out.info;
6112         }
6113
6114         return true;
6115 }
6116
6117 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6118                                    struct dcerpc_binding_handle *b,
6119                                    struct policy_handle *handle,
6120                                    const char *driver_name,
6121                                    const char *architecture)
6122 {
6123         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6124         int i;
6125
6126
6127         for (i=0;i<ARRAY_SIZE(levels);i++) {
6128
6129                 torture_assert(tctx,
6130                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6131                         "");
6132         }
6133
6134         return true;
6135 }
6136
6137 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6138                                         void *private_data)
6139 {
6140         struct test_spoolss_context *ctx =
6141                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6142         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6143         int i;
6144         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6145         struct dcerpc_binding_handle *b = p->binding_handle;
6146         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6147
6148         for (i=0;i<ARRAY_SIZE(levels);i++) {
6149
6150                 uint32_t count;
6151                 union spoolss_DriverInfo *info;
6152
6153                 torture_assert(tctx,
6154                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6155                         "failed to enumerate drivers");
6156
6157                 if (!info) {
6158                         torture_comment(tctx, "No printer drivers returned\n");
6159                         break;
6160                 }
6161         }
6162
6163         return true;
6164 }
6165
6166 static bool test_DeletePrinter(struct torture_context *tctx,
6167                                struct dcerpc_binding_handle *b,
6168                                struct policy_handle *handle)
6169 {
6170         struct spoolss_DeletePrinter r;
6171
6172         torture_comment(tctx, "Testing DeletePrinter\n");
6173
6174         r.in.handle = handle;
6175
6176         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6177                 "failed to delete printer");
6178         torture_assert_werr_ok(tctx, r.out.result,
6179                 "failed to delete printer");
6180
6181         return true;
6182 }
6183
6184 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6185                                        struct dcerpc_binding_handle *b,
6186                                        uint32_t flags,
6187                                        uint32_t level,
6188                                        const char *name,
6189                                        bool *found)
6190 {
6191         struct spoolss_EnumPrinters e;
6192         uint32_t count;
6193         union spoolss_PrinterInfo *info;
6194         uint32_t needed;
6195         int i;
6196
6197         *found = false;
6198
6199         e.in.flags = flags;
6200         e.in.server = NULL;
6201         e.in.level = level;
6202         e.in.buffer = NULL;
6203         e.in.offered = 0;
6204         e.out.count = &count;
6205         e.out.info = &info;
6206         e.out.needed = &needed;
6207
6208         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6209                 "failed to enum printers");
6210
6211         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6212                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6213                 e.in.buffer = &blob;
6214                 e.in.offered = needed;
6215
6216                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6217                         "failed to enum printers");
6218         }
6219
6220         torture_assert_werr_ok(tctx, e.out.result,
6221                 "failed to enum printers");
6222
6223         for (i=0; i < count; i++) {
6224
6225                 const char *current = NULL;
6226                 const char *q;
6227
6228                 switch (level) {
6229                 case 1:
6230                         current = info[i].info1.name;
6231                         break;
6232                 }
6233
6234                 if (strequal(current, name)) {
6235                         *found = true;
6236                         break;
6237                 }
6238
6239                 q = strrchr(current, '\\');
6240                 if (q) {
6241                         if (!e.in.server) {
6242                                 torture_warning(tctx,
6243                                         "server returns printername %s incl. servername although we did not set servername", current);
6244                         }
6245                         q++;
6246                         if (strequal(q, name)) {
6247                                 *found = true;
6248                                 break;
6249                         }
6250                 }
6251         }
6252
6253         return true;
6254 }
6255
6256 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6257                                       struct dcerpc_pipe *p,
6258                                       const char *printername,
6259                                       bool ex)
6260 {
6261         WERROR result;
6262         struct spoolss_AddPrinter r;
6263         struct spoolss_AddPrinterEx rex;
6264         struct spoolss_SetPrinterInfoCtr info_ctr;
6265         struct spoolss_SetPrinterInfo1 info1;
6266         struct spoolss_DevmodeContainer devmode_ctr;
6267         struct sec_desc_buf secdesc_ctr;
6268         struct spoolss_UserLevelCtr userlevel_ctr;
6269         struct policy_handle handle;
6270         bool found = false;
6271         struct dcerpc_binding_handle *b = p->binding_handle;
6272
6273         ZERO_STRUCT(devmode_ctr);
6274         ZERO_STRUCT(secdesc_ctr);
6275         ZERO_STRUCT(userlevel_ctr);
6276         ZERO_STRUCT(info1);
6277
6278         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6279                         ex ? "Ex":"", printername);
6280
6281         /* try to add printer to wellknown printer list (level 1) */
6282
6283         userlevel_ctr.level = 1;
6284
6285         info_ctr.info.info1 = &info1;
6286         info_ctr.level = 1;
6287
6288         rex.in.server = NULL;
6289         rex.in.info_ctr = &info_ctr;
6290         rex.in.devmode_ctr = &devmode_ctr;
6291         rex.in.secdesc_ctr = &secdesc_ctr;
6292         rex.in.userlevel_ctr = &userlevel_ctr;
6293         rex.out.handle = &handle;
6294
6295         r.in.server = NULL;
6296         r.in.info_ctr = &info_ctr;
6297         r.in.devmode_ctr = &devmode_ctr;
6298         r.in.secdesc_ctr = &secdesc_ctr;
6299         r.out.handle = &handle;
6300
6301         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6302                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6303                 "failed to add printer");
6304         result = ex ? rex.out.result : r.out.result;
6305         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6306                 "unexpected result code");
6307
6308         info1.name = printername;
6309         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6310
6311         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6312                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6313                 "failed to add printer");
6314         result = ex ? rex.out.result : r.out.result;
6315         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6316                 "unexpected result code");
6317
6318         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6319            better do a real check to see the printer is really there */
6320
6321         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6322                                                         PRINTER_ENUM_NETWORK, 1,
6323                                                         printername,
6324                                                         &found),
6325                         "failed to enum printers");
6326
6327         torture_assert(tctx, found, "failed to find newly added printer");
6328
6329         info1.flags = 0;
6330
6331         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6332                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6333                 "failed to add printer");
6334         result = ex ? rex.out.result : r.out.result;
6335         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6336                 "unexpected result code");
6337
6338         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6339            better do a real check to see the printer has really been removed
6340            from the well known printer list */
6341
6342         found = false;
6343
6344         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6345                                                         PRINTER_ENUM_NETWORK, 1,
6346                                                         printername,
6347                                                         &found),
6348                         "failed to enum printers");
6349 #if 0
6350         torture_assert(tctx, !found, "printer still in well known printer list");
6351 #endif
6352         return true;
6353 }
6354
6355 static bool test_AddPrinter_normal(struct torture_context *tctx,
6356                                    struct dcerpc_pipe *p,
6357                                    struct policy_handle *handle_p,
6358                                    const char *printername,
6359                                    const char *drivername,
6360                                    const char *portname,
6361                                    struct spoolss_DeviceMode *devmode,
6362                                    bool ex)
6363 {
6364         WERROR result;
6365         struct spoolss_AddPrinter r;
6366         struct spoolss_AddPrinterEx rex;
6367         struct spoolss_SetPrinterInfoCtr info_ctr;
6368         struct spoolss_SetPrinterInfo2 info2;
6369         struct spoolss_DevmodeContainer devmode_ctr;
6370         struct sec_desc_buf secdesc_ctr;
6371         struct spoolss_UserLevelCtr userlevel_ctr;
6372         struct policy_handle handle;
6373         bool found = false;
6374         bool existing_printer_deleted = false;
6375         struct dcerpc_binding_handle *b = p->binding_handle;
6376
6377         ZERO_STRUCT(devmode_ctr);
6378         ZERO_STRUCT(secdesc_ctr);
6379         ZERO_STRUCT(userlevel_ctr);
6380
6381         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6382                         ex ? "Ex":"", printername);
6383
6384         devmode_ctr.devmode = devmode;
6385
6386         userlevel_ctr.level = 1;
6387
6388         rex.in.server = NULL;
6389         rex.in.info_ctr = &info_ctr;
6390         rex.in.devmode_ctr = &devmode_ctr;
6391         rex.in.secdesc_ctr = &secdesc_ctr;
6392         rex.in.userlevel_ctr = &userlevel_ctr;
6393         rex.out.handle = &handle;
6394
6395         r.in.server = NULL;
6396         r.in.info_ctr = &info_ctr;
6397         r.in.devmode_ctr = &devmode_ctr;
6398         r.in.secdesc_ctr = &secdesc_ctr;
6399         r.out.handle = &handle;
6400
6401  again:
6402
6403         /* try to add printer to printer list (level 2) */
6404
6405         ZERO_STRUCT(info2);
6406
6407         info_ctr.info.info2 = &info2;
6408         info_ctr.level = 2;
6409
6410         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6411                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6412                 "failed to add printer");
6413         result = ex ? rex.out.result : r.out.result;
6414         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6415                 "unexpected result code");
6416
6417         info2.printername = printername;
6418
6419         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6420                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6421                 "failed to add printer");
6422         result = ex ? rex.out.result : r.out.result;
6423
6424         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6425                 struct policy_handle printer_handle;
6426
6427                 if (existing_printer_deleted) {
6428                         torture_fail(tctx, "already deleted printer still existing?");
6429                 }
6430
6431                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6432                         "failed to open printer handle");
6433
6434                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6435                         "failed to delete printer");
6436
6437                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6438                         "failed to close server handle");
6439
6440                 existing_printer_deleted = true;
6441
6442                 goto again;
6443         }
6444
6445         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6446                 "unexpected result code");
6447
6448         info2.portname = portname;
6449
6450         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6451                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6452                 "failed to add printer");
6453         result = ex ? rex.out.result : r.out.result;
6454         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6455                 "unexpected result code");
6456
6457         info2.drivername = drivername;
6458
6459         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6460                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6461                 "failed to add printer");
6462         result = ex ? rex.out.result : r.out.result;
6463
6464         /* w2k8r2 allows to add printer w/o defining printprocessor */
6465
6466         if (!W_ERROR_IS_OK(result)) {
6467                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6468                         "unexpected result code");
6469
6470                 info2.printprocessor = "winprint";
6471
6472                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6473                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6474                         "failed to add printer");
6475                 result = ex ? rex.out.result : r.out.result;
6476                 torture_assert_werr_ok(tctx, result,
6477                         "failed to add printer");
6478         }
6479
6480         *handle_p = handle;
6481
6482         /* we are paranoid, really check if the printer is there now */
6483
6484         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6485                                                         PRINTER_ENUM_LOCAL, 1,
6486                                                         printername,
6487                                                         &found),
6488                         "failed to enum printers");
6489         torture_assert(tctx, found, "failed to find newly added printer");
6490
6491         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6492                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6493                 "failed to add printer");
6494         result = ex ? rex.out.result : r.out.result;
6495         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6496                 "unexpected result code");
6497
6498         return true;
6499 }
6500
6501 static bool test_printer_info(struct torture_context *tctx,
6502                               void *private_data)
6503 {
6504         struct torture_printer_context *t =
6505                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6506         struct dcerpc_pipe *p = t->spoolss_pipe;
6507         struct dcerpc_binding_handle *b = p->binding_handle;
6508
6509         bool ret = true;
6510
6511         if (torture_setting_bool(tctx, "samba3", false)) {
6512                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6513         }
6514
6515         if (!test_PrinterInfo(tctx, b, &t->handle)) {
6516                 ret = false;
6517         }
6518
6519         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6520                 ret = false;
6521         }
6522
6523         return ret;
6524 }
6525
6526 static bool test_EnumPrinterKey(struct torture_context *tctx,
6527                                 struct dcerpc_binding_handle *b,
6528                                 struct policy_handle *handle,
6529                                 const char *key_name,
6530                                 const char ***array)
6531 {
6532         struct spoolss_EnumPrinterKey r;
6533         uint32_t needed = 0;
6534         union spoolss_KeyNames key_buffer;
6535         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6536         uint32_t _ndr_size;
6537         int i;
6538
6539         r.in.handle = handle;
6540         r.in.key_name = key_name;
6541         r.out.key_buffer = &key_buffer;
6542         r.out.needed = &needed;
6543         r.out._ndr_size = &_ndr_size;
6544
6545         for (i=0; i < ARRAY_SIZE(offered); i++) {
6546
6547                 if (offered[i] < 0 && needed) {
6548                         if (needed <= 4) {
6549                                 continue;
6550                         }
6551                         r.in.offered = needed + offered[i];
6552                 } else {
6553                         r.in.offered = offered[i];
6554                 }
6555
6556                 ZERO_STRUCT(key_buffer);
6557
6558                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6559
6560                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6561                         "failed to call EnumPrinterKey");
6562                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6563
6564                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6565                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6566                                         _ndr_size, r.in.offered/2));
6567
6568                         r.in.offered = needed;
6569                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6570                                 "failed to call EnumPrinterKey");
6571                 }
6572
6573                 if (offered[i] > 0) {
6574                         torture_assert_werr_ok(tctx, r.out.result,
6575                                 "failed to call EnumPrinterKey");
6576                 }
6577
6578                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6579                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6580                                 _ndr_size, r.in.offered/2));
6581
6582                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6583                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6584
6585                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6586                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6587
6588                 if (key_buffer.string_array) {
6589                         uint32_t calc_needed = 0;
6590                         int s;
6591                         for (s=0; key_buffer.string_array[s]; s++) {
6592                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6593                         }
6594                         if (!key_buffer.string_array[0]) {
6595                                 calc_needed += 2;
6596                         }
6597                         calc_needed += 2;
6598
6599                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6600                                 "EnumPrinterKey unexpected size");
6601                 }
6602         }
6603
6604         if (array) {
6605                 *array = key_buffer.string_array;
6606         }
6607
6608         return true;
6609 }
6610
6611 bool test_printer_all_keys(struct torture_context *tctx,
6612                            struct dcerpc_binding_handle *b,
6613                            struct policy_handle *handle)
6614 {
6615         const char **key_array = NULL;
6616         int i;
6617
6618         torture_comment(tctx, "Testing Printer Keys\n");
6619
6620         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6621                 "failed to call test_EnumPrinterKey");
6622
6623         for (i=0; key_array && key_array[i]; i++) {
6624                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6625                         "failed to call test_EnumPrinterKey");
6626         }
6627         for (i=0; key_array && key_array[i]; i++) {
6628                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6629                         "failed to call test_EnumPrinterDataEx");
6630         }
6631
6632         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6633
6634         return true;
6635 }
6636
6637 static bool test_csetprinter(struct torture_context *tctx,
6638                              void *private_data)
6639 {
6640         struct torture_printer_context *t =
6641                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6642         struct dcerpc_pipe *p = t->spoolss_pipe;
6643
6644         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
6645         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6646         const char *portname = t->info2.portname;
6647
6648         union spoolss_PrinterInfo info;
6649         struct policy_handle new_handle, new_handle2;
6650         struct dcerpc_binding_handle *b = p->binding_handle;
6651
6652         torture_comment(tctx, "Testing c_setprinter\n");
6653
6654         torture_assert(tctx,
6655                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6656                 "failed to get level 0 printer info");
6657         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6658                 info.info0.c_setprinter);
6659
6660         /* check if c_setprinter on 1st handle increases after a printer has
6661          * been added */
6662
6663         torture_assert(tctx,
6664                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6665                 "failed to add new printer");
6666         torture_assert(tctx,
6667                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6668                 "failed to get level 0 printer info");
6669         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6670                 info.info0.c_setprinter);
6671
6672         /* check if c_setprinter on new handle increases after a printer has
6673          * been added */
6674
6675         torture_assert(tctx,
6676                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6677                 "failed to get level 0 printer info");
6678         torture_comment(tctx, "csetprinter on created handle: %d\n",
6679                 info.info0.c_setprinter);
6680
6681         /* open the new printer and check if c_setprinter increases */
6682
6683         torture_assert(tctx,
6684                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6685                 "failed to open created printer");
6686         torture_assert(tctx,
6687                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6688                 "failed to get level 0 printer info");
6689         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6690                 info.info0.c_setprinter);
6691
6692         /* cleanup */
6693
6694         torture_assert(tctx,
6695                 test_ClosePrinter(tctx, b, &new_handle2),
6696                 "failed to close printer");
6697         torture_assert(tctx,
6698                 test_DeletePrinter(tctx, b, &new_handle),
6699                 "failed to delete new printer");
6700
6701         return true;
6702 }
6703
6704 static bool compose_local_driver_directory(struct torture_context *tctx,
6705                                            const char *environment,
6706                                            const char *local_dir,
6707                                            const char **path)
6708 {
6709         char *p;
6710
6711         p = strrchr(local_dir, '/');
6712         if (!p) {
6713                 return NULL;
6714         }
6715         p++;
6716
6717         if (strequal(environment, "Windows x64")) {
6718                 if (!strequal(p, "x64")) {
6719                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6720                 }
6721         } else if (strequal(environment, "Windows NT x86")) {
6722                 if (!strequal(p, "i386")) {
6723                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6724                 }
6725         } else {
6726                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6727         }
6728
6729         return true;
6730 }
6731
6732 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6733                                                      const char *devicename)
6734 {
6735         struct spoolss_DeviceMode *r;
6736
6737         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6738         if (r == NULL) {
6739                 return NULL;
6740         }
6741
6742         r->devicename           = talloc_strdup(r, devicename);
6743         r->specversion          = DMSPEC_NT4_AND_ABOVE;
6744         r->driverversion        = 0x0600;
6745         r->size                 = 0x00dc;
6746         r->__driverextra_length = 0;
6747         r->fields               = DEVMODE_FORMNAME |
6748                                   DEVMODE_TTOPTION |
6749                                   DEVMODE_PRINTQUALITY |
6750                                   DEVMODE_DEFAULTSOURCE |
6751                                   DEVMODE_COPIES |
6752                                   DEVMODE_SCALE |
6753                                   DEVMODE_PAPERSIZE |
6754                                   DEVMODE_ORIENTATION;
6755         r->orientation          = DMORIENT_PORTRAIT;
6756         r->papersize            = DMPAPER_LETTER;
6757         r->paperlength          = 0;
6758         r->paperwidth           = 0;
6759         r->scale                = 100;
6760         r->copies               = 55;
6761         r->defaultsource        = DMBIN_FORMSOURCE;
6762         r->printquality         = DMRES_HIGH;
6763         r->color                = DMRES_MONOCHROME;
6764         r->duplex               = DMDUP_SIMPLEX;
6765         r->yresolution          = 0;
6766         r->ttoption             = DMTT_SUBDEV;
6767         r->collate              = DMCOLLATE_FALSE;
6768         r->formname             = talloc_strdup(r, "Letter");
6769
6770         return r;
6771 }
6772
6773 static bool test_architecture_buffer(struct torture_context *tctx,
6774                                      void *private_data)
6775 {
6776         struct test_spoolss_context *ctx =
6777                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6778
6779         struct spoolss_OpenPrinterEx r;
6780         struct spoolss_UserLevel1 u1;
6781         struct policy_handle handle;
6782         uint32_t architectures[] = {
6783                 PROCESSOR_ARCHITECTURE_INTEL,
6784                 PROCESSOR_ARCHITECTURE_IA64,
6785                 PROCESSOR_ARCHITECTURE_AMD64
6786         };
6787         uint32_t needed[3];
6788         int i;
6789         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6790         struct dcerpc_binding_handle *b = p->binding_handle;
6791
6792         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6793
6794                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6795
6796                 u1.size = 0;
6797                 u1.client = NULL;
6798                 u1.user = NULL;
6799                 u1.build = 0;
6800                 u1.major = 3;
6801                 u1.minor = 0;
6802                 u1.processor = architectures[i];
6803
6804                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6805                 r.in.datatype           = NULL;
6806                 r.in.devmode_ctr.devmode= NULL;
6807                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6808                 r.in.level               = 1;
6809                 r.in.userlevel.level1   = &u1;
6810                 r.out.handle            = &handle;
6811
6812                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6813                 torture_assert_werr_ok(tctx, r.out.result, "");
6814
6815                 {
6816                         struct spoolss_EnumPrinters e;
6817                         uint32_t count;
6818                         union spoolss_PrinterInfo *info;
6819
6820                         e.in.flags = PRINTER_ENUM_LOCAL;
6821                         e.in.server = NULL;
6822                         e.in.level = 2;
6823                         e.in.buffer = NULL;
6824                         e.in.offered = 0;
6825                         e.out.count = &count;
6826                         e.out.info = &info;
6827                         e.out.needed = &needed[i];
6828
6829                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6830 #if 0
6831                         torture_comment(tctx, "needed was %d\n", needed[i]);
6832 #endif
6833                 }
6834
6835                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6836         }
6837
6838         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6839                 if (needed[i-1] != needed[i]) {
6840                         torture_fail(tctx,
6841                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6842                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6843                 }
6844         }
6845
6846         return true;
6847 }
6848
6849 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
6850                                           void *private_data)
6851 {
6852         struct test_spoolss_context *ctx =
6853                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6854         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6855         struct dcerpc_binding_handle *b = p->binding_handle;
6856
6857         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
6858 }
6859
6860 static bool test_PrintServer_Forms(struct torture_context *tctx,
6861                                    void *private_data)
6862 {
6863         struct test_spoolss_context *ctx =
6864                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6865         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6866         struct dcerpc_binding_handle *b = p->binding_handle;
6867
6868         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
6869 }
6870
6871 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
6872                                        void *private_data)
6873 {
6874         struct test_spoolss_context *ctx =
6875                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6876         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6877         struct dcerpc_binding_handle *b = p->binding_handle;
6878
6879         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
6880 }
6881
6882 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
6883 {
6884         NTSTATUS status;
6885
6886         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
6887
6888         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
6889
6890         torture_assert(tctx,
6891                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
6892                 "failed to open printserver");
6893         torture_assert(tctx,
6894                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
6895                 "failed to get environment");
6896
6897         return true;
6898 }
6899
6900 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
6901 {
6902         struct test_spoolss_context *t;
6903
6904         *data = t = talloc_zero(tctx, struct test_spoolss_context);
6905
6906         return torture_rpc_spoolss_setup_common(tctx, t);
6907 }
6908
6909 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
6910 {
6911         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
6912
6913         return true;
6914 }
6915
6916 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
6917 {
6918         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
6919         bool ret;
6920
6921         ret = torture_rpc_spoolss_teardown_common(tctx, t);
6922         talloc_free(t);
6923
6924         return ret;
6925 }
6926
6927 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
6928 {
6929         struct dcerpc_pipe *p;
6930         struct dcerpc_binding_handle *b;
6931         const char *server_name_slash;
6932         const char *driver_name;
6933         const char *printer_name;
6934         const char *port_name;
6935
6936         torture_assert_ntstatus_ok(tctx,
6937                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
6938                 "Error connecting to server");
6939
6940         p = t->spoolss_pipe;
6941         b = p->binding_handle;
6942         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6943
6944         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
6945         t->driver.info8.driver_name             = TORTURE_DRIVER;
6946         t->driver.info8.driver_path             = "pscript5.dll";
6947         t->driver.info8.data_file               = "cups6.ppd";
6948         t->driver.info8.config_file             = "ps5ui.dll";
6949         t->driver.info8.help_file               = "pscript.hlp";
6950         t->driver.info8.default_datatype        = "RAW";
6951         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
6952         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6953         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6954         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6955         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6956         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6957         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6958         t->driver.info8.dependent_files->string[5] = "cups6.ini";
6959         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6960         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6961
6962         t->driver.local.driver_directory= "/usr/share/cups/drivers";
6963
6964         t->info2.drivername             = "Microsoft XPS Document Writer";
6965         t->info2.portname               = "LPT1:";
6966
6967         printer_name = t->info2.printername;
6968         port_name = t->info2.portname;
6969
6970         torture_assert(tctx,
6971                 fillup_printserver_info(tctx, p, &t->driver),
6972                 "failed to fillup printserver info");
6973
6974         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6975
6976         torture_assert(tctx,
6977                 compose_local_driver_directory(tctx, t->driver.remote.environment,
6978                                                t->driver.local.driver_directory,
6979                                                &t->driver.local.driver_directory),
6980                 "failed to compose local driver directory");
6981
6982         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6983                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
6984                         t->info2.drivername, t->driver.remote.environment);
6985                 t->have_driver = true;
6986                 goto try_add;
6987         }
6988
6989         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6990                 t->info2.drivername, t->driver.remote.environment);
6991         torture_comment(tctx, "trying to upload own driver\n");
6992
6993         if (!directory_exist(t->driver.local.driver_directory)) {
6994                 torture_warning(tctx, "no local driver is available!");
6995                 t->have_driver = false;
6996                 goto try_add;
6997         }
6998
6999         torture_assert(tctx,
7000                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7001                 "failed to upload printer driver");
7002
7003         torture_assert(tctx,
7004                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
7005                 "failed to add driver");
7006
7007         t->added_driver = true;
7008         t->have_driver = true;
7009
7010  try_add:
7011         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7012
7013         if (t->wellknown) {
7014                 torture_assert(tctx,
7015                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7016                         "failed to add wellknown printer");
7017         } else {
7018                 torture_assert(tctx,
7019                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7020                         "failed to add printer");
7021         }
7022
7023         return true;
7024 }
7025
7026 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7027 {
7028         struct torture_printer_context *t;
7029
7030         *data = t = talloc_zero(tctx, struct torture_printer_context);
7031
7032         t->ex                   = false;
7033         t->wellknown            = false;
7034         t->info2.printername    = TORTURE_PRINTER;
7035         t->devmode              = NULL;
7036
7037         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7038 }
7039
7040 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7041 {
7042         struct torture_printer_context *t;
7043
7044         *data = t = talloc_zero(tctx, struct torture_printer_context);
7045
7046         t->ex                   = true;
7047         t->wellknown            = false;
7048         t->info2.printername    = TORTURE_PRINTER_EX;
7049         t->devmode              = NULL;
7050
7051         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7052 }
7053
7054 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7055 {
7056         struct torture_printer_context *t;
7057
7058         *data = t = talloc_zero(tctx, struct torture_printer_context);
7059
7060         t->ex                   = false;
7061         t->wellknown            = true;
7062         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
7063         t->devmode              = NULL;
7064
7065         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7066                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7067         }
7068
7069         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7070 }
7071
7072 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7073 {
7074         struct torture_printer_context *t;
7075
7076         *data = t = talloc_zero(tctx, struct torture_printer_context);
7077
7078         t->ex                   = true;
7079         t->wellknown            = true;
7080         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7081         t->devmode              = NULL;
7082
7083         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7084                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7085         }
7086
7087         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7088 }
7089
7090 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7091 {
7092         struct torture_printer_context *t;
7093
7094         *data = t = talloc_zero(tctx, struct torture_printer_context);
7095
7096         t->ex                   = true;
7097         t->wellknown            = false;
7098         t->info2.printername    = TORTURE_PRINTER_EX;
7099         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7100
7101         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7102 }
7103
7104 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7105 {
7106         bool found = false;
7107         struct dcerpc_pipe *p = t->spoolss_pipe;
7108         struct dcerpc_binding_handle *b;
7109         const char *printer_name = t->info2.printername;
7110
7111         if (t->added_driver) {
7112                 torture_assert(tctx,
7113                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7114                         "failed to remove printer driver");
7115         }
7116
7117         if (p) {
7118                 b = p->binding_handle;
7119         }
7120
7121         if (!t->wellknown) {
7122                 torture_assert(tctx,
7123                         test_DeletePrinter(tctx, b, &t->handle),
7124                         "failed to delete printer");
7125
7126                 torture_assert(tctx,
7127                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7128                                                    printer_name, &found),
7129                         "failed to enumerate printers");
7130
7131                 torture_assert(tctx, !found, "deleted printer still there");
7132         }
7133
7134         return true;
7135 }
7136
7137 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7138 {
7139         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7140         bool ret;
7141
7142         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7143         talloc_free(t);
7144
7145         return ret;
7146 }
7147
7148 static bool test_print_test(struct torture_context *tctx,
7149                             void *private_data)
7150 {
7151         struct torture_printer_context *t =
7152                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7153         struct dcerpc_pipe *p = t->spoolss_pipe;
7154         struct dcerpc_binding_handle *b = p->binding_handle;
7155
7156         torture_assert(tctx,
7157                 test_PausePrinter(tctx, b, &t->handle),
7158                 "failed to pause printer");
7159
7160         torture_assert(tctx,
7161                 test_DoPrintTest(tctx, b, &t->handle),
7162                 "failed to do print test");
7163
7164         torture_assert(tctx,
7165                 test_ResumePrinter(tctx, b, &t->handle),
7166                 "failed to resume printer");
7167
7168         return true;
7169 }
7170
7171 static bool test_print_test_extended(struct torture_context *tctx,
7172                                      void *private_data)
7173 {
7174         struct torture_printer_context *t =
7175                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7176         struct dcerpc_pipe *p = t->spoolss_pipe;
7177         struct dcerpc_binding_handle *b = p->binding_handle;
7178         bool ret = true;
7179
7180         torture_assert(tctx,
7181                 test_PausePrinter(tctx, b, &t->handle),
7182                 "failed to pause printer");
7183
7184         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7185         if (ret == false) {
7186                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7187                 if (torture_setting_bool(tctx, "samba3", false)) {
7188                         torture_comment(tctx, "non-critical for samba3\n");
7189                         ret = true;
7190                         tctx->last_result = TORTURE_SKIP;
7191                 }
7192         }
7193
7194         torture_assert(tctx,
7195                 test_ResumePrinter(tctx, b, &t->handle),
7196                 "failed to resume printer");
7197
7198         return ret;
7199 }
7200
7201 static bool test_printer_sd(struct torture_context *tctx,
7202                             void *private_data)
7203 {
7204         struct torture_printer_context *t =
7205                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7206         struct dcerpc_pipe *p = t->spoolss_pipe;
7207         struct dcerpc_binding_handle *b = p->binding_handle;
7208
7209         torture_assert(tctx,
7210                 test_PrinterInfo_SD(tctx, b, &t->handle),
7211                 "failed to test security descriptors");
7212
7213         return true;
7214 }
7215
7216 static bool test_printer_dm(struct torture_context *tctx,
7217                             void *private_data)
7218 {
7219         struct torture_printer_context *t =
7220                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7221         struct dcerpc_pipe *p = t->spoolss_pipe;
7222
7223         torture_assert(tctx,
7224                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7225                 "failed to test devicemodes");
7226
7227         return true;
7228 }
7229
7230 static bool test_printer_info_winreg(struct torture_context *tctx,
7231                                      void *private_data)
7232 {
7233         struct torture_printer_context *t =
7234                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7235         struct dcerpc_pipe *p = t->spoolss_pipe;
7236
7237         torture_assert(tctx,
7238                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7239                 "failed to test printer info winreg");
7240
7241         return true;
7242 }
7243
7244 static bool test_printer_change_id(struct torture_context *tctx,
7245                                    void *private_data)
7246 {
7247         struct torture_printer_context *t =
7248                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7249         struct dcerpc_pipe *p = t->spoolss_pipe;
7250
7251         torture_assert(tctx,
7252                 test_ChangeID(tctx, p, &t->handle),
7253                 "failed to test change id");
7254
7255         return true;
7256 }
7257
7258 static bool test_printer_keys(struct torture_context *tctx,
7259                               void *private_data)
7260 {
7261         struct torture_printer_context *t =
7262                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7263         struct dcerpc_pipe *p = t->spoolss_pipe;
7264         struct dcerpc_binding_handle *b = p->binding_handle;
7265
7266         torture_assert(tctx,
7267                 test_printer_all_keys(tctx, b, &t->handle),
7268                 "failed to test printer keys");
7269
7270         return true;
7271 }
7272
7273 static bool test_printer_data_consistency(struct torture_context *tctx,
7274                                           void *private_data)
7275 {
7276         struct torture_printer_context *t =
7277                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7278         struct dcerpc_pipe *p = t->spoolss_pipe;
7279
7280         torture_assert(tctx,
7281                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7282                 "failed to test printer data consistency");
7283
7284         return true;
7285 }
7286
7287 static bool test_printer_data_keys(struct torture_context *tctx,
7288                                    void *private_data)
7289 {
7290         struct torture_printer_context *t =
7291                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7292         struct dcerpc_pipe *p = t->spoolss_pipe;
7293
7294         torture_assert(tctx,
7295                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7296                 "failed to test printer data keys");
7297
7298         return true;
7299 }
7300
7301 static bool test_printer_data_values(struct torture_context *tctx,
7302                                      void *private_data)
7303 {
7304         struct torture_printer_context *t =
7305                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7306         struct dcerpc_pipe *p = t->spoolss_pipe;
7307
7308         torture_assert(tctx,
7309                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7310                 "failed to test printer data values");
7311
7312         return true;
7313 }
7314
7315 static bool test_printer_data_set(struct torture_context *tctx,
7316                                   void *private_data)
7317 {
7318         struct torture_printer_context *t =
7319                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7320         struct dcerpc_pipe *p = t->spoolss_pipe;
7321
7322         torture_assert(tctx,
7323                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7324                 "failed to test printer data set");
7325
7326         return true;
7327 }
7328
7329 static bool test_printer_data_winreg(struct torture_context *tctx,
7330                                      void *private_data)
7331 {
7332         struct torture_printer_context *t =
7333                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7334         struct dcerpc_pipe *p = t->spoolss_pipe;
7335
7336         torture_assert(tctx,
7337                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7338                 "failed to test printer data winreg");
7339
7340         return true;
7341 }
7342
7343 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7344                                         void *private_data)
7345 {
7346         struct torture_printer_context *t =
7347                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7348         struct dcerpc_pipe *p = t->spoolss_pipe;
7349
7350         torture_assert(tctx,
7351                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7352                 "failed to test printer data winreg dsspooler");
7353
7354         return true;
7355 }
7356
7357 static bool test_driver_info_winreg(struct torture_context *tctx,
7358                                     void *private_data)
7359 {
7360         struct torture_printer_context *t =
7361                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7362         struct dcerpc_pipe *p = t->spoolss_pipe;
7363         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7364
7365         if (!t->have_driver) {
7366                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7367         }
7368
7369         torture_assert(tctx,
7370                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7371                 "failed to test driver info winreg");
7372
7373         return true;
7374 }
7375
7376 void torture_tcase_printer(struct torture_tcase *tcase)
7377 {
7378         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7379         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7380         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7381         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7382         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7383         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7384         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7385         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7386         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7387         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7388         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7389         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7390         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7391         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7392         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7393         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7394         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7395 }
7396
7397 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7398 {
7399         struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
7400         struct torture_tcase *tcase;
7401
7402         tcase = torture_suite_add_tcase(suite, "addprinter");
7403
7404         torture_tcase_set_fixture(tcase,
7405                                   torture_rpc_spoolss_printer_setup,
7406                                   torture_rpc_spoolss_printer_teardown);
7407
7408         torture_tcase_printer(tcase);
7409
7410         tcase = torture_suite_add_tcase(suite, "addprinterex");
7411
7412         torture_tcase_set_fixture(tcase,
7413                                   torture_rpc_spoolss_printerex_setup,
7414                                   torture_rpc_spoolss_printer_teardown);
7415
7416         torture_tcase_printer(tcase);
7417
7418         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7419
7420         torture_tcase_set_fixture(tcase,
7421                                   torture_rpc_spoolss_printerwkn_setup,
7422                                   torture_rpc_spoolss_printer_teardown);
7423
7424         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7425
7426         torture_tcase_set_fixture(tcase,
7427                                   torture_rpc_spoolss_printerexwkn_setup,
7428                                   torture_rpc_spoolss_printer_teardown);
7429
7430 #if 0
7431         /* test is not correct */
7432         tcase = torture_suite_add_tcase(suite, "addprinterdm");
7433
7434         torture_tcase_set_fixture(tcase,
7435                                   torture_rpc_spoolss_printerdm_setup,
7436                                   torture_rpc_spoolss_printer_teardown);
7437
7438         torture_tcase_printer(tcase);
7439 #endif
7440         return suite;
7441 }
7442
7443 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7444 {
7445         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7446         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7447
7448         torture_tcase_set_fixture(tcase,
7449                                   torture_rpc_spoolss_setup,
7450                                   torture_rpc_spoolss_teardown);
7451
7452         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7453         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7454         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7455         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7456         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7457         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7458         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7459         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7460         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7461         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7462         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7463         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7464         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7465         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7466         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7467         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7468         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7469         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7470         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7471
7472         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7473
7474         return suite;
7475 }
7476
7477 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7478                                                   struct dcerpc_binding_handle *b,
7479                                                   const char *server,
7480                                                   const char *environment,
7481                                                   const char **dir_p)
7482 {
7483         struct spoolss_GetPrinterDriverDirectory r;
7484         uint32_t needed;
7485
7486         r.in.server             = server;
7487         r.in.environment        = environment;
7488         r.in.level              = 1;
7489         r.in.buffer             = NULL;
7490         r.in.offered            = 0;
7491         r.out.needed            = &needed;
7492
7493         torture_assert_ntstatus_ok(tctx,
7494                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7495                 "failed to query driver directory");
7496
7497         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7498                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7499                 r.in.buffer = &blob;
7500                 r.in.offered = needed;
7501
7502                 torture_assert_ntstatus_ok(tctx,
7503                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7504                         "failed to query driver directory");
7505         }
7506
7507         torture_assert_werr_ok(tctx, r.out.result,
7508                 "failed to query driver directory");
7509
7510         if (dir_p) {
7511                 *dir_p = r.out.info->info1.directory_name;
7512         }
7513
7514         return true;
7515 }
7516
7517 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7518 {
7519         if (info_ctr == NULL) {
7520                 return NULL;
7521         }
7522
7523         switch (info_ctr->level) {
7524         case 1:
7525                 return info_ctr->info.info1->driver_name;
7526         case 2:
7527                 return info_ctr->info.info2->driver_name;
7528         case 3:
7529                 return info_ctr->info.info3->driver_name;
7530         case 4:
7531                 return info_ctr->info.info4->driver_name;
7532         case 6:
7533                 return info_ctr->info.info6->driver_name;
7534         case 8:
7535                 return info_ctr->info.info8->driver_name;
7536         default:
7537                 return NULL;
7538         }
7539 }
7540
7541 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7542 {
7543         if (info_ctr == NULL) {
7544                 return NULL;
7545         }
7546
7547         switch (info_ctr->level) {
7548         case 2:
7549                 return info_ctr->info.info2->architecture;
7550         case 3:
7551                 return info_ctr->info.info3->architecture;
7552         case 4:
7553                 return info_ctr->info.info4->architecture;
7554         case 6:
7555                 return info_ctr->info.info6->architecture;
7556         case 8:
7557                 return info_ctr->info.info8->architecture;
7558         default:
7559                 return NULL;
7560         }
7561 }
7562
7563
7564 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7565                                       struct dcerpc_binding_handle *b,
7566                                       const char *servername,
7567                                       struct spoolss_AddDriverInfoCtr *info_ctr,
7568                                       WERROR expected_result)
7569 {
7570         struct spoolss_AddPrinterDriver r;
7571         const char *drivername = get_driver_from_info(info_ctr);
7572         const char *environment = get_environment_from_info(info_ctr);
7573
7574         r.in.servername = servername;
7575         r.in.info_ctr = info_ctr;
7576
7577         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7578                 drivername, info_ctr->level, environment);
7579
7580         torture_assert_ntstatus_ok(tctx,
7581                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7582                 "spoolss_AddPrinterDriver failed");
7583         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7584                 "spoolss_AddPrinterDriver failed with unexpected result");
7585
7586         return true;
7587
7588 }
7589
7590 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7591                                         struct dcerpc_binding_handle *b,
7592                                         const char *servername,
7593                                         struct spoolss_AddDriverInfoCtr *info_ctr,
7594                                         uint32_t flags,
7595                                         WERROR expected_result)
7596 {
7597         struct spoolss_AddPrinterDriverEx r;
7598         const char *drivername = get_driver_from_info(info_ctr);
7599         const char *environment = get_environment_from_info(info_ctr);
7600
7601         r.in.servername = servername;
7602         r.in.info_ctr = info_ctr;
7603         r.in.flags = flags;
7604
7605         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7606                 drivername, info_ctr->level, environment);
7607
7608         torture_assert_ntstatus_ok(tctx,
7609                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7610                 "AddPrinterDriverEx failed");
7611         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7612                 "AddPrinterDriverEx failed with unexpected result");
7613
7614         return true;
7615 }
7616
7617 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7618                                                struct dcerpc_binding_handle *b,
7619                                                const char *server_name,
7620                                                struct spoolss_AddDriverInfo8 *r,
7621                                                uint32_t flags,
7622                                                bool ex)
7623 {
7624         struct spoolss_AddDriverInfoCtr info_ctr;
7625         struct spoolss_AddDriverInfo1 info1;
7626
7627         ZERO_STRUCT(info1);
7628
7629         info_ctr.level = 1;
7630         info_ctr.info.info1 = &info1;
7631
7632         if (ex) {
7633                 torture_assert(tctx,
7634                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7635                         "failed to test AddPrinterDriverEx level 1");
7636         } else {
7637                 torture_assert(tctx,
7638                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7639                         "failed to test AddPrinterDriver level 1");
7640         }
7641
7642         info1.driver_name = r->driver_name;
7643
7644         if (ex) {
7645                 torture_assert(tctx,
7646                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7647                         "failed to test AddPrinterDriverEx level 1");
7648         } else {
7649                 torture_assert(tctx,
7650                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7651                         "failed to test AddPrinterDriver level 1");
7652         }
7653
7654         return true;
7655 }
7656
7657 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7658                                                struct dcerpc_binding_handle *b,
7659                                                const char *server_name,
7660                                                struct spoolss_AddDriverInfo8 *r,
7661                                                uint32_t flags,
7662                                                bool ex)
7663 {
7664         struct spoolss_AddDriverInfoCtr info_ctr;
7665         struct spoolss_AddDriverInfo2 info2;
7666
7667         ZERO_STRUCT(info2);
7668
7669         info_ctr.level = 2;
7670         info_ctr.info.info2 = &info2;
7671
7672         if (ex) {
7673                 torture_assert(tctx,
7674                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7675                         "failed to test AddPrinterDriverEx level 2");
7676         } else {
7677                 torture_assert(tctx,
7678                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7679                         "failed to test AddPrinterDriver level 2");
7680         }
7681
7682         info2.driver_name = r->driver_name;
7683
7684         if (ex) {
7685                 torture_assert(tctx,
7686                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7687                         "failed to test AddPrinterDriverEx level 2");
7688         } else {
7689                 torture_assert(tctx,
7690                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7691                         "failed to test AddPrinterDriver level 2");
7692         }
7693
7694         info2.version = r->version;
7695
7696         if (ex) {
7697                 torture_assert(tctx,
7698                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7699                         "failed to test AddPrinterDriverEx level 2");
7700         } else {
7701                 torture_assert(tctx,
7702                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7703                         "failed to test AddPrinterDriver level 2");
7704         }
7705
7706         info2.architecture = r->architecture;
7707
7708         if (ex) {
7709                 torture_assert(tctx,
7710                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7711                         "failed to test AddPrinterDriverEx level 2");
7712         } else {
7713                 torture_assert(tctx,
7714                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7715                         "failed to test AddPrinterDriver level 2");
7716         }
7717
7718         info2.driver_path = r->driver_path;
7719
7720         if (ex) {
7721                 torture_assert(tctx,
7722                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7723                         "failed to test AddPrinterDriverEx level 2");
7724         } else {
7725                 torture_assert(tctx,
7726                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7727                         "failed to test AddPrinterDriver level 2");
7728         }
7729
7730         info2.data_file = r->data_file;
7731
7732         if (ex) {
7733                 torture_assert(tctx,
7734                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7735                         "failed to test AddPrinterDriverEx level 2");
7736         } else {
7737                 torture_assert(tctx,
7738                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7739                         "failed to test AddPrinterDriver level 2");
7740         }
7741
7742         info2.config_file = r->config_file;
7743
7744         if (ex) {
7745                 torture_assert(tctx,
7746                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7747                         "failed to test AddPrinterDriverEx");
7748         }
7749
7750         if (ex) {
7751                 torture_assert(tctx,
7752                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7753                         "failed to test AddPrinterDriverEx level 2");
7754         } else {
7755                 torture_assert(tctx,
7756                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7757                         "failed to test AddPrinterDriver level 2");
7758         }
7759
7760         torture_assert(tctx,
7761                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7762                 "failed to find added printer driver");
7763
7764         return true;
7765 }
7766
7767 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7768                                                struct dcerpc_binding_handle *b,
7769                                                const char *server_name,
7770                                                struct spoolss_AddDriverInfo8 *r,
7771                                                uint32_t flags,
7772                                                bool ex)
7773 {
7774         struct spoolss_AddDriverInfoCtr info_ctr;
7775         struct spoolss_AddDriverInfo3 info3;
7776
7777         info3.driver_name       = r->driver_name;
7778         info3.version           = r->version;
7779         info3.architecture      = r->architecture;
7780         info3.driver_path       = r->driver_path;
7781         info3.data_file         = r->data_file;
7782         info3.config_file       = r->config_file;
7783         info3.help_file         = r->help_file;
7784         info3.monitor_name      = r->monitor_name;
7785         info3.default_datatype  = r->default_datatype;
7786         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7787         info3.dependent_files   = r->dependent_files;
7788
7789         info_ctr.level = 3;
7790         info_ctr.info.info3 = &info3;
7791
7792         if (ex) {
7793                 torture_assert(tctx,
7794                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7795                         "failed to test AddPrinterDriverEx level 3");
7796         } else {
7797                 torture_assert(tctx,
7798                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7799                         "failed to test AddPrinterDriver level 3");
7800         }
7801
7802         torture_assert(tctx,
7803                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7804                 "failed to find added printer driver");
7805
7806         return true;
7807 }
7808
7809 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7810                                                struct dcerpc_binding_handle *b,
7811                                                const char *server_name,
7812                                                struct spoolss_AddDriverInfo8 *r,
7813                                                uint32_t flags,
7814                                                bool ex)
7815 {
7816         struct spoolss_AddDriverInfoCtr info_ctr;
7817         struct spoolss_AddDriverInfo4 info4;
7818
7819         info4.version           = r->version;
7820         info4.driver_name       = r->driver_name;
7821         info4.architecture      = r->architecture;
7822         info4.driver_path       = r->driver_path;
7823         info4.data_file         = r->data_file;
7824         info4.config_file       = r->config_file;
7825         info4.help_file         = r->help_file;
7826         info4.monitor_name      = r->monitor_name;
7827         info4.default_datatype  = r->default_datatype;
7828         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7829         info4.dependent_files   = r->dependent_files;
7830         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7831         info4.previous_names = r->previous_names;
7832
7833         info_ctr.level = 4;
7834         info_ctr.info.info4 = &info4;
7835
7836         if (ex) {
7837                 torture_assert(tctx,
7838                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7839                         "failed to test AddPrinterDriverEx level 4");
7840         } else {
7841                 torture_assert(tctx,
7842                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7843                         "failed to test AddPrinterDriver level 4");
7844         }
7845
7846         torture_assert(tctx,
7847                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7848                 "failed to find added printer driver");
7849
7850         return true;
7851 }
7852
7853 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7854                                                struct dcerpc_binding_handle *b,
7855                                                const char *server_name,
7856                                                struct spoolss_AddDriverInfo8 *r,
7857                                                uint32_t flags,
7858                                                bool ex)
7859 {
7860         struct spoolss_AddDriverInfoCtr info_ctr;
7861         struct spoolss_AddDriverInfo6 info6;
7862
7863         info6.version           = r->version;
7864         info6.driver_name       = r->driver_name;
7865         info6.architecture      = r->architecture;
7866         info6.driver_path       = r->driver_path;
7867         info6.data_file         = r->data_file;
7868         info6.config_file       = r->config_file;
7869         info6.help_file         = r->help_file;
7870         info6.monitor_name      = r->monitor_name;
7871         info6.default_datatype  = r->default_datatype;
7872         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7873         info6.dependent_files   = r->dependent_files;
7874         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7875         info6.previous_names    = r->previous_names;
7876         info6.driver_date       = r->driver_date;
7877         info6.driver_version    = r->driver_version;
7878         info6.manufacturer_name = r->manufacturer_name;
7879         info6.manufacturer_url  = r->manufacturer_url;
7880         info6.hardware_id       = r->hardware_id;
7881         info6.provider          = r->provider;
7882
7883         info_ctr.level = 6;
7884         info_ctr.info.info6 = &info6;
7885
7886         if (ex) {
7887                 torture_assert(tctx,
7888                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7889                         "failed to test AddPrinterDriverEx level 6");
7890         } else {
7891                 torture_assert(tctx,
7892                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7893                         "failed to test AddPrinterDriver level 6");
7894         }
7895
7896         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7897
7898         if (!ex) {
7899                 return true;
7900         }
7901
7902         torture_assert(tctx,
7903                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7904                 "failed to find added printer driver");
7905
7906         return true;
7907 }
7908
7909 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7910                                                struct dcerpc_binding_handle *b,
7911                                                const char *server_name,
7912                                                struct spoolss_AddDriverInfo8 *r,
7913                                                uint32_t flags,
7914                                                bool ex)
7915 {
7916         struct spoolss_AddDriverInfoCtr info_ctr;
7917
7918         info_ctr.level = 8;
7919         info_ctr.info.info8 = r;
7920
7921         if (ex) {
7922                 torture_assert(tctx,
7923                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7924                         "failed to test AddPrinterDriverEx level 8");
7925         } else {
7926                 torture_assert(tctx,
7927                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7928                         "failed to test AddPrinterDriver level 8");
7929         }
7930
7931         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7932
7933         if (!ex) {
7934                 return true;
7935         }
7936
7937         torture_assert(tctx,
7938                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7939                 "failed to find added printer driver");
7940
7941         return true;
7942 }
7943
7944 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7945                                          struct dcerpc_binding_handle *b,
7946                                          const char *server,
7947                                          const char *driver,
7948                                          const char *environment,
7949                                          WERROR expected_result)
7950 {
7951         struct spoolss_DeletePrinterDriver r;
7952
7953         r.in.server = server;
7954         r.in.architecture = environment;
7955         r.in.driver = driver;
7956
7957         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7958
7959         torture_assert_ntstatus_ok(tctx,
7960                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7961                 "DeletePrinterDriver failed");
7962         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7963                 "DeletePrinterDriver failed with unexpected result");
7964
7965         return true;
7966 }
7967
7968 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7969                                            struct dcerpc_binding_handle *b,
7970                                            const char *server,
7971                                            const char *driver,
7972                                            const char *environment,
7973                                            uint32_t delete_flags,
7974                                            uint32_t version,
7975                                            WERROR expected_result)
7976 {
7977         struct spoolss_DeletePrinterDriverEx r;
7978
7979         r.in.server = server;
7980         r.in.architecture = environment;
7981         r.in.driver = driver;
7982         r.in.delete_flags = delete_flags;
7983         r.in.version = version;
7984
7985         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7986
7987         torture_assert_ntstatus_ok(tctx,
7988                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7989                 "DeletePrinterDriverEx failed");
7990         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7991                 "DeletePrinterDriverEx failed with unexpected result");
7992
7993         return true;
7994 }
7995
7996 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7997                                      struct dcerpc_binding_handle *b,
7998                                      const char *server_name,
7999                                      const char *driver,
8000                                      const char *environment)
8001 {
8002         torture_assert(tctx,
8003                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8004                 "failed to delete driver");
8005
8006         torture_assert(tctx,
8007                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8008                 "failed to delete driver");
8009
8010         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8011                 torture_fail(tctx, "deleted driver still enumerated");
8012         }
8013
8014         torture_assert(tctx,
8015                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8016                 "2nd delete failed");
8017
8018         return true;
8019 }
8020
8021 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8022                                        struct dcerpc_binding_handle *b,
8023                                        const char *server_name,
8024                                        const char *driver,
8025                                        const char *environment,
8026                                        uint32_t delete_flags,
8027                                        uint32_t version)
8028 {
8029         torture_assert(tctx,
8030                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8031                 "failed to delete driver");
8032
8033         torture_assert(tctx,
8034                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8035                 "failed to delete driver");
8036
8037         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8038                 torture_fail(tctx, "deleted driver still enumerated");
8039         }
8040
8041         torture_assert(tctx,
8042                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8043                 "2nd delete failed");
8044
8045         return true;
8046 }
8047
8048 static bool test_PrinterDriver_args(struct torture_context *tctx,
8049                                     struct dcerpc_binding_handle *b,
8050                                     const char *server_name,
8051                                     uint32_t level,
8052                                     struct spoolss_AddDriverInfo8 *r,
8053                                     uint32_t add_flags,
8054                                     uint32_t delete_flags,
8055                                     uint32_t delete_version,
8056                                     bool ex)
8057 {
8058         bool ret = true;
8059
8060         switch (level) {
8061         case 1:
8062                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
8063                 break;
8064         case 2:
8065                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
8066                 break;
8067         case 3:
8068                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
8069                 break;
8070         case 4:
8071                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
8072                 break;
8073         case 6:
8074                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
8075                 break;
8076         case 8:
8077                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
8078                 break;
8079         default:
8080                 return false;
8081         }
8082
8083         if (ret == false) {
8084                 return ret;
8085         }
8086
8087         if (level == 1) {
8088                 return ret;
8089         }
8090
8091         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8092
8093         if (!ex && (level == 6 || level == 8)) {
8094                 return ret;
8095         }
8096
8097         if (ex) {
8098                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8099         } else {
8100                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8101         }
8102 }
8103
8104 static bool fillup_printserver_info(struct torture_context *tctx,
8105                                     struct dcerpc_pipe *p,
8106                                     struct torture_driver_context *d)
8107 {
8108         struct policy_handle server_handle;
8109         struct dcerpc_binding_handle *b = p->binding_handle;
8110         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8111
8112         torture_assert(tctx,
8113                 test_OpenPrinter_server(tctx, p, &server_handle),
8114                 "failed to open printserver");
8115         torture_assert(tctx,
8116                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8117                 "failed to get environment");
8118         torture_assert(tctx,
8119                 test_ClosePrinter(tctx, b, &server_handle),
8120                 "failed to close printserver");
8121
8122         torture_assert(tctx,
8123                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8124                         d->local.environment ? d->local.environment : d->remote.environment,
8125                         &d->remote.driver_directory),
8126                 "failed to get driver directory");
8127
8128         return true;
8129 }
8130
8131 static const char *driver_directory_dir(const char *driver_directory)
8132 {
8133         char *p;
8134
8135         p = strrchr(driver_directory, '\\');
8136         if (p) {
8137                 return p+1;
8138         }
8139
8140         return NULL;
8141 }
8142
8143 static const char *driver_directory_share(struct torture_context *tctx,
8144                                           const char *driver_directory)
8145 {
8146         const char *p;
8147         char *tok;
8148
8149         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8150                 driver_directory += 2;
8151         }
8152
8153         p = talloc_strdup(tctx, driver_directory);
8154
8155         torture_assert(tctx,
8156                 next_token_talloc(tctx, &p, &tok, "\\"),
8157                 "cannot explode uri");
8158         torture_assert(tctx,
8159                 next_token_talloc(tctx, &p, &tok, "\\"),
8160                 "cannot explode uri");
8161
8162         return tok;
8163 }
8164
8165 static bool upload_printer_driver_file(struct torture_context *tctx,
8166                                        struct smbcli_state *cli,
8167                                        struct torture_driver_context *d,
8168                                        const char *file_name)
8169 {
8170         XFILE *f;
8171         int fnum;
8172         uint8_t *buf;
8173         int maxwrite = 64512;
8174         off_t nread = 0;
8175         size_t start = 0;
8176         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8177         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8178         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8179
8180         if (!file_name) {
8181                 return true;
8182         }
8183
8184         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8185
8186         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8187         if (fnum == -1) {
8188                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8189         }
8190
8191         f = x_fopen(local_name, O_RDONLY, 0);
8192         if (f == NULL) {
8193                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8194         }
8195
8196         buf = talloc_array(tctx, uint8_t, maxwrite);
8197         if (!buf) {
8198                 return false;
8199         }
8200
8201         while (!x_feof(f)) {
8202                 int n = maxwrite;
8203                 int ret;
8204
8205                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8206                         if((n == 0) && x_feof(f))
8207                                 break; /* Empty local file. */
8208
8209                         torture_warning(tctx,
8210                                 "failed to read file: %s\n", strerror(errno));
8211                         break;
8212                 }
8213
8214                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8215
8216                 if (n != ret) {
8217                         torture_warning(tctx,
8218                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8219                         break;
8220                 }
8221
8222                 nread += n;
8223         }
8224
8225         x_fclose(f);
8226
8227         torture_assert_ntstatus_ok(tctx,
8228                 smbcli_close(cli->tree, fnum),
8229                 "failed to close file");
8230
8231         return true;
8232 }
8233
8234 static bool connect_printer_driver_share(struct torture_context *tctx,
8235                                          const char *server_name,
8236                                          const char *share_name,
8237                                          struct smbcli_state **cli)
8238 {
8239         struct smbcli_options smb_options;
8240         struct smbcli_session_options smb_session_options;
8241
8242         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8243                 share_name, server_name);
8244
8245         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8246         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8247
8248         torture_assert_ntstatus_ok(tctx,
8249                 smbcli_full_connection(tctx, cli, server_name,
8250                                         lpcfg_smb_ports(tctx->lp_ctx),
8251                                         share_name, NULL,
8252                                         lpcfg_socket_options(tctx->lp_ctx),
8253                                         cmdline_credentials,
8254                                         lpcfg_resolve_context(tctx->lp_ctx),
8255                                         tctx->ev,
8256                                         &smb_options,
8257                                         &smb_session_options,
8258                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8259                 "failed to open driver share");
8260
8261         return true;
8262 }
8263
8264 static bool upload_printer_driver(struct torture_context *tctx,
8265                                   const char *server_name,
8266                                   struct torture_driver_context *d)
8267 {
8268         struct smbcli_state *cli;
8269         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8270         int i;
8271
8272         torture_assert(tctx,
8273                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8274                 "failed to connect to driver share");
8275
8276         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8277                 server_name, share_name);
8278
8279         torture_assert(tctx,
8280                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8281                 "failed to upload driver_path");
8282         torture_assert(tctx,
8283                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8284                 "failed to upload data_file");
8285         torture_assert(tctx,
8286                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8287                 "failed to upload config_file");
8288         torture_assert(tctx,
8289                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8290                 "failed to upload help_file");
8291         if (d->info8.dependent_files) {
8292                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8293                         torture_assert(tctx,
8294                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8295                                 "failed to upload dependent_files");
8296                 }
8297         }
8298
8299         talloc_free(cli);
8300
8301         return true;
8302 }
8303
8304 static bool remove_printer_driver_file(struct torture_context *tctx,
8305                                        struct smbcli_state *cli,
8306                                        struct torture_driver_context *d,
8307                                        const char *file_name)
8308 {
8309         const char *remote_name;
8310         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
8311
8312         if (!file_name) {
8313                 return true;
8314         }
8315
8316         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8317
8318         torture_comment(tctx, "Removing %s\n", remote_name);
8319
8320         torture_assert_ntstatus_ok(tctx,
8321                 smbcli_unlink(cli->tree, remote_name),
8322                 "failed to unlink");
8323
8324         return true;
8325 }
8326
8327 static bool remove_printer_driver(struct torture_context *tctx,
8328                                   const char *server_name,
8329                                   struct torture_driver_context *d)
8330 {
8331         struct smbcli_state *cli;
8332         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8333         int i;
8334
8335         torture_assert(tctx,
8336                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8337                 "failed to connect to driver share");
8338
8339         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8340                 server_name, share_name);
8341
8342         torture_assert(tctx,
8343                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8344                 "failed to remove driver_path");
8345         torture_assert(tctx,
8346                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8347                 "failed to remove data_file");
8348         torture_assert(tctx,
8349                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8350                 "failed to remove config_file");
8351         torture_assert(tctx,
8352                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8353                 "failed to remove help_file");
8354         if (d->info8.dependent_files) {
8355                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8356                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8357                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8358                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8359                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8360                                 continue;
8361                         }
8362                         torture_assert(tctx,
8363                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8364                                 "failed to remove dependent_files");
8365                 }
8366         }
8367
8368         talloc_free(cli);
8369
8370         return true;
8371
8372 }
8373
8374 static bool test_add_driver_arg(struct torture_context *tctx,
8375                                 struct dcerpc_pipe *p,
8376                                 struct torture_driver_context *d)
8377 {
8378         bool ret = true;
8379         struct dcerpc_binding_handle *b = p->binding_handle;
8380         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8381         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8382         int i;
8383         struct spoolss_AddDriverInfo8 info8;
8384         uint32_t add_flags = APD_COPY_NEW_FILES;
8385         uint32_t delete_flags = 0;
8386
8387         ZERO_STRUCT(info8);
8388
8389         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8390                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8391
8392         torture_assert(tctx,
8393                 fillup_printserver_info(tctx, p, d),
8394                 "failed to fillup printserver info");
8395
8396         if (!directory_exist(d->local.driver_directory)) {
8397                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8398         }
8399
8400         torture_assert(tctx,
8401                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8402                 "failed to upload printer driver");
8403
8404         info8.version           = d->info8.version;
8405         info8.driver_name       = d->info8.driver_name;
8406         info8.architecture      = d->local.environment;
8407         info8.driver_path       = d->info8.driver_path;
8408         info8.data_file         = d->info8.data_file;
8409         info8.config_file       = d->info8.config_file;
8410
8411         for (i=0; i < ARRAY_SIZE(levels); i++) {
8412
8413                 if (torture_setting_bool(tctx, "samba3", false)) {
8414                         switch (levels[i]) {
8415                         case 2:
8416                         case 4:
8417                         case 8:
8418                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8419                                 continue;
8420                         default:
8421                                 break;
8422                         }
8423                 }
8424
8425                 torture_comment(tctx,
8426                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
8427                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8428
8429                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8430         }
8431
8432         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8433         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8434         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8435
8436         for (i=0; i < ARRAY_SIZE(levels); i++) {
8437
8438                 if (torture_setting_bool(tctx, "samba3", false)) {
8439                         switch (levels[i]) {
8440                         case 2:
8441                         case 4:
8442                         case 8:
8443                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8444                                 continue;
8445                         default:
8446                                 break;
8447                         }
8448                 }
8449
8450
8451                 torture_comment(tctx,
8452                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8453                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8454
8455                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8456         }
8457
8458         torture_assert(tctx,
8459                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8460                 "failed to remove printer driver");
8461
8462         torture_comment(tctx, "\n");
8463
8464         return ret;
8465 }
8466
8467 static bool test_add_driver_ex_64(struct torture_context *tctx,
8468                                   struct dcerpc_pipe *p,
8469                                   void *private_data)
8470 {
8471         struct torture_driver_context *d =
8472                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8473
8474         d->local.environment            = talloc_strdup(d, "Windows x64");
8475         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8476         d->info8.driver_name            = TORTURE_DRIVER_EX;
8477         d->ex                           = true;
8478
8479         return test_add_driver_arg(tctx, p, d);
8480 }
8481
8482 static bool test_add_driver_ex_32(struct torture_context *tctx,
8483                                   struct dcerpc_pipe *p,
8484                                   void *private_data)
8485 {
8486         struct torture_driver_context *d =
8487                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8488
8489         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8490         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8491         d->info8.driver_name            = TORTURE_DRIVER_EX;
8492         d->ex                           = true;
8493
8494         return test_add_driver_arg(tctx, p, d);
8495 }
8496
8497 static bool test_add_driver_64(struct torture_context *tctx,
8498                                struct dcerpc_pipe *p,
8499                                void *private_data)
8500 {
8501         struct torture_driver_context *d =
8502                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8503
8504         d->local.environment            = talloc_strdup(d, "Windows x64");
8505         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8506         d->info8.driver_name            = TORTURE_DRIVER;
8507         d->ex                           = false;
8508
8509         return test_add_driver_arg(tctx, p, d);
8510 }
8511
8512 static bool test_add_driver_32(struct torture_context *tctx,
8513                                struct dcerpc_pipe *p,
8514                                void *private_data)
8515 {
8516         struct torture_driver_context *d =
8517                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8518
8519         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8520         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8521         d->info8.driver_name            = TORTURE_DRIVER;
8522         d->ex                           = false;
8523
8524         return test_add_driver_arg(tctx, p, d);
8525 }
8526
8527 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8528 {
8529         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8530
8531         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8532                                                         "driver", &ndr_table_spoolss);
8533         struct torture_driver_context *t;
8534
8535         t = talloc_zero(mem_ctx, struct torture_driver_context);
8536
8537         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
8538         t->info8.driver_name    = NULL;
8539         t->info8.architecture   = NULL;
8540         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
8541         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
8542         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
8543
8544         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8545         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8546
8547         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8548         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8549
8550         return suite;
8551 }