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