s4-smbtorture: start on a test to verify how SetPrinter changes DsSpooler Printer...
[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,
2958                         uint32_t job_id,
2959                         struct spoolss_JobInfoContainer *ctr,
2960                         enum spoolss_JobControl command)
2961 {
2962         NTSTATUS status;
2963         struct spoolss_SetJob r;
2964
2965         r.in.handle     = handle;
2966         r.in.job_id     = job_id;
2967         r.in.ctr        = ctr;
2968         r.in.command    = command;
2969
2970         switch (command) {
2971         case SPOOLSS_JOB_CONTROL_PAUSE:
2972                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2973                 break;
2974         case SPOOLSS_JOB_CONTROL_RESUME:
2975                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2976                 break;
2977         case SPOOLSS_JOB_CONTROL_CANCEL:
2978                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2979                 break;
2980         case SPOOLSS_JOB_CONTROL_RESTART:
2981                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2982                 break;
2983         case SPOOLSS_JOB_CONTROL_DELETE:
2984                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2985                 break;
2986         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2987                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2988                 break;
2989         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2990                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2991                 break;
2992         case SPOOLSS_JOB_CONTROL_RETAIN:
2993                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2994                 break;
2995         case SPOOLSS_JOB_CONTROL_RELEASE:
2996                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2997                 break;
2998         default:
2999                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3000                 break;
3001         }
3002
3003         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3004         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3005         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3006
3007         return true;
3008 }
3009
3010 static bool test_AddJob(struct torture_context *tctx,
3011                         struct dcerpc_binding_handle *b,
3012                         struct policy_handle *handle)
3013 {
3014         NTSTATUS status;
3015         struct spoolss_AddJob r;
3016         uint32_t needed;
3017
3018         r.in.level = 0;
3019         r.in.handle = handle;
3020         r.in.offered = 0;
3021         r.out.needed = &needed;
3022         r.in.buffer = r.out.buffer = NULL;
3023
3024         torture_comment(tctx, "Testing AddJob\n");
3025
3026         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3027         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3028
3029         r.in.level = 1;
3030
3031         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3032         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3033
3034         return true;
3035 }
3036
3037
3038 static bool test_EnumJobs_args(struct torture_context *tctx,
3039                                struct dcerpc_binding_handle *b,
3040                                struct policy_handle *handle,
3041                                uint32_t level,
3042                                uint32_t *count_p,
3043                                union spoolss_JobInfo **info_p)
3044 {
3045         NTSTATUS status;
3046         struct spoolss_EnumJobs r;
3047         uint32_t needed;
3048         uint32_t count;
3049         union spoolss_JobInfo *info;
3050
3051         r.in.handle = handle;
3052         r.in.firstjob = 0;
3053         r.in.numjobs = 0xffffffff;
3054         r.in.level = level;
3055         r.in.buffer = NULL;
3056         r.in.offered = 0;
3057         r.out.needed = &needed;
3058         r.out.count = &count;
3059         r.out.info = &info;
3060
3061         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3062
3063         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3064
3065         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3066
3067         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3068                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3069                 r.in.buffer = &blob;
3070                 r.in.offered = needed;
3071
3072                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3073
3074                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3075                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3076                 torture_assert(tctx, info, "No jobs returned");
3077
3078                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3079
3080         } else {
3081                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3082         }
3083
3084         if (count_p) {
3085                 *count_p = count;
3086         }
3087         if (info_p) {
3088                 *info_p = info;
3089         }
3090
3091         return true;
3092 }
3093
3094 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3095                                          struct dcerpc_binding_handle *b,
3096                                          struct policy_handle *handle,
3097                                          uint32_t *job_id)
3098 {
3099         NTSTATUS status;
3100         struct spoolss_StartDocPrinter s;
3101         struct spoolss_DocumentInfo1 info1;
3102         struct spoolss_StartPagePrinter sp;
3103         struct spoolss_WritePrinter w;
3104         struct spoolss_EndPagePrinter ep;
3105         struct spoolss_EndDocPrinter e;
3106         int i;
3107         uint32_t num_written;
3108
3109         torture_comment(tctx, "Testing StartDocPrinter\n");
3110
3111         s.in.handle             = handle;
3112         s.in.level              = 1;
3113         s.in.info.info1         = &info1;
3114         s.out.job_id            = job_id;
3115         info1.document_name     = "TorturePrintJob";
3116         info1.output_file       = NULL;
3117         info1.datatype          = "RAW";
3118
3119         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3120         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3121         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3122
3123         for (i=1; i < 4; i++) {
3124                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3125
3126                 sp.in.handle            = handle;
3127
3128                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3129                 torture_assert_ntstatus_ok(tctx, status,
3130                                            "dcerpc_spoolss_StartPagePrinter failed");
3131                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3132
3133                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3134
3135                 w.in.handle             = handle;
3136                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3137                 w.out.num_written       = &num_written;
3138
3139                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3140                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3141                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3142
3143                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3144
3145                 ep.in.handle            = handle;
3146
3147                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3148                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3149                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3150         }
3151
3152         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3153
3154         e.in.handle = handle;
3155
3156         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3157         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3158         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3159
3160         return true;
3161 }
3162
3163 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3164                                         struct dcerpc_binding_handle *b,
3165                                         struct policy_handle *handle,
3166                                         uint32_t num_jobs,
3167                                         uint32_t *job_ids)
3168 {
3169         uint32_t count;
3170         union spoolss_JobInfo *info = NULL;
3171         int i;
3172
3173         torture_assert(tctx,
3174                 test_AddJob(tctx, b, handle),
3175                 "AddJob failed");
3176
3177         torture_assert(tctx,
3178                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3179                 "EnumJobs level 1 failed");
3180
3181         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3182
3183         for (i=0; i < num_jobs; i++) {
3184                 union spoolss_JobInfo ginfo;
3185                 const char *document_name;
3186                 const char *new_document_name = "any_other_docname";
3187                 struct spoolss_JobInfoContainer ctr;
3188                 struct spoolss_SetJobInfo1 info1;
3189
3190                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3191
3192                 torture_assert(tctx,
3193                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3194                         "failed to call test_GetJob");
3195
3196                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3197
3198                 document_name = ginfo.info1.document_name;
3199
3200                 info1.job_id            = ginfo.info1.job_id;
3201                 info1.printer_name      = ginfo.info1.printer_name;
3202                 info1.server_name       = ginfo.info1.server_name;
3203                 info1.user_name         = ginfo.info1.user_name;
3204                 info1.document_name     = new_document_name;
3205                 info1.data_type         = ginfo.info1.data_type;
3206                 info1.text_status       = ginfo.info1.text_status;
3207                 info1.status            = ginfo.info1.status;
3208                 info1.priority          = ginfo.info1.priority;
3209                 info1.position          = ginfo.info1.position;
3210                 info1.total_pages       = ginfo.info1.total_pages;
3211                 info1.pages_printed     = ginfo.info1.pages_printed;
3212                 info1.submitted         = ginfo.info1.submitted;
3213
3214                 ctr.level = 1;
3215                 ctr.info.info1 = &info1;
3216
3217                 torture_assert(tctx,
3218                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3219                         "failed to call test_SetJob level 1");
3220
3221                 torture_assert(tctx,
3222                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3223                         "failed to call test_GetJob");
3224
3225                 if (strequal(ginfo.info1.document_name, document_name)) {
3226                         torture_warning(tctx,
3227                                 talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
3228                                         document_name, new_document_name));
3229                 }
3230         }
3231
3232         for (i=0; i < num_jobs; i++) {
3233                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3234                         torture_warning(tctx, "failed to pause printjob\n");
3235                 }
3236                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3237                         torture_warning(tctx, "failed to resume printjob\n");
3238                 }
3239         }
3240
3241         return true;
3242 }
3243
3244 static bool test_DoPrintTest(struct torture_context *tctx,
3245                              struct dcerpc_binding_handle *b,
3246                              struct policy_handle *handle)
3247 {
3248         bool ret = true;
3249         uint32_t num_jobs = 8;
3250         uint32_t *job_ids;
3251         int i;
3252
3253         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3254
3255         for (i=0; i < num_jobs; i++) {
3256                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3257         }
3258
3259         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3260
3261         for (i=0; i < num_jobs; i++) {
3262                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3263         }
3264
3265         return ret;
3266 }
3267
3268 static bool test_PausePrinter(struct torture_context *tctx,
3269                               struct dcerpc_binding_handle *b,
3270                               struct policy_handle *handle)
3271 {
3272         NTSTATUS status;
3273         struct spoolss_SetPrinter r;
3274         struct spoolss_SetPrinterInfoCtr info_ctr;
3275         struct spoolss_DevmodeContainer devmode_ctr;
3276         struct sec_desc_buf secdesc_ctr;
3277
3278         info_ctr.level = 0;
3279         info_ctr.info.info0 = NULL;
3280
3281         ZERO_STRUCT(devmode_ctr);
3282         ZERO_STRUCT(secdesc_ctr);
3283
3284         r.in.handle             = handle;
3285         r.in.info_ctr           = &info_ctr;
3286         r.in.devmode_ctr        = &devmode_ctr;
3287         r.in.secdesc_ctr        = &secdesc_ctr;
3288         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3289
3290         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3291
3292         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3293
3294         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3295
3296         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3297
3298         return true;
3299 }
3300
3301 static bool test_ResumePrinter(struct torture_context *tctx,
3302                                struct dcerpc_binding_handle *b,
3303                                struct policy_handle *handle)
3304 {
3305         NTSTATUS status;
3306         struct spoolss_SetPrinter r;
3307         struct spoolss_SetPrinterInfoCtr info_ctr;
3308         struct spoolss_DevmodeContainer devmode_ctr;
3309         struct sec_desc_buf secdesc_ctr;
3310
3311         info_ctr.level = 0;
3312         info_ctr.info.info0 = NULL;
3313
3314         ZERO_STRUCT(devmode_ctr);
3315         ZERO_STRUCT(secdesc_ctr);
3316
3317         r.in.handle             = handle;
3318         r.in.info_ctr           = &info_ctr;
3319         r.in.devmode_ctr        = &devmode_ctr;
3320         r.in.secdesc_ctr        = &secdesc_ctr;
3321         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3322
3323         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3324
3325         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3326
3327         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3328
3329         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3330
3331         return true;
3332 }
3333
3334 static bool test_GetPrinterData(struct torture_context *tctx,
3335                                 struct dcerpc_binding_handle *b,
3336                                 struct policy_handle *handle,
3337                                 const char *value_name,
3338                                 enum winreg_Type *type_p,
3339                                 uint8_t **data_p,
3340                                 uint32_t *needed_p)
3341 {
3342         NTSTATUS status;
3343         struct spoolss_GetPrinterData r;
3344         uint32_t needed;
3345         enum winreg_Type type;
3346         union spoolss_PrinterData data;
3347
3348         r.in.handle = handle;
3349         r.in.value_name = value_name;
3350         r.in.offered = 0;
3351         r.out.needed = &needed;
3352         r.out.type = &type;
3353         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3354
3355         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3356
3357         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3358         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3359
3360         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3361                 r.in.offered = needed;
3362                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3363                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3364                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3365         }
3366
3367         torture_assert_werr_ok(tctx, r.out.result,
3368                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3369
3370         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3371
3372         if (type_p) {
3373                 *type_p = type;
3374         }
3375
3376         if (data_p) {
3377                 *data_p = r.out.data;
3378         }
3379
3380         if (needed_p) {
3381                 *needed_p = needed;
3382         }
3383
3384         return true;
3385 }
3386
3387 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3388                                   struct dcerpc_pipe *p,
3389                                   struct policy_handle *handle,
3390                                   const char *key_name,
3391                                   const char *value_name,
3392                                   enum winreg_Type *type_p,
3393                                   uint8_t **data_p,
3394                                   uint32_t *needed_p)
3395 {
3396         NTSTATUS status;
3397         struct spoolss_GetPrinterDataEx r;
3398         enum winreg_Type type;
3399         uint32_t needed;
3400         union spoolss_PrinterData data;
3401         struct dcerpc_binding_handle *b = p->binding_handle;
3402
3403         r.in.handle = handle;
3404         r.in.key_name = key_name;
3405         r.in.value_name = value_name;
3406         r.in.offered = 0;
3407         r.out.type = &type;
3408         r.out.needed = &needed;
3409         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3410
3411         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3412                 r.in.key_name, r.in.value_name);
3413
3414         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3415         if (!NT_STATUS_IS_OK(status)) {
3416                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3417                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3418                 }
3419                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3420         }
3421
3422         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3423                 r.in.offered = needed;
3424                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3425                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3426                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3427         }
3428
3429         torture_assert_werr_ok(tctx, r.out.result,
3430                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3431
3432         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3433
3434         if (type_p) {
3435                 *type_p = type;
3436         }
3437
3438         if (data_p) {
3439                 *data_p = r.out.data;
3440         }
3441
3442         if (needed_p) {
3443                 *needed_p = needed;
3444         }
3445
3446         return true;
3447 }
3448
3449 static bool test_get_environment(struct torture_context *tctx,
3450                                  struct dcerpc_binding_handle *b,
3451                                  struct policy_handle *handle,
3452                                  const char **architecture)
3453 {
3454         DATA_BLOB blob;
3455         enum winreg_Type type;
3456         uint8_t *data;
3457         uint32_t needed;
3458
3459         torture_assert(tctx,
3460                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3461                 "failed to get Architecture");
3462
3463         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3464
3465         blob = data_blob_const(data, needed);
3466         *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3467
3468         return true;
3469 }
3470
3471 static bool test_GetPrinterData_list(struct torture_context *tctx,
3472                                      struct dcerpc_pipe *p,
3473                                      struct policy_handle *handle,
3474                                      const char **architecture)
3475 {
3476         struct dcerpc_binding_handle *b = p->binding_handle;
3477         const char *list[] = {
3478                 "W3SvcInstalled",
3479                 "BeepEnabled",
3480                 "EventLog",
3481                 /* "NetPopup", not on w2k8 */
3482                 /* "NetPopupToComputer", not on w2k8 */
3483                 "MajorVersion",
3484                 "MinorVersion",
3485                 "DefaultSpoolDirectory",
3486                 "Architecture",
3487                 "DsPresent",
3488                 "OSVersion",
3489                 /* "OSVersionEx", not on s3 */
3490                 "DNSMachineName"
3491         };
3492         int i;
3493
3494         for (i=0; i < ARRAY_SIZE(list); i++) {
3495                 enum winreg_Type type, type_ex;
3496                 uint8_t *data, *data_ex;
3497                 uint32_t needed, needed_ex;
3498
3499                 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3500                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3501                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3502                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3503                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3504                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3505                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3506
3507                 if (strequal(list[i], "Architecture")) {
3508                         if (architecture) {
3509                                 DATA_BLOB blob = data_blob_const(data, needed);
3510                                 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3511                         }
3512                 }
3513         }
3514
3515         return true;
3516 }
3517
3518 static bool test_EnumPrinterData(struct torture_context *tctx,
3519                                  struct dcerpc_pipe *p,
3520                                  struct policy_handle *handle,
3521                                  uint32_t enum_index,
3522                                  uint32_t value_offered,
3523                                  uint32_t data_offered,
3524                                  enum winreg_Type *type_p,
3525                                  uint32_t *value_needed_p,
3526                                  uint32_t *data_needed_p,
3527                                  const char **value_name_p,
3528                                  uint8_t **data_p,
3529                                  WERROR *result_p)
3530 {
3531         struct spoolss_EnumPrinterData r;
3532         uint32_t data_needed;
3533         uint32_t value_needed;
3534         enum winreg_Type type;
3535         struct dcerpc_binding_handle *b = p->binding_handle;
3536
3537         r.in.handle = handle;
3538         r.in.enum_index = enum_index;
3539         r.in.value_offered = value_offered;
3540         r.in.data_offered = data_offered;
3541         r.out.data_needed = &data_needed;
3542         r.out.value_needed = &value_needed;
3543         r.out.type = &type;
3544         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3545         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3546
3547         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3548
3549         torture_assert_ntstatus_ok(tctx,
3550                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3551                 "EnumPrinterData failed");
3552
3553         if (type_p) {
3554                 *type_p = type;
3555         }
3556         if (value_needed_p) {
3557                 *value_needed_p = value_needed;
3558         }
3559         if (data_needed_p) {
3560                 *data_needed_p = data_needed;
3561         }
3562         if (value_name_p) {
3563                 *value_name_p = r.out.value_name;
3564         }
3565         if (data_p) {
3566                 *data_p = r.out.data;
3567         }
3568         if (result_p) {
3569                 *result_p = r.out.result;
3570         }
3571
3572         return true;
3573 }
3574
3575
3576 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3577                                      struct dcerpc_pipe *p,
3578                                      struct policy_handle *handle)
3579 {
3580         uint32_t enum_index = 0;
3581         enum winreg_Type type;
3582         uint32_t value_needed;
3583         uint32_t data_needed;
3584         uint8_t *data;
3585         const char *value_name;
3586         WERROR result;
3587
3588         torture_comment(tctx, "Testing EnumPrinterData\n");
3589
3590         do {
3591                 torture_assert(tctx,
3592                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3593                                              &type, &value_needed, &data_needed,
3594                                              &value_name, &data, &result),
3595                         "EnumPrinterData failed");
3596
3597                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3598                         break;
3599                 }
3600
3601                 torture_assert(tctx,
3602                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3603                                              &type, &value_needed, &data_needed,
3604                                              &value_name, &data, &result),
3605                         "EnumPrinterData failed");
3606
3607                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3608                         break;
3609                 }
3610
3611                 enum_index++;
3612
3613         } while (W_ERROR_IS_OK(result));
3614
3615         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3616
3617         return true;
3618 }
3619
3620 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3621                                    struct dcerpc_binding_handle *b,
3622                                    struct policy_handle *handle,
3623                                    const char *key_name,
3624                                    uint32_t *count_p,
3625                                    struct spoolss_PrinterEnumValues **info_p)
3626 {
3627         struct spoolss_EnumPrinterDataEx r;
3628         struct spoolss_PrinterEnumValues *info;
3629         uint32_t needed;
3630         uint32_t count;
3631
3632         r.in.handle = handle;
3633         r.in.key_name = key_name;
3634         r.in.offered = 0;
3635         r.out.needed = &needed;
3636         r.out.count = &count;
3637         r.out.info = &info;
3638
3639         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3640
3641         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3642                 "EnumPrinterDataEx failed");
3643         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3644                 r.in.offered = needed;
3645                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3646                         "EnumPrinterDataEx failed");
3647         }
3648
3649         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3650
3651         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3652
3653         if (count_p) {
3654                 *count_p = count;
3655         }
3656         if (info_p) {
3657                 *info_p = info;
3658         }
3659
3660         return true;
3661 }
3662
3663 static bool test_SetPrinterData(struct torture_context *tctx,
3664                                 struct dcerpc_binding_handle *b,
3665                                 struct policy_handle *handle,
3666                                 const char *value_name,
3667                                 enum winreg_Type type,
3668                                 uint8_t *data,
3669                                 uint32_t offered);
3670 static bool test_DeletePrinterData(struct torture_context *tctx,
3671                                    struct dcerpc_binding_handle *b,
3672                                    struct policy_handle *handle,
3673                                    const char *value_name);
3674
3675 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3676                                              struct dcerpc_pipe *p,
3677                                              struct policy_handle *handle)
3678 {
3679         uint32_t count;
3680         struct spoolss_PrinterEnumValues *info;
3681         int i;
3682         uint32_t value_needed, data_needed;
3683         uint32_t value_offered, data_offered;
3684         WERROR result;
3685         struct dcerpc_binding_handle *b = p->binding_handle;
3686
3687         enum winreg_Type type;
3688         DATA_BLOB blob;
3689
3690         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3691
3692         torture_assert(tctx,
3693                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3694                                   "REG_SZ", "torture_data1", &type, &blob), "");
3695
3696         torture_assert(tctx,
3697                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3698                 "SetPrinterData failed");
3699
3700         blob = data_blob_string_const("torture_data2");
3701
3702         torture_assert(tctx,
3703                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3704                 "SetPrinterData failed");
3705
3706         blob = data_blob_talloc(tctx, NULL, 4);
3707         SIVAL(blob.data, 0, 0x11223344);
3708
3709         torture_assert(tctx,
3710                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3711                 "SetPrinterData failed");
3712
3713         torture_assert(tctx,
3714                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3715                 "failed to call EnumPrinterDataEx");
3716
3717         /* get the max sizes for value and data */
3718
3719         torture_assert(tctx,
3720                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3721                                      NULL, &value_needed, &data_needed,
3722                                      NULL, NULL, &result),
3723                 "EnumPrinterData failed");
3724         torture_assert_werr_ok(tctx, result, "unexpected result");
3725
3726         /* check if the reply from the EnumPrinterData really matches max values */
3727
3728         for (i=0; i < count; i++) {
3729                 if (info[i].value_name_len > value_needed) {
3730                         torture_fail(tctx,
3731                                 talloc_asprintf(tctx,
3732                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3733                                 info[i].value_name_len, value_needed));
3734                 }
3735                 if (info[i].data_length > data_needed) {
3736                         torture_fail(tctx,
3737                                 talloc_asprintf(tctx,
3738                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3739                                 info[i].data_length, data_needed));
3740                 }
3741         }
3742
3743         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3744          * sort or not sort the replies by value name, we should be able to do
3745          * the following entry comparison */
3746
3747         data_offered = data_needed;
3748         value_offered = value_needed;
3749
3750         for (i=0; i < count; i++) {
3751
3752                 const char *value_name;
3753                 uint8_t *data;
3754
3755                 torture_assert(tctx,
3756                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3757                                              &type, &value_needed, &data_needed,
3758                                              &value_name, &data, &result),
3759                         "EnumPrinterData failed");
3760
3761                 if (i -1 == count) {
3762                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3763                                 "unexpected result");
3764                         break;
3765                 } else {
3766                         torture_assert_werr_ok(tctx, result, "unexpected result");
3767                 }
3768
3769                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3770                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3771                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3772                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3773                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3774         }
3775
3776         torture_assert(tctx,
3777                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3778                 "DeletePrinterData failed");
3779         torture_assert(tctx,
3780                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3781                 "DeletePrinterData failed");
3782         torture_assert(tctx,
3783                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3784                 "DeletePrinterData failed");
3785
3786         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3787
3788         return true;
3789 }
3790
3791 static bool test_DeletePrinterData(struct torture_context *tctx,
3792                                    struct dcerpc_binding_handle *b,
3793                                    struct policy_handle *handle,
3794                                    const char *value_name)
3795 {
3796         NTSTATUS status;
3797         struct spoolss_DeletePrinterData r;
3798
3799         r.in.handle = handle;
3800         r.in.value_name = value_name;
3801
3802         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3803                 r.in.value_name);
3804
3805         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3806
3807         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3808         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3809
3810         return true;
3811 }
3812
3813 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3814                                      struct dcerpc_binding_handle *b,
3815                                      struct policy_handle *handle,
3816                                      const char *key_name,
3817                                      const char *value_name)
3818 {
3819         struct spoolss_DeletePrinterDataEx r;
3820
3821         r.in.handle = handle;
3822         r.in.key_name = key_name;
3823         r.in.value_name = value_name;
3824
3825         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3826                 r.in.key_name, r.in.value_name);
3827
3828         torture_assert_ntstatus_ok(tctx,
3829                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3830                 "DeletePrinterDataEx failed");
3831         torture_assert_werr_ok(tctx, r.out.result,
3832                 "DeletePrinterDataEx failed");
3833
3834         return true;
3835 }
3836
3837 static bool test_DeletePrinterKey(struct torture_context *tctx,
3838                                   struct dcerpc_binding_handle *b,
3839                                   struct policy_handle *handle,
3840                                   const char *key_name)
3841 {
3842         struct spoolss_DeletePrinterKey r;
3843
3844         r.in.handle = handle;
3845         r.in.key_name = key_name;
3846
3847         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3848
3849         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3850                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3851                 return true;
3852         }
3853
3854         torture_assert_ntstatus_ok(tctx,
3855                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3856                 "DeletePrinterKey failed");
3857         torture_assert_werr_ok(tctx, r.out.result,
3858                 "DeletePrinterKey failed");
3859
3860         return true;
3861 }
3862
3863 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3864                                  struct dcerpc_binding_handle *b,
3865                                  struct policy_handle *handle)
3866 {
3867         struct winreg_OpenHKLM r;
3868
3869         r.in.system_name = NULL;
3870         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3871         r.out.handle = handle;
3872
3873         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3874
3875         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3876         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3877
3878         return true;
3879 }
3880
3881 static void init_winreg_String(struct winreg_String *name, const char *s)
3882 {
3883         name->name = s;
3884         if (s) {
3885                 name->name_len = 2 * (strlen_m(s) + 1);
3886                 name->name_size = name->name_len;
3887         } else {
3888                 name->name_len = 0;
3889                 name->name_size = 0;
3890         }
3891 }
3892
3893 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3894                                      struct dcerpc_binding_handle *b,
3895                                      struct policy_handle *hive_handle,
3896                                      const char *keyname,
3897                                      uint32_t options,
3898                                      struct policy_handle *key_handle)
3899 {
3900         struct winreg_OpenKey r;
3901
3902         r.in.parent_handle = hive_handle;
3903         init_winreg_String(&r.in.keyname, keyname);
3904         r.in.options = options;
3905         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3906         r.out.handle = key_handle;
3907
3908         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3909
3910         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3911         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3912
3913         return true;
3914 }
3915
3916 static bool test_winreg_OpenKey(struct torture_context *tctx,
3917                                 struct dcerpc_binding_handle *b,
3918                                 struct policy_handle *hive_handle,
3919                                 const char *keyname,
3920                                 struct policy_handle *key_handle)
3921 {
3922         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
3923                                         REG_OPTION_NON_VOLATILE, key_handle);
3924 }
3925
3926 static bool test_winreg_CloseKey(struct torture_context *tctx,
3927                                  struct dcerpc_binding_handle *b,
3928                                  struct policy_handle *handle)
3929 {
3930         struct winreg_CloseKey r;
3931
3932         r.in.handle = handle;
3933         r.out.handle = handle;
3934
3935         torture_comment(tctx, "Testing winreg_CloseKey\n");
3936
3937         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3938         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3939
3940         return true;
3941 }
3942
3943 bool test_winreg_QueryValue(struct torture_context *tctx,
3944                             struct dcerpc_binding_handle *b,
3945                             struct policy_handle *handle,
3946                             const char *value_name,
3947                             enum winreg_Type *type_p,
3948                             uint32_t *data_size_p,
3949                             uint32_t *data_length_p,
3950                             uint8_t **data_p)
3951 {
3952         struct winreg_QueryValue r;
3953         enum winreg_Type type = REG_NONE;
3954         uint32_t data_size = 0;
3955         uint32_t data_length = 0;
3956         struct winreg_String valuename;
3957         uint8_t *data = NULL;
3958
3959         init_winreg_String(&valuename, value_name);
3960
3961         data = talloc_zero_array(tctx, uint8_t, 0);
3962
3963         r.in.handle = handle;
3964         r.in.value_name = &valuename;
3965         r.in.type = &type;
3966         r.in.data_size = &data_size;
3967         r.in.data_length = &data_length;
3968         r.in.data = data;
3969         r.out.type = &type;
3970         r.out.data = data;
3971         r.out.data_size = &data_size;
3972         r.out.data_length = &data_length;
3973
3974         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3975
3976         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3977         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3978                 *r.in.data_size = *r.out.data_size;
3979                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3980                 r.in.data = data;
3981                 r.out.data = data;
3982                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3983         }
3984         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3985
3986         if (type_p) {
3987                 *type_p = *r.out.type;
3988         }
3989         if (data_size_p) {
3990                 *data_size_p = *r.out.data_size;
3991         }
3992         if (data_length_p) {
3993                 *data_length_p = *r.out.data_length;
3994         }
3995         if (data_p) {
3996                 *data_p = r.out.data;
3997         }
3998
3999         return true;
4000 }
4001
4002 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4003                                           struct dcerpc_binding_handle *b,
4004                                           struct policy_handle *handle,
4005                                           const char *printer_name,
4006                                           const char *key_name,
4007                                           const char *value_name,
4008                                           enum winreg_Type *w_type,
4009                                           uint32_t *w_size,
4010                                           uint32_t *w_length,
4011                                           uint8_t **w_data)
4012 {
4013         const char *printer_key;
4014         struct policy_handle key_handle;
4015
4016         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4017                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4018
4019         torture_assert(tctx,
4020                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4021
4022         torture_assert(tctx,
4023                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4024
4025         torture_assert(tctx,
4026                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4027
4028         return true;
4029 }
4030
4031 static bool test_GetForm_winreg(struct torture_context *tctx,
4032                                 struct dcerpc_binding_handle *b,
4033                                 struct policy_handle *handle,
4034                                 const char *key_name,
4035                                 const char *form_name,
4036                                 enum winreg_Type *w_type,
4037                                 uint32_t *w_size,
4038                                 uint32_t *w_length,
4039                                 uint8_t **w_data)
4040 {
4041         struct policy_handle key_handle;
4042
4043         torture_assert(tctx,
4044                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4045
4046         torture_assert(tctx,
4047                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4048
4049         torture_assert(tctx,
4050                 test_winreg_CloseKey(tctx, b, &key_handle), "");
4051
4052         return true;
4053 }
4054
4055 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4056                                       struct dcerpc_binding_handle *b,
4057                                       struct policy_handle *handle,
4058                                       const char *symlink_keyname,
4059                                       const char *symlink_destination)
4060 {
4061         /* check if the first key is a symlink to the second key */
4062
4063         enum winreg_Type w_type;
4064         uint32_t w_size;
4065         uint32_t w_length;
4066         uint8_t *w_data;
4067         struct policy_handle key_handle;
4068         DATA_BLOB blob;
4069         const char *str;
4070
4071         if (torture_setting_bool(tctx, "samba3", false)) {
4072                 torture_skip(tctx, "skip winreg symlink test against samba");
4073         }
4074
4075         torture_assert(tctx,
4076                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4077                         "failed to open key link");
4078
4079         torture_assert(tctx,
4080                 test_winreg_QueryValue(tctx, b, &key_handle,
4081                                        "SymbolicLinkValue",
4082                                        &w_type, &w_size, &w_length, &w_data),
4083                 "failed to query for 'SymbolicLinkValue' attribute");
4084
4085         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4086
4087         blob = data_blob(w_data, w_size);
4088         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
4089
4090         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4091
4092         torture_assert(tctx,
4093                 test_winreg_CloseKey(tctx, b, &key_handle),
4094                 "failed to close key link");
4095
4096         return true;
4097 }
4098
4099 static const char *strip_unc(const char *unc)
4100 {
4101         char *name;
4102
4103         if (!unc) {
4104                 return NULL;
4105         }
4106
4107         if (unc[0] == '\\' && unc[1] == '\\') {
4108                 unc +=2;
4109         }
4110
4111         name = strchr(unc, '\\');
4112         if (name) {
4113                 return name+1;
4114         }
4115
4116         return unc;
4117 }
4118
4119 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4120                                        struct dcerpc_binding_handle *b,
4121                                        struct policy_handle *handle,
4122                                        const char *printer_name,
4123                                        struct dcerpc_binding_handle *winreg_handle,
4124                                        struct policy_handle *hive_handle)
4125 {
4126         union spoolss_PrinterInfo info;
4127         const char *keys[] = {
4128                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4129                 TOP_LEVEL_PRINT_PRINTERS_KEY
4130         };
4131         int i;
4132         const char *printername, *sharename;
4133
4134         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4135
4136         torture_assert(tctx,
4137                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4138                 "failed to get printer info level 2");
4139
4140         printername = strip_unc(info.info2.printername);
4141         sharename = strip_unc(info.info2.sharename);
4142
4143 #define test_sz(wname, iname) \
4144 do {\
4145         DATA_BLOB blob;\
4146         const char *str;\
4147         enum winreg_Type w_type;\
4148         uint32_t w_size;\
4149         uint32_t w_length;\
4150         uint8_t *w_data;\
4151         torture_assert(tctx,\
4152                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4153                                        &w_type, &w_size, &w_length, &w_data),\
4154                 "failed to query winreg");\
4155         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4156         blob = data_blob(w_data, w_size);\
4157         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);\
4158         if (w_size == 2 && iname == NULL) {\
4159                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4160         } else {\
4161                 torture_assert_str_equal(tctx, str, iname,\
4162                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4163         }\
4164 } while(0);
4165
4166 #define test_dword(wname, iname) \
4167 do {\
4168         uint32_t value;\
4169         enum winreg_Type w_type;\
4170         uint32_t w_size;\
4171         uint32_t w_length;\
4172         uint8_t *w_data;\
4173         torture_assert(tctx,\
4174                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4175                                        &w_type, &w_size, &w_length, &w_data),\
4176                 "failed to query winreg");\
4177         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4178         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4179         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4180         value = IVAL(w_data, 0);\
4181         torture_assert_int_equal(tctx, value, iname,\
4182                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4183 } while(0);
4184
4185 #define test_dm(wname, iname) \
4186 do {\
4187         DATA_BLOB blob;\
4188         struct spoolss_DeviceMode dm;\
4189         enum ndr_err_code ndr_err;\
4190         enum winreg_Type w_type;\
4191         uint32_t w_size;\
4192         uint32_t w_length;\
4193         uint8_t *w_data;\
4194         torture_assert(tctx,\
4195                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4196                                        &w_type, &w_size, &w_length, &w_data),\
4197                 "failed to query winreg");\
4198         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4199         blob = data_blob(w_data, w_size);\
4200         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &dm,\
4201                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4202         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4203         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4204                 "dm unequal");\
4205 } while(0);
4206
4207 #define test_sd(wname, iname) \
4208 do {\
4209         DATA_BLOB blob;\
4210         struct security_descriptor sd;\
4211         enum ndr_err_code ndr_err;\
4212         enum winreg_Type w_type;\
4213         uint32_t w_size;\
4214         uint32_t w_length;\
4215         uint8_t *w_data;\
4216         torture_assert(tctx,\
4217                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4218                                        &w_type, &w_size, &w_length, &w_data),\
4219                 "failed to query winreg");\
4220         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4221         blob = data_blob(w_data, w_size);\
4222         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &sd,\
4223                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4224         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4225         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4226                 "sd unequal");\
4227 } while(0);
4228
4229 #define test_multi_sz(wname, iname) \
4230 do {\
4231         DATA_BLOB blob;\
4232         const char **array;\
4233         enum winreg_Type w_type;\
4234         uint32_t w_size;\
4235         uint32_t w_length;\
4236         uint8_t *w_data;\
4237         int i;\
4238         torture_assert(tctx,\
4239                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4240                                        &w_type, &w_size, &w_length, &w_data),\
4241                 "failed to query winreg");\
4242         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4243         blob = data_blob(w_data, w_size);\
4244         torture_assert(tctx, \
4245                 pull_reg_multi_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &array),\
4246                 "failed to pull multi sz");\
4247         for (i=0; array[i] != NULL; i++) {\
4248                 torture_assert_str_equal(tctx, array[i], iname[i],\
4249                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4250         }\
4251 } while(0);
4252
4253
4254         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4255                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4256                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4257         {
4258                 torture_warning(tctx, "failed to check for winreg symlink");
4259         }
4260
4261
4262         for (i=0; i < ARRAY_SIZE(keys); i++) {
4263
4264                 const char *printer_key;
4265                 struct policy_handle key_handle;
4266
4267                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4268                         keys[i], printer_name);
4269
4270                 torture_assert(tctx,
4271                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4272
4273                 test_sz("Name", printername);
4274                 test_sz("Share Name", sharename);
4275                 test_sz("Port", info.info2.portname);
4276                 test_sz("Printer Driver", info.info2.drivername);
4277                 test_sz("Description", info.info2.comment);
4278                 test_sz("Location", info.info2.location);
4279                 test_sz("Separator File", info.info2.sepfile);
4280                 test_sz("Print Processor", info.info2.printprocessor);
4281                 test_sz("Datatype", info.info2.datatype);
4282                 test_sz("Parameters", info.info2.parameters);
4283                 /* winreg: 0, spoolss not */
4284 /*              test_dword("Attributes", info.info2.attributes); */
4285                 test_dword("Priority", info.info2.priority);
4286                 test_dword("Default Priority", info.info2.defaultpriority);
4287                 /* winreg: 60, spoolss: 0 */
4288 /*              test_dword("StartTime", info.info2.starttime); */
4289 /*              test_dword("UntilTime", info.info2.untiltime); */
4290                 /* winreg != spoolss */
4291 /*              test_dword("Status", info.info2.status); */
4292                 test_dm("Default DevMode", info.info2.devmode);
4293                 test_sd("Security", info.info2.secdesc);
4294
4295                 torture_assert(tctx,
4296                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4297         }
4298
4299 #undef test_dm
4300 #undef test_sd
4301
4302         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4303
4304         return true;
4305 }
4306
4307 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4308                                          struct dcerpc_binding_handle *b,
4309                                          struct policy_handle *handle,
4310                                          const char *driver_name,
4311                                          const char *architecture,
4312                                          uint32_t level,
4313                                          uint32_t client_major_version,
4314                                          uint32_t client_minor_version,
4315                                          union spoolss_DriverInfo *info_p,
4316                                          WERROR *result);
4317
4318 static const char *strip_path(const char *path)
4319 {
4320         char *p;
4321
4322         if (path == NULL) {
4323                 return NULL;
4324         }
4325
4326         p = strrchr(path, '\\');
4327         if (p) {
4328                 return p+1;
4329         }
4330
4331         return path;
4332 }
4333
4334 static const char **strip_paths(const char **path_array)
4335 {
4336         int i;
4337
4338         if (path_array == NULL) {
4339                 return NULL;
4340         }
4341
4342         for (i=0; path_array[i] != NULL; i++) {
4343                 path_array[i] = strip_path(path_array[i]);
4344         }
4345
4346         return path_array;
4347 }
4348
4349 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4350 {
4351         time_t t;
4352         struct tm *tm;
4353         t = nt_time_to_unix(nt);
4354         tm = localtime(&t);
4355
4356         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4357                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4358 }
4359
4360 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4361 {
4362         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4363                 (unsigned)((v >> 48) & 0xFFFF),
4364                 (unsigned)((v >> 32) & 0xFFFF),
4365                 (unsigned)((v >> 16) & 0xFFFF),
4366                 (unsigned)(v & 0xFFFF));
4367 }
4368
4369 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4370                                       struct dcerpc_binding_handle *b,
4371                                       struct policy_handle *handle,
4372                                       const char *printer_name,
4373                                       const char *driver_name,
4374                                       const char *environment,
4375                                       struct dcerpc_binding_handle *winreg_handle,
4376                                       struct policy_handle *hive_handle)
4377 {
4378         WERROR result;
4379         union spoolss_DriverInfo info;
4380         const char *driver_key;
4381         struct policy_handle key_handle;
4382
4383         const char *driver_path;
4384         const char *data_file;
4385         const char *config_file;
4386         const char *help_file;
4387         const char **dependent_files;
4388
4389         const char *driver_date;
4390         const char *inbox_driver_date;
4391
4392         const char *driver_version;
4393         const char *inbox_driver_version;
4394
4395         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4396
4397         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4398                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4399                                      environment,
4400                                      3,
4401                                      driver_name);
4402
4403         torture_assert(tctx,
4404                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4405                 "failed to open driver key");
4406
4407         if (torture_setting_bool(tctx, "samba3", false)) {
4408                 goto try_level3;
4409         }
4410
4411         torture_assert(tctx,
4412                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4413                 "failed to get driver info level 8");
4414
4415         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4416                 goto try_level6;
4417         }
4418
4419         driver_path     = strip_path(info.info8.driver_path);
4420         data_file       = strip_path(info.info8.data_file);
4421         config_file     = strip_path(info.info8.config_file);
4422         help_file       = strip_path(info.info8.help_file);
4423         dependent_files = strip_paths(info.info8.dependent_files);
4424
4425         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4426         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4427
4428         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4429         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4430
4431         test_sz("Configuration File",           config_file);
4432         test_sz("Data File",                    data_file);
4433         test_sz("Datatype",                     info.info8.default_datatype);
4434         test_sz("Driver",                       driver_path);
4435         test_sz("DriverDate",                   driver_date);
4436         test_sz("DriverVersion",                driver_version);
4437         test_sz("HardwareID",                   info.info8.hardware_id);
4438         test_sz("Help File",                    help_file);
4439         test_sz("InfPath",                      info.info8.inf_path);
4440         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4441         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4442         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4443         test_sz("Monitor",                      info.info8.monitor_name);
4444         test_sz("OEM URL",                      info.info8.manufacturer_url);
4445         test_sz("Print Processor",              info.info8.print_processor);
4446         test_sz("Provider",                     info.info8.provider);
4447         test_sz("VendorSetup",                  info.info8.vendor_setup);
4448         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4449         test_multi_sz("Dependent Files",        dependent_files);
4450         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4451         test_multi_sz("Previous Names",         info.info8.previous_names);
4452 /*      test_dword("Attributes",                ?); */
4453         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4454         test_dword("Version",                   info.info8.version);
4455 /*      test_dword("TempDir",                   ?); */
4456
4457  try_level6:
4458
4459         torture_assert(tctx,
4460                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4461                 "failed to get driver info level 6");
4462
4463         driver_path     = strip_path(info.info6.driver_path);
4464         data_file       = strip_path(info.info6.data_file);
4465         config_file     = strip_path(info.info6.config_file);
4466         help_file       = strip_path(info.info6.help_file);
4467         dependent_files = strip_paths(info.info6.dependent_files);
4468
4469         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4470
4471         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4472
4473         test_sz("Configuration File",           config_file);
4474         test_sz("Data File",                    data_file);
4475         test_sz("Datatype",                     info.info6.default_datatype);
4476         test_sz("Driver",                       driver_path);
4477         test_sz("DriverDate",                   driver_date);
4478         test_sz("DriverVersion",                driver_version);
4479         test_sz("HardwareID",                   info.info6.hardware_id);
4480         test_sz("Help File",                    help_file);
4481         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4482         test_sz("Monitor",                      info.info6.monitor_name);
4483         test_sz("OEM URL",                      info.info6.manufacturer_url);
4484         test_sz("Provider",                     info.info6.provider);
4485         test_multi_sz("Dependent Files",        dependent_files);
4486         test_multi_sz("Previous Names",         info.info6.previous_names);
4487 /*      test_dword("Attributes",                ?); */
4488         test_dword("Version",                   info.info6.version);
4489 /*      test_dword("TempDir",                   ?); */
4490
4491  try_level3:
4492
4493         torture_assert(tctx,
4494                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4495                 "failed to get driver info level 3");
4496
4497         driver_path     = strip_path(info.info3.driver_path);
4498         data_file       = strip_path(info.info3.data_file);
4499         config_file     = strip_path(info.info3.config_file);
4500         help_file       = strip_path(info.info3.help_file);
4501         dependent_files = strip_paths(info.info3.dependent_files);
4502
4503         test_sz("Configuration File",           config_file);
4504         test_sz("Data File",                    data_file);
4505         test_sz("Datatype",                     info.info3.default_datatype);
4506         test_sz("Driver",                       driver_path);
4507         test_sz("Help File",                    help_file);
4508         test_sz("Monitor",                      info.info3.monitor_name);
4509         test_multi_sz("Dependent Files",        dependent_files);
4510 /*      test_dword("Attributes",                ?); */
4511         test_dword("Version",                   info.info3.version);
4512 /*      test_dword("TempDir",                   ?); */
4513
4514
4515         torture_assert(tctx,
4516                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4517
4518         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4519
4520         return true;
4521 }
4522
4523 #undef test_sz
4524 #undef test_dword
4525
4526 static bool test_SetPrinterData(struct torture_context *tctx,
4527                                 struct dcerpc_binding_handle *b,
4528                                 struct policy_handle *handle,
4529                                 const char *value_name,
4530                                 enum winreg_Type type,
4531                                 uint8_t *data,
4532                                 uint32_t offered)
4533 {
4534         struct spoolss_SetPrinterData r;
4535
4536         r.in.handle = handle;
4537         r.in.value_name = value_name;
4538         r.in.type = type;
4539         r.in.data = data;
4540         r.in.offered = offered;
4541
4542         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4543                 r.in.value_name);
4544
4545         torture_assert_ntstatus_ok(tctx,
4546                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4547                 "SetPrinterData failed");
4548         torture_assert_werr_ok(tctx, r.out.result,
4549                 "SetPrinterData failed");
4550
4551         return true;
4552 }
4553
4554 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4555                                        struct dcerpc_binding_handle *b,
4556                                        struct policy_handle *handle,
4557                                        const char *printer_name,
4558                                        struct dcerpc_binding_handle *winreg_handle,
4559                                        struct policy_handle *hive_handle)
4560 {
4561         const char *values[] = {
4562                 "spootyfoot",
4563                 "spooty\\foot",
4564 #if 0
4565         /* FIXME: not working with s3 atm. */
4566                 "spooty,foot",
4567                 "spooty,fo,ot",
4568 #endif
4569                 "spooty foot",
4570 #if 0
4571         /* FIXME: not working with s3 atm. */
4572                 "spooty\\fo,ot",
4573                 "spooty,fo\\ot"
4574 #endif
4575         };
4576         int i;
4577
4578         for (i=0; i < ARRAY_SIZE(values); i++) {
4579
4580                 enum winreg_Type type;
4581                 DATA_BLOB blob;
4582                 uint8_t *data;
4583                 uint32_t needed;
4584
4585                 torture_assert(tctx,
4586                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4587                                           "REG_SZ", "dog", &type, &blob), "");
4588
4589                 torture_assert(tctx,
4590                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4591                         "SetPrinterData failed");
4592
4593                 torture_assert(tctx,
4594                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4595                         "GetPrinterData failed");
4596
4597                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4598                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4599                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4600
4601                 if (winreg_handle && hive_handle) {
4602
4603                         enum winreg_Type w_type;
4604                         uint32_t w_size;
4605                         uint32_t w_length;
4606                         uint8_t *w_data;
4607
4608                         torture_assert(tctx,
4609                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4610                                         printer_name, "PrinterDriverData", values[i],
4611                                         &w_type, &w_size, &w_length, &w_data), "");
4612
4613                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4614                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4615                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4616                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4617                 }
4618
4619                 torture_assert(tctx,
4620                         test_DeletePrinterData(tctx, b, handle, values[i]),
4621                         "DeletePrinterData failed");
4622         }
4623
4624         return true;
4625 }
4626
4627
4628 static bool test_EnumPrinterKey(struct torture_context *tctx,
4629                                 struct dcerpc_binding_handle *b,
4630                                 struct policy_handle *handle,
4631                                 const char *key_name,
4632                                 const char ***array);
4633
4634 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4635                                   struct dcerpc_binding_handle *b,
4636                                   struct policy_handle *handle,
4637                                   const char *key_name,
4638                                   const char *value_name,
4639                                   enum winreg_Type type,
4640                                   uint8_t *data,
4641                                   uint32_t offered)
4642 {
4643         NTSTATUS status;
4644         struct spoolss_SetPrinterDataEx r;
4645
4646         r.in.handle = handle;
4647         r.in.key_name = key_name;
4648         r.in.value_name = value_name;
4649         r.in.type = type;
4650         r.in.data = data;
4651         r.in.offered = offered;
4652
4653         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4654                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4655
4656         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4657
4658         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4659         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4660
4661         return true;
4662 }
4663
4664 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4665                                          struct dcerpc_pipe *p,
4666                                          struct policy_handle *handle,
4667                                          const char *printername,
4668                                          struct dcerpc_binding_handle *winreg_handle,
4669                                          struct policy_handle *hive_handle)
4670 {
4671         struct dcerpc_binding_handle *b = p->binding_handle;
4672         const char *value_name = "dog";
4673         const char *keys[] = {
4674                 "torturedataex",
4675                 "torture data ex",
4676 #if 0
4677         /* FIXME: not working with s3 atm. */
4678                 "torturedataex_with_subkey\\subkey",
4679                 "torturedataex_with_subkey\\subkey:0",
4680                 "torturedataex_with_subkey\\subkey:1",
4681                 "torturedataex_with_subkey\\subkey\\subsubkey",
4682                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4683                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4684 #endif
4685                 "torture,data",
4686 #if 0
4687         /* FIXME: not working with s3 atm. */
4688
4689                 "torture,data,ex",
4690                 "torture,data\\ex",
4691                 "torture\\data,ex"
4692 #endif
4693         };
4694         enum winreg_Type types[] = {
4695                 REG_SZ,
4696                 REG_MULTI_SZ,
4697                 REG_DWORD,
4698                 REG_BINARY
4699         };
4700         const char *str = "abcdefghijklmnopqrstuvwxzy";
4701         int i, t, s;
4702
4703
4704         for (i=0; i < ARRAY_SIZE(keys); i++) {
4705         for (t=0; t < ARRAY_SIZE(types); t++) {
4706         for (s=0; s < strlen(str); s++) {
4707
4708                 char *c;
4709                 const char *key;
4710                 enum winreg_Type type;
4711                 const char *string = talloc_strndup(tctx, str, s);
4712                 DATA_BLOB blob = data_blob_string_const(string);
4713                 const char **subkeys;
4714                 DATA_BLOB data;
4715                 uint8_t *data_out;
4716                 uint32_t needed, offered = 0;
4717                 uint32_t ecount;
4718                 struct spoolss_PrinterEnumValues *einfo;
4719
4720                 if (types[t] == REG_DWORD) {
4721                         s = 0xffff;
4722                 }
4723
4724                 if (torture_setting_bool(tctx, "samba3", false)) {
4725                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
4726                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4727                                 continue;
4728                         }
4729                 }
4730
4731                 switch (types[t]) {
4732                 case REG_BINARY:
4733                         data = blob;
4734                         offered = blob.length;
4735                         break;
4736                 case REG_DWORD:
4737                         data = data_blob_talloc(tctx, NULL, 4);
4738                         SIVAL(data.data, 0, 0x12345678);
4739                         offered = 4;
4740                         break;
4741                 case REG_SZ:
4742                         torture_assert(tctx,
4743                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4744                                                   "REG_SZ", string, &type, &data), "");
4745                         offered = data.length;
4746                         /*strlen_m_term(data.string)*2;*/
4747                         break;
4748                 case REG_MULTI_SZ:
4749                         torture_assert(tctx,
4750                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4751                                                   "REG_SZ", string, &type, &data), "");
4752                         torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
4753                         memset(&data.data[data.length - 2], '\0', 2);
4754                         offered = data.length;
4755                         break;
4756                 default:
4757                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4758                 }
4759
4760                 torture_assert(tctx,
4761                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4762                         "failed to call SetPrinterDataEx");
4763
4764                 torture_assert(tctx,
4765                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4766                         "failed to call GetPrinterDataEx");
4767
4768                 torture_assert(tctx,
4769                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4770                         "failed to call EnumPrinterDataEx");
4771
4772                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4773                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4774                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4775
4776                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4777                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4778                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4779                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4780                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4781                 if (einfo[0].data_length > 0) {
4782                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4783                 }
4784
4785                 if (winreg_handle && hive_handle) {
4786                         enum winreg_Type w_type;
4787                         uint32_t w_size;
4788                         uint32_t w_length;
4789                         uint8_t *w_data;
4790
4791                         torture_assert(tctx,
4792                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4793                                         printername, keys[i], value_name,
4794                                         &w_type, &w_size, &w_length, &w_data), "");
4795
4796                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4797                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4798                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4799                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4800                 }
4801
4802                 key = talloc_strdup(tctx, keys[i]);
4803
4804                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4805                         return false;
4806                 }
4807
4808                 c = strchr(key, '\\');
4809                 if (c) {
4810                         int k;
4811
4812                         /* we have subkeys */
4813
4814                         *c = 0;
4815
4816                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4817                                 return false;
4818                         }
4819
4820                         for (k=0; subkeys && subkeys[k]; k++) {
4821
4822                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4823
4824                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4825                                         return false;
4826                                 }
4827                         }
4828
4829                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4830                                 return false;
4831                         }
4832
4833                 } else {
4834                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4835                                 return false;
4836                         }
4837                 }
4838         }
4839         }
4840         }
4841
4842         return true;
4843 }
4844
4845 static bool test_PrinterData_winreg(struct torture_context *tctx,
4846                                     struct dcerpc_pipe *p,
4847                                     struct policy_handle *handle,
4848                                     const char *printer_name)
4849 {
4850         struct dcerpc_binding_handle *b = p->binding_handle;
4851         struct dcerpc_pipe *p2;
4852         bool ret = true;
4853         struct policy_handle hive_handle;
4854         struct dcerpc_binding_handle *b2;
4855
4856         torture_assert_ntstatus_ok(tctx,
4857                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4858                 "could not open winreg pipe");
4859         b2 = p2->binding_handle;
4860
4861         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4862
4863         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4864         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4865
4866         test_winreg_CloseKey(tctx, b2, &hive_handle);
4867
4868         talloc_free(p2);
4869
4870         return ret;
4871 }
4872
4873 static bool test_Forms_winreg(struct torture_context *tctx,
4874                               struct dcerpc_binding_handle *b,
4875                               struct policy_handle *handle,
4876                               bool print_server,
4877                               const char *printer_name)
4878 {
4879         struct dcerpc_pipe *p2;
4880         bool ret = true;
4881         struct policy_handle hive_handle;
4882         struct dcerpc_binding_handle *b2;
4883
4884         torture_assert_ntstatus_ok(tctx,
4885                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4886                 "could not open winreg pipe");
4887         b2 = p2->binding_handle;
4888
4889         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4890
4891         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4892
4893         test_winreg_CloseKey(tctx, b2, &hive_handle);
4894
4895         talloc_free(p2);
4896
4897         return ret;
4898 }
4899
4900 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
4901                                     struct dcerpc_pipe *p,
4902                                     struct policy_handle *handle,
4903                                     const char *printer_name)
4904 {
4905         struct dcerpc_binding_handle *b = p->binding_handle;
4906         struct dcerpc_pipe *p2;
4907         bool ret = true;
4908         struct policy_handle hive_handle;
4909         struct dcerpc_binding_handle *b2;
4910
4911         torture_assert_ntstatus_ok(tctx,
4912                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4913                 "could not open winreg pipe");
4914         b2 = p2->binding_handle;
4915
4916         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4917
4918         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
4919
4920         test_winreg_CloseKey(tctx, b2, &hive_handle);
4921
4922         talloc_free(p2);
4923
4924         return ret;
4925 }
4926
4927 static bool test_DriverInfo_winreg(struct torture_context *tctx,
4928                                    struct dcerpc_pipe *p,
4929                                    struct policy_handle *handle,
4930                                    const char *printer_name,
4931                                    const char *driver_name,
4932                                    const char *environment)
4933 {
4934         struct dcerpc_binding_handle *b = p->binding_handle;
4935         struct dcerpc_pipe *p2;
4936         bool ret = true;
4937         struct policy_handle hive_handle;
4938         struct dcerpc_binding_handle *b2;
4939
4940         torture_assert_ntstatus_ok(tctx,
4941                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4942                 "could not open winreg pipe");
4943         b2 = p2->binding_handle;
4944
4945         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4946
4947         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
4948
4949         test_winreg_CloseKey(tctx, b2, &hive_handle);
4950
4951         talloc_free(p2);
4952
4953         return ret;
4954 }
4955
4956 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
4957                                        struct dcerpc_pipe *p,
4958                                        struct policy_handle *handle,
4959                                        const char *printer_name)
4960 {
4961         struct spoolss_SetPrinterInfoCtr info_ctr;
4962         struct spoolss_DevmodeContainer devmode_ctr;
4963         struct sec_desc_buf secdesc_ctr;
4964         union spoolss_SetPrinterInfo sinfo;
4965         union spoolss_PrinterInfo info;
4966         struct dcerpc_binding_handle *b = p->binding_handle;
4967
4968         ZERO_STRUCT(info_ctr);
4969         ZERO_STRUCT(devmode_ctr);
4970         ZERO_STRUCT(secdesc_ctr);
4971
4972         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
4973
4974         torture_assert(tctx,
4975                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4976                 "failed to query Printer level 2");
4977
4978         torture_assert(tctx,
4979                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
4980                 "failed to convert");
4981
4982         info_ctr.level = 2;
4983         info_ctr.info = sinfo;
4984
4985 #define TEST_SET_SZ(wname, iname, val) \
4986 do {\
4987         enum winreg_Type type;\
4988         uint8_t *data;\
4989         uint32_t needed;\
4990         DATA_BLOB blob;\
4991         const char *str;\
4992         sinfo.info2->iname = val;\
4993         torture_assert(tctx,\
4994                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
4995                 "failed to call SetPrinter");\
4996         torture_assert(tctx,\
4997                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
4998                 "failed to query");\
4999         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5000         blob = data_blob_const(data, needed);\
5001         torture_assert(tctx,\
5002                 pull_reg_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &str),\
5003                 "failed to pull REG_SZ");\
5004         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5005 } while(0);
5006
5007 #define TEST_SET_DWORD(wname, iname, val) \
5008 do {\
5009         enum winreg_Type type;\
5010         uint8_t *data;\
5011         uint32_t needed;\
5012         uint32_t value;\
5013         sinfo.info2->iname = val;\
5014         torture_assert(tctx,\
5015                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5016                 "failed to call SetPrinter");\
5017         torture_assert(tctx,\
5018                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5019                 "failed to query");\
5020         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5021         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5022         value = IVAL(data, 0); \
5023         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5024 } while(0);
5025
5026         TEST_SET_SZ("description", comment, "newval");
5027         TEST_SET_SZ("location", location, "newval");
5028 /*      TEST_SET_DWORD("priority", priority, 25); */
5029
5030         /* FIXME gd: complete the list */
5031
5032 #undef TEST_SET_SZ
5033 #undef TEST_DWORD
5034
5035         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5036
5037         return true;
5038 }
5039
5040 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5041                                          struct dcerpc_binding_handle *b,
5042                                          struct policy_handle *handle,
5043                                          uint32_t *change_id)
5044 {
5045         enum winreg_Type type;
5046         uint8_t *data;
5047         uint32_t needed;
5048
5049         torture_assert(tctx,
5050                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5051                 "failed to call GetPrinterData");
5052
5053         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5054         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5055
5056         *change_id = IVAL(data, 0);
5057
5058         return true;
5059 }
5060
5061 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5062                                            struct dcerpc_pipe *p,
5063                                            struct policy_handle *handle,
5064                                            uint32_t *change_id)
5065 {
5066         enum winreg_Type type;
5067         uint8_t *data;
5068         uint32_t needed;
5069
5070         torture_assert(tctx,
5071                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5072                 "failed to call GetPrinterData");
5073
5074         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5075         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5076
5077         *change_id = IVAL(data, 0);
5078
5079         return true;
5080 }
5081
5082 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5083                                          struct dcerpc_binding_handle *b,
5084                                          struct policy_handle *handle,
5085                                          uint32_t *change_id)
5086 {
5087         union spoolss_PrinterInfo info;
5088
5089         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5090                 "failed to query Printer level 0");
5091
5092         *change_id = info.info0.change_id;
5093
5094         return true;
5095 }
5096
5097 static bool test_ChangeID(struct torture_context *tctx,
5098                           struct dcerpc_pipe *p,
5099                           struct policy_handle *handle)
5100 {
5101         uint32_t change_id, change_id_ex, change_id_info;
5102         uint32_t change_id2, change_id_ex2, change_id_info2;
5103         union spoolss_PrinterInfo info;
5104         const char *comment;
5105         struct dcerpc_binding_handle *b = p->binding_handle;
5106
5107         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5108
5109         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5110                 "failed to query for ChangeID");
5111         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5112                 "failed to query for ChangeID");
5113         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5114                 "failed to query for ChangeID");
5115
5116         torture_assert_int_equal(tctx, change_id, change_id_ex,
5117                 "change_ids should all be equal");
5118         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5119                 "change_ids should all be equal");
5120
5121
5122         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5123
5124         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5125                 "failed to query for ChangeID");
5126         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5127                 "failed to query Printer level 2");
5128         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5129                 "failed to query for ChangeID");
5130         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5131                 "failed to query for ChangeID");
5132         torture_assert_int_equal(tctx, change_id, change_id_ex,
5133                 "change_id should not have changed");
5134         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5135                 "change_id should not have changed");
5136
5137
5138         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5139
5140         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5141                 "failed to query for ChangeID");
5142         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5143                 "failed to query for ChangeID");
5144         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5145                 "failed to query for ChangeID");
5146         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5147                 "failed to query Printer level 2");
5148         comment = talloc_strdup(tctx, info.info2.comment);
5149
5150         {
5151                 struct spoolss_SetPrinterInfoCtr info_ctr;
5152                 struct spoolss_DevmodeContainer devmode_ctr;
5153                 struct sec_desc_buf secdesc_ctr;
5154                 union spoolss_SetPrinterInfo sinfo;
5155
5156                 ZERO_STRUCT(info_ctr);
5157                 ZERO_STRUCT(devmode_ctr);
5158                 ZERO_STRUCT(secdesc_ctr);
5159
5160
5161                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5162                 sinfo.info2->comment    = "torture_comment";
5163
5164                 info_ctr.level = 2;
5165                 info_ctr.info = sinfo;
5166
5167                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5168                         "failed to call SetPrinter");
5169
5170                 sinfo.info2->comment    = comment;
5171
5172                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5173                         "failed to call SetPrinter");
5174
5175         }
5176
5177         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5178                 "failed to query for ChangeID");
5179         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5180                 "failed to query for ChangeID");
5181         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5182                 "failed to query for ChangeID");
5183
5184         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5185                 "change_ids should all be equal");
5186         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5187                 "change_ids should all be equal");
5188
5189         torture_assert(tctx, (change_id < change_id2),
5190                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5191                 change_id2, change_id));
5192         torture_assert(tctx, (change_id_ex < change_id_ex2),
5193                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5194                 change_id_ex2, change_id_ex));
5195         torture_assert(tctx, (change_id_info < change_id_info2),
5196                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5197                 change_id_info2, change_id_info));
5198
5199         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5200
5201         return true;
5202 }
5203
5204 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5205                                        struct dcerpc_pipe *p,
5206                                        struct policy_handle *handle)
5207 {
5208         NTSTATUS status;
5209         struct dcerpc_binding *b;
5210         struct dcerpc_pipe *p2;
5211         struct spoolss_ClosePrinter cp;
5212
5213         /* only makes sense on SMB */
5214         if (p->conn->transport.transport != NCACN_NP) {
5215                 return true;
5216         }
5217
5218         torture_comment(tctx, "Testing close on secondary pipe\n");
5219
5220         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5221         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5222
5223         status = dcerpc_secondary_connection(p, &p2, b);
5224         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5225
5226         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5227         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5228
5229         cp.in.handle = handle;
5230         cp.out.handle = handle;
5231
5232         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5233         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5234                         "ERROR: Allowed close on secondary connection");
5235
5236         talloc_free(p2);
5237
5238         return true;
5239 }
5240
5241 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5242                                      struct dcerpc_binding_handle *b, const char *name)
5243 {
5244         NTSTATUS status;
5245         struct spoolss_OpenPrinter op;
5246         struct spoolss_OpenPrinterEx opEx;
5247         struct policy_handle handle;
5248         bool ret = true;
5249
5250         op.in.printername       = name;
5251         op.in.datatype          = NULL;
5252         op.in.devmode_ctr.devmode= NULL;
5253         op.in.access_mask       = 0;
5254         op.out.handle           = &handle;
5255
5256         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5257
5258         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5259         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5260         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5261                 "unexpected result");
5262
5263         if (W_ERROR_IS_OK(op.out.result)) {
5264                 ret &=test_ClosePrinter(tctx, b, &handle);
5265         }
5266
5267         opEx.in.printername             = name;
5268         opEx.in.datatype                = NULL;
5269         opEx.in.devmode_ctr.devmode     = NULL;
5270         opEx.in.access_mask             = 0;
5271         opEx.in.level                   = 1;
5272         opEx.in.userlevel.level1        = NULL;
5273         opEx.out.handle                 = &handle;
5274
5275         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5276
5277         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5278         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5279         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5280                 "unexpected result");
5281
5282         if (W_ERROR_IS_OK(opEx.out.result)) {
5283                 ret &=test_ClosePrinter(tctx, b, &handle);
5284         }
5285
5286         return ret;
5287 }
5288
5289 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5290                                           struct dcerpc_binding_handle *b,
5291                                           const char *server_name)
5292 {
5293         const char *badnames[] = {
5294                 "__INVALID_PRINTER__",
5295                 "\\\\__INVALID_HOST__",
5296                 "",
5297                 "\\\\\\",
5298                 "\\\\\\__INVALID_PRINTER__"
5299         };
5300         const char *badname;
5301         int i;
5302
5303         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5304                 torture_assert(tctx,
5305                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5306                         "");
5307         }
5308
5309         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5310         torture_assert(tctx,
5311                 test_OpenPrinter_badname(tctx, b, badname),
5312                 "");
5313
5314         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5315         torture_assert(tctx,
5316                 test_OpenPrinter_badname(tctx, b, badname),
5317                 "");
5318
5319         return true;
5320 }
5321
5322 static bool test_OpenPrinter(struct torture_context *tctx,
5323                              struct dcerpc_pipe *p,
5324                              const char *name,
5325                              const char *environment)
5326 {
5327         NTSTATUS status;
5328         struct spoolss_OpenPrinter r;
5329         struct policy_handle handle;
5330         bool ret = true;
5331         struct dcerpc_binding_handle *b = p->binding_handle;
5332
5333         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5334         r.in.datatype           = NULL;
5335         r.in.devmode_ctr.devmode= NULL;
5336         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5337         r.out.handle            = &handle;
5338
5339         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5340
5341         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5342
5343         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5344
5345         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5346
5347         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5348                 ret = false;
5349         }
5350
5351         if (!torture_setting_bool(tctx, "samba3", false)) {
5352                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5353                         ret = false;
5354                 }
5355         }
5356
5357         if (!test_ClosePrinter(tctx, b, &handle)) {
5358                 ret = false;
5359         }
5360
5361         return ret;
5362 }
5363
5364 static bool call_OpenPrinterEx(struct torture_context *tctx,
5365                                struct dcerpc_pipe *p,
5366                                const char *name,
5367                                struct spoolss_DeviceMode *devmode,
5368                                struct policy_handle *handle)
5369 {
5370         struct spoolss_OpenPrinterEx r;
5371         struct spoolss_UserLevel1 userlevel1;
5372         NTSTATUS status;
5373         struct dcerpc_binding_handle *b = p->binding_handle;
5374
5375         if (name && name[0]) {
5376                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5377                                                    dcerpc_server_name(p), name);
5378         } else {
5379                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5380                                                    dcerpc_server_name(p));
5381         }
5382
5383         r.in.datatype           = NULL;
5384         r.in.devmode_ctr.devmode= devmode;
5385         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5386         r.in.level              = 1;
5387         r.in.userlevel.level1   = &userlevel1;
5388         r.out.handle = handle;
5389
5390         userlevel1.size = 1234;
5391         userlevel1.client = "hello";
5392         userlevel1.user = "spottyfoot!";
5393         userlevel1.build = 1;
5394         userlevel1.major = 2;
5395         userlevel1.minor = 3;
5396         userlevel1.processor = 4;
5397
5398         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5399
5400         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5401
5402         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5403
5404         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5405
5406         return true;
5407 }
5408
5409 static bool test_printer_rename(struct torture_context *tctx,
5410                                 struct dcerpc_pipe *p,
5411                                 struct policy_handle *handle,
5412                                 const char *name)
5413 {
5414         bool ret = true;
5415         union spoolss_PrinterInfo info;
5416         union spoolss_SetPrinterInfo sinfo;
5417         struct spoolss_SetPrinterInfoCtr info_ctr;
5418         struct spoolss_DevmodeContainer devmode_ctr;
5419         struct sec_desc_buf secdesc_ctr;
5420         const char *printer_name;
5421         const char *printer_name_orig;
5422         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5423         struct policy_handle new_handle;
5424         const char *q;
5425         struct dcerpc_binding_handle *b = p->binding_handle;
5426
5427         ZERO_STRUCT(devmode_ctr);
5428         ZERO_STRUCT(secdesc_ctr);
5429
5430         torture_comment(tctx, "Testing Printer rename operations\n");
5431
5432         torture_assert(tctx,
5433                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5434                 "failed to call GetPrinter level 2");
5435
5436         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5437
5438         q = strrchr(info.info2.printername, '\\');
5439         if (q) {
5440                 torture_warning(tctx,
5441                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5442         }
5443
5444         torture_assert(tctx,
5445                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5446
5447         sinfo.info2->printername = printer_name_new;
5448
5449         info_ctr.level = 2;
5450         info_ctr.info = sinfo;
5451
5452         torture_assert(tctx,
5453                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5454                 "failed to call SetPrinter level 2");
5455
5456         torture_assert(tctx,
5457                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5458                 "failed to call GetPrinter level 2");
5459
5460         printer_name = talloc_strdup(tctx, info.info2.printername);
5461
5462         q = strrchr(info.info2.printername, '\\');
5463         if (q) {
5464                 torture_warning(tctx,
5465                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5466                 q++;
5467                 printer_name = q;
5468         }
5469
5470         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5471                 "new printer name was not set");
5472
5473         /* samba currently cannot fully rename printers */
5474         if (!torture_setting_bool(tctx, "samba3", false)) {
5475                 torture_assert(tctx,
5476                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5477                         "still can open printer with oldname after rename");
5478         } else {
5479                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5480         }
5481
5482         torture_assert(tctx,
5483                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5484                 "failed to open printer with new name");
5485
5486         torture_assert(tctx,
5487                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5488                 "failed to call GetPrinter level 2");
5489
5490         /* FIXME: we openend with servername! */
5491         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5492                 dcerpc_server_name(p), printer_name_new);
5493
5494         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5495                 "new printer name was not set");
5496
5497         torture_assert(tctx,
5498                 test_ClosePrinter(tctx, b, &new_handle),
5499                 "failed to close printer");
5500
5501         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5502
5503         return ret;
5504 }
5505
5506
5507 static bool test_OpenPrinterEx(struct torture_context *tctx,
5508                                struct dcerpc_pipe *p,
5509                                const char *name,
5510                                const char *environment)
5511 {
5512         struct policy_handle handle;
5513         bool ret = true;
5514         struct dcerpc_binding_handle *b = p->binding_handle;
5515
5516         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5517                 return false;
5518         }
5519
5520         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5521                 ret = false;
5522         }
5523
5524         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5525                 ret = false;
5526         }
5527
5528         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5529                 ret = false;
5530         }
5531
5532         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5533                 ret = false;
5534         }
5535
5536         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5537                 ret = false;
5538         }
5539
5540         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5541                 ret = false;
5542         }
5543
5544         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5545                 ret = false;
5546         }
5547
5548         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5549                 ret = false;
5550         }
5551
5552         if (!test_printer_keys(tctx, b, &handle)) {
5553                 ret = false;
5554         }
5555
5556         if (!test_PausePrinter(tctx, b, &handle)) {
5557                 ret = false;
5558         }
5559
5560         if (!test_DoPrintTest(tctx, b, &handle)) {
5561                 ret = false;
5562         }
5563
5564         if (!test_ResumePrinter(tctx, b, &handle)) {
5565                 ret = false;
5566         }
5567
5568         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5569                 ret = false;
5570         }
5571
5572         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5573                 ret = false;
5574         }
5575
5576         if (!torture_setting_bool(tctx, "samba3", false)) {
5577                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5578                         ret = false;
5579                 }
5580         }
5581
5582         if (!test_ClosePrinter(tctx, b, &handle)) {
5583                 ret = false;
5584         }
5585
5586         return ret;
5587 }
5588
5589 static bool test_EnumPrinters_old(struct torture_context *tctx,
5590                                   struct dcerpc_pipe *p,
5591                                   const char *environment)
5592 {
5593         struct spoolss_EnumPrinters r;
5594         NTSTATUS status;
5595         uint16_t levels[] = {1, 2, 4, 5};
5596         int i;
5597         bool ret = true;
5598         struct dcerpc_binding_handle *b = p->binding_handle;
5599
5600         for (i=0;i<ARRAY_SIZE(levels);i++) {
5601                 union spoolss_PrinterInfo *info;
5602                 int j;
5603                 uint32_t needed;
5604                 uint32_t count;
5605
5606                 r.in.flags      = PRINTER_ENUM_LOCAL;
5607                 r.in.server     = "";
5608                 r.in.level      = levels[i];
5609                 r.in.buffer     = NULL;
5610                 r.in.offered    = 0;
5611                 r.out.needed    = &needed;
5612                 r.out.count     = &count;
5613                 r.out.info      = &info;
5614
5615                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5616
5617                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5618                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5619
5620                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5621                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5622                         r.in.buffer = &blob;
5623                         r.in.offered = needed;
5624                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5625                 }
5626
5627                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5628
5629                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5630
5631                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5632
5633                 if (!info) {
5634                         torture_comment(tctx, "No printers returned\n");
5635                         return true;
5636                 }
5637
5638                 for (j=0;j<count;j++) {
5639                         if (r.in.level == 1) {
5640                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5641                                 char *slash, *name;
5642                                 name = unc;
5643                                 if (unc[0] == '\\' && unc[1] == '\\') {
5644                                         unc +=2;
5645                                 }
5646                                 slash = strchr(unc, '\\');
5647                                 if (slash) {
5648                                         slash++;
5649                                         name = slash;
5650                                 }
5651                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
5652                                         ret = false;
5653                                 }
5654                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
5655                                         ret = false;
5656                                 }
5657                         }
5658                 }
5659         }
5660
5661         return ret;
5662 }
5663
5664 static bool test_GetPrinterDriver(struct torture_context *tctx,
5665                                   struct dcerpc_binding_handle *b,
5666                                   struct policy_handle *handle,
5667                                   const char *driver_name)
5668 {
5669         struct spoolss_GetPrinterDriver r;
5670         uint32_t needed;
5671
5672         r.in.handle = handle;
5673         r.in.architecture = "W32X86";
5674         r.in.level = 1;
5675         r.in.buffer = NULL;
5676         r.in.offered = 0;
5677         r.out.needed = &needed;
5678
5679         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5680
5681         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5682                 "failed to call GetPrinterDriver");
5683         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5684                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5685                 r.in.buffer = &blob;
5686                 r.in.offered = needed;
5687                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5688                         "failed to call GetPrinterDriver");
5689         }
5690
5691         torture_assert_werr_ok(tctx, r.out.result,
5692                 "failed to call GetPrinterDriver");
5693
5694         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5695
5696         return true;
5697 }
5698
5699 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5700                                          struct dcerpc_binding_handle *b,
5701                                          struct policy_handle *handle,
5702                                          const char *driver_name,
5703                                          const char *architecture,
5704                                          uint32_t level,
5705                                          uint32_t client_major_version,
5706                                          uint32_t client_minor_version,
5707                                          union spoolss_DriverInfo *info_p,
5708                                          WERROR *result_p)
5709
5710 {
5711         struct spoolss_GetPrinterDriver2 r;
5712         uint32_t needed;
5713         uint32_t server_major_version;
5714         uint32_t server_minor_version;
5715
5716         r.in.handle = handle;
5717         r.in.architecture = architecture;
5718         r.in.client_major_version = client_major_version;
5719         r.in.client_minor_version = client_minor_version;
5720         r.in.buffer = NULL;
5721         r.in.offered = 0;
5722         r.in.level = level;
5723         r.out.needed = &needed;
5724         r.out.server_major_version = &server_major_version;
5725         r.out.server_minor_version = &server_minor_version;
5726
5727         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5728                 driver_name, r.in.level);
5729
5730         torture_assert_ntstatus_ok(tctx,
5731                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5732                 "failed to call GetPrinterDriver2");
5733         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5734                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5735                 r.in.buffer = &blob;
5736                 r.in.offered = needed;
5737                 torture_assert_ntstatus_ok(tctx,
5738                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5739                         "failed to call GetPrinterDriver2");
5740         }
5741
5742         if (result_p) {
5743                 *result_p = r.out.result;
5744         }
5745
5746         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5747                 switch (r.in.level) {
5748                 case 101:
5749                 case 8:
5750                         torture_comment(tctx,
5751                                 "level %d not implemented, not considering as an error\n",
5752                                 r.in.level);
5753                         return true;
5754                 default:
5755                         break;
5756                 }
5757         }
5758
5759         torture_assert_werr_ok(tctx, r.out.result,
5760                 "failed to call GetPrinterDriver2");
5761
5762         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5763
5764         if (info_p) {
5765                 *info_p = *r.out.info;
5766         }
5767
5768         return true;
5769 }
5770
5771 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5772                                    struct dcerpc_binding_handle *b,
5773                                    struct policy_handle *handle,
5774                                    const char *driver_name,
5775                                    const char *architecture)
5776 {
5777         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5778         int i;
5779
5780
5781         for (i=0;i<ARRAY_SIZE(levels);i++) {
5782
5783                 torture_assert(tctx,
5784                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
5785                         "");
5786         }
5787
5788         return true;
5789 }
5790
5791 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
5792                                         struct dcerpc_pipe *p,
5793                                         const char *environment)
5794 {
5795         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
5796         int i;
5797         struct dcerpc_binding_handle *b = p->binding_handle;
5798         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5799
5800         for (i=0;i<ARRAY_SIZE(levels);i++) {
5801
5802                 uint32_t count;
5803                 union spoolss_DriverInfo *info;
5804
5805                 torture_assert(tctx,
5806                         test_EnumPrinterDrivers_args(tctx, b, server_name, environment, levels[i], &count, &info),
5807                         "failed to enumerate drivers");
5808
5809                 if (!info) {
5810                         torture_comment(tctx, "No printer drivers returned\n");
5811                         break;
5812                 }
5813         }
5814
5815         return true;
5816 }
5817
5818 static bool test_DeletePrinter(struct torture_context *tctx,
5819                                struct dcerpc_binding_handle *b,
5820                                struct policy_handle *handle)
5821 {
5822         struct spoolss_DeletePrinter r;
5823
5824         torture_comment(tctx, "Testing DeletePrinter\n");
5825
5826         r.in.handle = handle;
5827
5828         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
5829                 "failed to delete printer");
5830         torture_assert_werr_ok(tctx, r.out.result,
5831                 "failed to delete printer");
5832
5833         return true;
5834 }
5835
5836 static bool test_EnumPrinters_findname(struct torture_context *tctx,
5837                                        struct dcerpc_binding_handle *b,
5838                                        uint32_t flags,
5839                                        uint32_t level,
5840                                        const char *name,
5841                                        bool *found)
5842 {
5843         struct spoolss_EnumPrinters e;
5844         uint32_t count;
5845         union spoolss_PrinterInfo *info;
5846         uint32_t needed;
5847         int i;
5848
5849         *found = false;
5850
5851         e.in.flags = flags;
5852         e.in.server = NULL;
5853         e.in.level = level;
5854         e.in.buffer = NULL;
5855         e.in.offered = 0;
5856         e.out.count = &count;
5857         e.out.info = &info;
5858         e.out.needed = &needed;
5859
5860         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5861                 "failed to enum printers");
5862
5863         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
5864                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5865                 e.in.buffer = &blob;
5866                 e.in.offered = needed;
5867
5868                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5869                         "failed to enum printers");
5870         }
5871
5872         torture_assert_werr_ok(tctx, e.out.result,
5873                 "failed to enum printers");
5874
5875         for (i=0; i < count; i++) {
5876
5877                 const char *current = NULL;
5878                 const char *q;
5879
5880                 switch (level) {
5881                 case 1:
5882                         current = info[i].info1.name;
5883                         break;
5884                 }
5885
5886                 if (strequal(current, name)) {
5887                         *found = true;
5888                         break;
5889                 }
5890
5891                 q = strrchr(current, '\\');
5892                 if (q) {
5893                         if (!e.in.server) {
5894                                 torture_warning(tctx,
5895                                         "server returns printername %s incl. servername although we did not set servername", current);
5896                         }
5897                         q++;
5898                         if (strequal(q, name)) {
5899                                 *found = true;
5900                                 break;
5901                         }
5902                 }
5903         }
5904
5905         return true;
5906 }
5907
5908 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5909                                       struct dcerpc_pipe *p,
5910                                       const char *printername,
5911                                       bool ex)
5912 {
5913         WERROR result;
5914         struct spoolss_AddPrinter r;
5915         struct spoolss_AddPrinterEx rex;
5916         struct spoolss_SetPrinterInfoCtr info_ctr;
5917         struct spoolss_SetPrinterInfo1 info1;
5918         struct spoolss_DevmodeContainer devmode_ctr;
5919         struct sec_desc_buf secdesc_ctr;
5920         struct spoolss_UserLevelCtr userlevel_ctr;
5921         struct policy_handle handle;
5922         bool found = false;
5923         struct dcerpc_binding_handle *b = p->binding_handle;
5924
5925         ZERO_STRUCT(devmode_ctr);
5926         ZERO_STRUCT(secdesc_ctr);
5927         ZERO_STRUCT(userlevel_ctr);
5928         ZERO_STRUCT(info1);
5929
5930         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5931
5932         /* try to add printer to wellknown printer list (level 1) */
5933
5934         userlevel_ctr.level = 1;
5935
5936         info_ctr.info.info1 = &info1;
5937         info_ctr.level = 1;
5938
5939         rex.in.server = NULL;
5940         rex.in.info_ctr = &info_ctr;
5941         rex.in.devmode_ctr = &devmode_ctr;
5942         rex.in.secdesc_ctr = &secdesc_ctr;
5943         rex.in.userlevel_ctr = &userlevel_ctr;
5944         rex.out.handle = &handle;
5945
5946         r.in.server = NULL;
5947         r.in.info_ctr = &info_ctr;
5948         r.in.devmode_ctr = &devmode_ctr;
5949         r.in.secdesc_ctr = &secdesc_ctr;
5950         r.out.handle = &handle;
5951
5952         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5953                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5954                 "failed to add printer");
5955         result = ex ? rex.out.result : r.out.result;
5956         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5957                 "unexpected result code");
5958
5959         info1.name = printername;
5960         info1.flags = PRINTER_ATTRIBUTE_SHARED;
5961
5962         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5963                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5964                 "failed to add printer");
5965         result = ex ? rex.out.result : r.out.result;
5966         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5967                 "unexpected result code");
5968
5969         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5970            better do a real check to see the printer is really there */
5971
5972         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5973                                                         PRINTER_ENUM_NETWORK, 1,
5974                                                         printername,
5975                                                         &found),
5976                         "failed to enum printers");
5977
5978         torture_assert(tctx, found, "failed to find newly added printer");
5979
5980         info1.flags = 0;
5981
5982         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5983                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5984                 "failed to add printer");
5985         result = ex ? rex.out.result : r.out.result;
5986         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5987                 "unexpected result code");
5988
5989         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5990            better do a real check to see the printer has really been removed
5991            from the well known printer list */
5992
5993         found = false;
5994
5995         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5996                                                         PRINTER_ENUM_NETWORK, 1,
5997                                                         printername,
5998                                                         &found),
5999                         "failed to enum printers");
6000 #if 0
6001         torture_assert(tctx, !found, "printer still in well known printer list");
6002 #endif
6003         return true;
6004 }
6005
6006 static bool test_AddPrinter_normal(struct torture_context *tctx,
6007                                    struct dcerpc_pipe *p,
6008                                    struct policy_handle *handle_p,
6009                                    const char *printername,
6010                                    const char *drivername,
6011                                    const char *portname,
6012                                    bool ex)
6013 {
6014         WERROR result;
6015         struct spoolss_AddPrinter r;
6016         struct spoolss_AddPrinterEx rex;
6017         struct spoolss_SetPrinterInfoCtr info_ctr;
6018         struct spoolss_SetPrinterInfo2 info2;
6019         struct spoolss_DevmodeContainer devmode_ctr;
6020         struct sec_desc_buf secdesc_ctr;
6021         struct spoolss_UserLevelCtr userlevel_ctr;
6022         struct policy_handle handle;
6023         bool found = false;
6024         bool existing_printer_deleted = false;
6025         struct dcerpc_binding_handle *b = p->binding_handle;
6026
6027         ZERO_STRUCT(devmode_ctr);
6028         ZERO_STRUCT(secdesc_ctr);
6029         ZERO_STRUCT(userlevel_ctr);
6030
6031         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
6032
6033         userlevel_ctr.level = 1;
6034
6035         rex.in.server = NULL;
6036         rex.in.info_ctr = &info_ctr;
6037         rex.in.devmode_ctr = &devmode_ctr;
6038         rex.in.secdesc_ctr = &secdesc_ctr;
6039         rex.in.userlevel_ctr = &userlevel_ctr;
6040         rex.out.handle = &handle;
6041
6042         r.in.server = NULL;
6043         r.in.info_ctr = &info_ctr;
6044         r.in.devmode_ctr = &devmode_ctr;
6045         r.in.secdesc_ctr = &secdesc_ctr;
6046         r.out.handle = &handle;
6047
6048  again:
6049
6050         /* try to add printer to printer list (level 2) */
6051
6052         ZERO_STRUCT(info2);
6053
6054         info_ctr.info.info2 = &info2;
6055         info_ctr.level = 2;
6056
6057         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6058                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6059                 "failed to add printer");
6060         result = ex ? rex.out.result : r.out.result;
6061         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6062                 "unexpected result code");
6063
6064         info2.printername = printername;
6065
6066         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6067                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6068                 "failed to add printer");
6069         result = ex ? rex.out.result : r.out.result;
6070
6071         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6072                 struct policy_handle printer_handle;
6073
6074                 if (existing_printer_deleted) {
6075                         torture_fail(tctx, "already deleted printer still existing?");
6076                 }
6077
6078                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6079                         "failed to open printer handle");
6080
6081                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6082                         "failed to delete printer");
6083
6084                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6085                         "failed to close server handle");
6086
6087                 existing_printer_deleted = true;
6088
6089                 goto again;
6090         }
6091
6092         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6093                 "unexpected result code");
6094
6095         info2.portname = portname;
6096
6097         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6098                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6099                 "failed to add printer");
6100         result = ex ? rex.out.result : r.out.result;
6101         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6102                 "unexpected result code");
6103
6104         info2.drivername = drivername;
6105
6106         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6107                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6108                 "failed to add printer");
6109         result = ex ? rex.out.result : r.out.result;
6110
6111         /* w2k8r2 allows to add printer w/o defining printprocessor */
6112
6113         if (!W_ERROR_IS_OK(result)) {
6114                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6115                         "unexpected result code");
6116
6117                 info2.printprocessor = "winprint";
6118
6119                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6120                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6121                         "failed to add printer");
6122                 result = ex ? rex.out.result : r.out.result;
6123                 torture_assert_werr_ok(tctx, result,
6124                         "failed to add printer");
6125         }
6126
6127         *handle_p = handle;
6128
6129         /* we are paranoid, really check if the printer is there now */
6130
6131         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6132                                                         PRINTER_ENUM_LOCAL, 1,
6133                                                         printername,
6134                                                         &found),
6135                         "failed to enum printers");
6136         torture_assert(tctx, found, "failed to find newly added printer");
6137
6138         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6139                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6140                 "failed to add printer");
6141         result = ex ? rex.out.result : r.out.result;
6142         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6143                 "unexpected result code");
6144
6145         return true;
6146 }
6147
6148 static bool test_printer_info(struct torture_context *tctx,
6149                               struct dcerpc_binding_handle *b,
6150                               struct policy_handle *handle)
6151 {
6152         bool ret = true;
6153
6154         if (torture_setting_bool(tctx, "samba3", false)) {
6155                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6156         }
6157
6158         if (!test_PrinterInfo(tctx, b, handle)) {
6159                 ret = false;
6160         }
6161
6162         if (!test_SetPrinter_errors(tctx, b, handle)) {
6163                 ret = false;
6164         }
6165
6166         return ret;
6167 }
6168
6169 static bool test_EnumPrinterKey(struct torture_context *tctx,
6170                                 struct dcerpc_binding_handle *b,
6171                                 struct policy_handle *handle,
6172                                 const char *key_name,
6173                                 const char ***array)
6174 {
6175         struct spoolss_EnumPrinterKey r;
6176         uint32_t needed = 0;
6177         union spoolss_KeyNames key_buffer;
6178         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6179         uint32_t _ndr_size;
6180         int i;
6181
6182         r.in.handle = handle;
6183         r.in.key_name = key_name;
6184         r.out.key_buffer = &key_buffer;
6185         r.out.needed = &needed;
6186         r.out._ndr_size = &_ndr_size;
6187
6188         for (i=0; i < ARRAY_SIZE(offered); i++) {
6189
6190                 if (offered[i] < 0 && needed) {
6191                         if (needed <= 4) {
6192                                 continue;
6193                         }
6194                         r.in.offered = needed + offered[i];
6195                 } else {
6196                         r.in.offered = offered[i];
6197                 }
6198
6199                 ZERO_STRUCT(key_buffer);
6200
6201                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6202
6203                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6204                         "failed to call EnumPrinterKey");
6205                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6206
6207                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6208                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6209                                         _ndr_size, r.in.offered/2));
6210
6211                         r.in.offered = needed;
6212                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6213                                 "failed to call EnumPrinterKey");
6214                 }
6215
6216                 if (offered[i] > 0) {
6217                         torture_assert_werr_ok(tctx, r.out.result,
6218                                 "failed to call EnumPrinterKey");
6219                 }
6220
6221                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6222                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6223                                 _ndr_size, r.in.offered/2));
6224
6225                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6226                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6227
6228                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6229                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6230
6231                 if (key_buffer.string_array) {
6232                         uint32_t calc_needed = 0;
6233                         int s;
6234                         for (s=0; key_buffer.string_array[s]; s++) {
6235                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6236                         }
6237                         if (!key_buffer.string_array[0]) {
6238                                 calc_needed += 2;
6239                         }
6240                         calc_needed += 2;
6241
6242                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6243                                 "EnumPrinterKey unexpected size");
6244                 }
6245         }
6246
6247         if (array) {
6248                 *array = key_buffer.string_array;
6249         }
6250
6251         return true;
6252 }
6253
6254 bool test_printer_keys(struct torture_context *tctx,
6255                        struct dcerpc_binding_handle *b,
6256                        struct policy_handle *handle)
6257 {
6258         const char **key_array = NULL;
6259         int i;
6260
6261         torture_comment(tctx, "Testing Printer Keys\n");
6262
6263         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6264                 "failed to call test_EnumPrinterKey");
6265
6266         for (i=0; key_array && key_array[i]; i++) {
6267                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6268                         "failed to call test_EnumPrinterKey");
6269         }
6270         for (i=0; key_array && key_array[i]; i++) {
6271                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6272                         "failed to call test_EnumPrinterDataEx");
6273         }
6274
6275         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6276
6277         return true;
6278 }
6279
6280 static bool test_one_printer(struct torture_context *tctx,
6281                              struct dcerpc_pipe *p,
6282                              struct policy_handle *handle,
6283                              const char *name,
6284                              const char *drivername,
6285                              const char *environment,
6286                              bool have_driver)
6287 {
6288         bool ret = true;
6289         struct dcerpc_binding_handle *b = p->binding_handle;
6290
6291         if (!test_PausePrinter(tctx, b, handle)) {
6292                 ret = false;
6293         }
6294
6295         if (!test_DoPrintTest(tctx, b, handle)) {
6296                 ret = false;
6297         }
6298
6299         if (!test_ResumePrinter(tctx, b, handle)) {
6300                 ret = false;
6301         }
6302
6303         if (!test_printer_info(tctx, b, handle)) {
6304                 ret = false;
6305         }
6306
6307         if (!test_PrinterInfo_SD(tctx, b, handle)) {
6308                 ret = false;
6309         }
6310
6311         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
6312                 ret = false;
6313         }
6314
6315         if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
6316                 ret = false;
6317         }
6318
6319         if (!test_ChangeID(tctx, p, handle)) {
6320                 ret = false;
6321         }
6322
6323         if (!test_printer_keys(tctx, b, handle)) {
6324                 ret = false;
6325         }
6326
6327         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
6328                 ret = false;
6329         }
6330
6331         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
6332                 ret = false;
6333         }
6334
6335         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
6336                 ret = false;
6337         }
6338
6339         if (!test_PrinterData_DsSpooler(tctx, p, handle, name)) {
6340                 ret = false;
6341         }
6342
6343         if (have_driver) {
6344                 if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
6345                         ret = false;
6346                 }
6347         }
6348
6349         if (!test_printer_rename(tctx, p, handle, name)) {
6350                 ret = false;
6351         }
6352
6353         return ret;
6354 }
6355
6356 static bool test_csetprinter(struct torture_context *tctx,
6357                              struct dcerpc_pipe *p,
6358                              struct policy_handle *handle,
6359                              const char *printername,
6360                              const char *drivername,
6361                              const char *portname)
6362 {
6363         union spoolss_PrinterInfo info;
6364         struct policy_handle new_handle, new_handle2;
6365         struct dcerpc_binding_handle *b = p->binding_handle;
6366
6367         torture_comment(tctx, "Testing c_setprinter\n");
6368
6369         torture_assert(tctx,
6370                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6371                 "failed to get level 0 printer info");
6372         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6373                 info.info0.c_setprinter);
6374
6375         /* check if c_setprinter on 1st handle increases after a printer has
6376          * been added */
6377
6378         torture_assert(tctx,
6379                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, false),
6380                 "failed to add new printer");
6381         torture_assert(tctx,
6382                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6383                 "failed to get level 0 printer info");
6384         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6385                 info.info0.c_setprinter);
6386
6387         /* check if c_setprinter on new handle increases after a printer has
6388          * been added */
6389
6390         torture_assert(tctx,
6391                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6392                 "failed to get level 0 printer info");
6393         torture_comment(tctx, "csetprinter on created handle: %d\n",
6394                 info.info0.c_setprinter);
6395
6396         /* open the new printer and check if c_setprinter increases */
6397
6398         torture_assert(tctx,
6399                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6400                 "failed to open created printer");
6401         torture_assert(tctx,
6402                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6403                 "failed to get level 0 printer info");
6404         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6405                 info.info0.c_setprinter);
6406
6407         /* cleanup */
6408
6409         torture_assert(tctx,
6410                 test_ClosePrinter(tctx, b, &new_handle2),
6411                 "failed to close printer");
6412         torture_assert(tctx,
6413                 test_DeletePrinter(tctx, b, &new_handle),
6414                 "failed to delete new printer");
6415
6416         return true;
6417 }
6418
6419 static bool test_add_printer_args_with_driver(struct torture_context *tctx,
6420                                               struct dcerpc_pipe *p,
6421                                               struct torture_printer_context *t)
6422 {
6423         bool ret = true;
6424         struct policy_handle handle;
6425         bool found = false;
6426         struct dcerpc_binding_handle *b = p->binding_handle;
6427         const char *printer_name = t->info2.printername;
6428         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6429         const char *port_name = t->info2.portname;
6430         const char *printer_name2 = talloc_asprintf(tctx, "%s2", printer_name);
6431
6432         if (t->wellknown) {
6433                 torture_assert(tctx,
6434                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6435                         "failed to add wellknown printer");
6436         } else {
6437                 torture_assert(tctx,
6438                         test_AddPrinter_normal(tctx, p, &handle, printer_name, driver_name, port_name, t->ex),
6439                         "failed to add printer");
6440         }
6441
6442         if (!test_csetprinter(tctx, p, &handle, printer_name2, driver_name, port_name)) {
6443                 ret = false;
6444         }
6445
6446         if (!test_one_printer(tctx, p, &handle, printer_name, driver_name, t->driver.remote.environment, t->have_driver)) {
6447                 ret = false;
6448         }
6449
6450         if (!test_DeletePrinter(tctx, b, &handle)) {
6451                 ret = false;
6452         }
6453
6454         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6455                                         printer_name, &found)) {
6456                 ret = false;
6457         }
6458
6459         torture_assert(tctx, !found, "deleted printer still there");
6460
6461         return ret;
6462 }
6463
6464 static bool compose_local_driver_directory(struct torture_context *tctx,
6465                                            const char *environment,
6466                                            const char *local_dir,
6467                                            const char **path)
6468 {
6469         char *p;
6470
6471         p = strrchr(local_dir, '/');
6472         if (!p) {
6473                 return NULL;
6474         }
6475         p++;
6476
6477         if (strequal(environment, "Windows x64")) {
6478                 if (!strequal(p, "x64")) {
6479                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6480                 }
6481         } else if (strequal(environment, "Windows NT x86")) {
6482                 if (!strequal(p, "i386")) {
6483                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6484                 }
6485         } else {
6486                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6487         }
6488
6489         return true;
6490 }
6491
6492 static bool test_add_printer_args(struct torture_context *tctx,
6493                                   struct dcerpc_pipe *p,
6494                                   struct torture_printer_context *t)
6495 {
6496         bool ret = true;
6497         struct dcerpc_binding_handle *b = p->binding_handle;
6498         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6499
6500         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6501                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6502         }
6503
6504         torture_assert(tctx,
6505                 fillup_printserver_info(tctx, p, &t->driver),
6506                 "failed to fillup printserver info");
6507
6508         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6509
6510         torture_assert(tctx,
6511                 compose_local_driver_directory(tctx, t->driver.remote.environment,
6512                                                t->driver.local.driver_directory,
6513                                                &t->driver.local.driver_directory),
6514                 "failed to compose local driver directory");
6515
6516         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6517                 t->have_driver = true;
6518                 goto try_run;
6519         }
6520
6521         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6522                 t->info2.drivername, t->driver.remote.environment);
6523         torture_comment(tctx, "trying to upload own driver\n");
6524
6525         if (!directory_exist(t->driver.local.driver_directory)) {
6526                 torture_warning(tctx, "no local driver is available!");
6527                 t->have_driver = false;
6528                 goto try_run;
6529         }
6530
6531         torture_assert(tctx,
6532                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6533                 "failed to upload printer driver");
6534
6535         torture_assert(tctx,
6536                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6537                 "failed to add driver");
6538
6539         t->added_driver = true;
6540         t->have_driver = true;
6541
6542  try_run:
6543         ret = test_add_printer_args_with_driver(tctx, p, t);
6544
6545         if (t->added_driver) {
6546                 torture_assert(tctx,
6547                         remove_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6548                         "failed to remove printer driver");
6549         }
6550
6551         return ret;
6552 }
6553
6554 static bool test_add_printer(struct torture_context *tctx,
6555                              struct dcerpc_pipe *p,
6556                              void *private_data)
6557 {
6558         struct torture_printer_context *t =
6559                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6560
6561         t->ex                   = false;
6562         t->wellknown            = false;
6563         t->info2.printername    = TORTURE_PRINTER;
6564
6565         return test_add_printer_args(tctx, p, t);
6566 }
6567
6568 static bool test_add_printer_wellknown(struct torture_context *tctx,
6569                                        struct dcerpc_pipe *p,
6570                                        void *private_data)
6571 {
6572         struct torture_printer_context *t =
6573                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6574
6575         t->ex                   = false;
6576         t->wellknown            = true;
6577         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
6578
6579         return test_add_printer_args(tctx, p, t);
6580 }
6581
6582 static bool test_add_printer_ex(struct torture_context *tctx,
6583                                 struct dcerpc_pipe *p,
6584                                 void *private_data)
6585 {
6586         struct torture_printer_context *t =
6587                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6588
6589         t->ex                   = true;
6590         t->wellknown            = false;
6591         t->info2.printername    = TORTURE_PRINTER_EX;
6592
6593         return test_add_printer_args(tctx, p, t);
6594 }
6595
6596 static bool test_add_printer_ex_wellknown(struct torture_context *tctx,
6597                                           struct dcerpc_pipe *p,
6598                                           void *private_data)
6599 {
6600         struct torture_printer_context *t =
6601                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6602
6603         t->ex                   = true;
6604         t->wellknown            = true;
6605         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
6606
6607         return test_add_printer_args(tctx, p, t);
6608 }
6609
6610 static bool test_architecture_buffer(struct torture_context *tctx,
6611                                      struct dcerpc_pipe *p)
6612 {
6613         struct spoolss_OpenPrinterEx r;
6614         struct spoolss_UserLevel1 u1;
6615         struct policy_handle handle;
6616         uint32_t architectures[] = {
6617                 PROCESSOR_ARCHITECTURE_INTEL,
6618                 PROCESSOR_ARCHITECTURE_IA64,
6619                 PROCESSOR_ARCHITECTURE_AMD64
6620         };
6621         uint32_t needed[3];
6622         int i;
6623         struct dcerpc_binding_handle *b = p->binding_handle;
6624
6625         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6626
6627                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6628
6629                 u1.size = 0;
6630                 u1.client = NULL;
6631                 u1.user = NULL;
6632                 u1.build = 0;
6633                 u1.major = 3;
6634                 u1.minor = 0;
6635                 u1.processor = architectures[i];
6636
6637                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6638                 r.in.datatype           = NULL;
6639                 r.in.devmode_ctr.devmode= NULL;
6640                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6641                 r.in.level               = 1;
6642                 r.in.userlevel.level1   = &u1;
6643                 r.out.handle            = &handle;
6644
6645                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6646                 torture_assert_werr_ok(tctx, r.out.result, "");
6647
6648                 {
6649                         struct spoolss_EnumPrinters e;
6650                         uint32_t count;
6651                         union spoolss_PrinterInfo *info;
6652
6653                         e.in.flags = PRINTER_ENUM_LOCAL;
6654                         e.in.server = NULL;
6655                         e.in.level = 2;
6656                         e.in.buffer = NULL;
6657                         e.in.offered = 0;
6658                         e.out.count = &count;
6659                         e.out.info = &info;
6660                         e.out.needed = &needed[i];
6661
6662                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6663 #if 0
6664                         torture_comment(tctx, "needed was %d\n", needed[i]);
6665 #endif
6666                 }
6667
6668                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6669         }
6670
6671         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6672                 if (needed[i-1] != needed[i]) {
6673                         torture_fail(tctx,
6674                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6675                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6676                 }
6677         }
6678
6679         return true;
6680 }
6681
6682 bool torture_rpc_spoolss(struct torture_context *torture)
6683 {
6684         NTSTATUS status;
6685         struct dcerpc_pipe *p;
6686         struct dcerpc_binding_handle *b;
6687         bool ret = true;
6688         struct test_spoolss_context *ctx;
6689         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
6690
6691         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
6692         if (!NT_STATUS_IS_OK(status)) {
6693                 return false;
6694         }
6695         b = p->binding_handle;
6696
6697         ctx = talloc_zero(torture, struct test_spoolss_context);
6698
6699         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
6700         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
6701         ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
6702         ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
6703         ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
6704         ret &= test_EnumPorts(torture, b, ctx);
6705         ret &= test_GetPrinterDriverDirectory(torture, p, environment);
6706         ret &= test_GetPrintProcessorDirectory(torture, p, environment);
6707         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
6708         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
6709         ret &= test_EnumMonitors(torture, b, ctx);
6710         ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
6711         ret &= test_EnumPrintProcDataTypes(torture, b);
6712         ret &= test_EnumPrinters(torture, b, ctx);
6713         ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
6714
6715         ret &= test_AddPort(torture, p);
6716         ret &= test_EnumPorts_old(torture, p);
6717         ret &= test_EnumPrinters_old(torture, p, environment);
6718         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
6719         ret &= test_architecture_buffer(torture, p);
6720
6721         return ret;
6722 }
6723
6724 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
6725 {
6726         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
6727
6728         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
6729                                                         "printer", &ndr_table_spoolss);
6730
6731         struct torture_printer_context *t;
6732
6733         t = talloc_zero(mem_ctx, struct torture_printer_context);
6734
6735         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
6736         t->driver.info8.driver_name             = TORTURE_DRIVER;
6737         t->driver.info8.driver_path             = "pscript5.dll";
6738         t->driver.info8.data_file               = "cups6.ppd";
6739         t->driver.info8.config_file             = "ps5ui.dll";
6740         t->driver.info8.help_file               = "pscript.hlp";
6741         t->driver.info8.default_datatype        = "RAW";
6742         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
6743         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6744         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6745         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6746         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6747         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6748         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6749         t->driver.info8.dependent_files->string[5] = "cups6.ini";
6750         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6751         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6752
6753         t->driver.local.driver_directory= "/usr/share/cups/drivers";
6754
6755         t->info2.drivername             = "Microsoft XPS Document Writer";
6756         t->info2.portname               = "LPT1:";
6757
6758         torture_rpc_tcase_add_test_ex(tcase, "add_printer", test_add_printer, t);
6759         torture_rpc_tcase_add_test_ex(tcase, "add_printer_wellknown", test_add_printer_wellknown, t);
6760         torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex", test_add_printer_ex, t);
6761         torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex_wellknown", test_add_printer_ex_wellknown, t);
6762
6763         return suite;
6764 }
6765
6766 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
6767                                                   struct dcerpc_binding_handle *b,
6768                                                   const char *server,
6769                                                   const char *environment,
6770                                                   const char **dir_p)
6771 {
6772         struct spoolss_GetPrinterDriverDirectory r;
6773         uint32_t needed;
6774
6775         r.in.server             = server;
6776         r.in.environment        = environment;
6777         r.in.level              = 1;
6778         r.in.buffer             = NULL;
6779         r.in.offered            = 0;
6780         r.out.needed            = &needed;
6781
6782         torture_assert_ntstatus_ok(tctx,
6783                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6784                 "failed to query driver directory");
6785
6786         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6787                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6788                 r.in.buffer = &blob;
6789                 r.in.offered = needed;
6790
6791                 torture_assert_ntstatus_ok(tctx,
6792                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6793                         "failed to query driver directory");
6794         }
6795
6796         torture_assert_werr_ok(tctx, r.out.result,
6797                 "failed to query driver directory");
6798
6799         if (dir_p) {
6800                 *dir_p = r.out.info->info1.directory_name;
6801         }
6802
6803         return true;
6804 }
6805
6806 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6807 {
6808         if (info_ctr == NULL) {
6809                 return NULL;
6810         }
6811
6812         switch (info_ctr->level) {
6813         case 1:
6814                 return info_ctr->info.info1->driver_name;
6815         case 2:
6816                 return info_ctr->info.info2->driver_name;
6817         case 3:
6818                 return info_ctr->info.info3->driver_name;
6819         case 4:
6820                 return info_ctr->info.info4->driver_name;
6821         case 6:
6822                 return info_ctr->info.info6->driver_name;
6823         case 8:
6824                 return info_ctr->info.info8->driver_name;
6825         default:
6826                 return NULL;
6827         }
6828 }
6829
6830 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6831 {
6832         if (info_ctr == NULL) {
6833                 return NULL;
6834         }
6835
6836         switch (info_ctr->level) {
6837         case 2:
6838                 return info_ctr->info.info2->architecture;
6839         case 3:
6840                 return info_ctr->info.info3->architecture;
6841         case 4:
6842                 return info_ctr->info.info4->architecture;
6843         case 6:
6844                 return info_ctr->info.info6->architecture;
6845         case 8:
6846                 return info_ctr->info.info8->architecture;
6847         default:
6848                 return NULL;
6849         }
6850 }
6851
6852
6853 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
6854                                       struct dcerpc_binding_handle *b,
6855                                       const char *servername,
6856                                       struct spoolss_AddDriverInfoCtr *info_ctr,
6857                                       WERROR expected_result)
6858 {
6859         struct spoolss_AddPrinterDriver r;
6860         const char *drivername = get_driver_from_info(info_ctr);
6861         const char *environment = get_environment_from_info(info_ctr);
6862
6863         r.in.servername = servername;
6864         r.in.info_ctr = info_ctr;
6865
6866         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
6867                 drivername, info_ctr->level, environment);
6868
6869         torture_assert_ntstatus_ok(tctx,
6870                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
6871                 "spoolss_AddPrinterDriver failed");
6872         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6873                 "spoolss_AddPrinterDriver failed with unexpected result");
6874
6875         return true;
6876
6877 }
6878
6879 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
6880                                         struct dcerpc_binding_handle *b,
6881                                         const char *servername,
6882                                         struct spoolss_AddDriverInfoCtr *info_ctr,
6883                                         uint32_t flags,
6884                                         WERROR expected_result)
6885 {
6886         struct spoolss_AddPrinterDriverEx r;
6887         const char *drivername = get_driver_from_info(info_ctr);
6888         const char *environment = get_environment_from_info(info_ctr);
6889
6890         r.in.servername = servername;
6891         r.in.info_ctr = info_ctr;
6892         r.in.flags = flags;
6893
6894         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
6895                 drivername, info_ctr->level, environment);
6896
6897         torture_assert_ntstatus_ok(tctx,
6898                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
6899                 "AddPrinterDriverEx failed");
6900         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6901                 "AddPrinterDriverEx failed with unexpected result");
6902
6903         return true;
6904 }
6905
6906 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
6907                                                struct dcerpc_binding_handle *b,
6908                                                const char *server_name,
6909                                                struct spoolss_AddDriverInfo8 *r,
6910                                                uint32_t flags,
6911                                                bool ex)
6912 {
6913         struct spoolss_AddDriverInfoCtr info_ctr;
6914         struct spoolss_AddDriverInfo1 info1;
6915
6916         ZERO_STRUCT(info1);
6917
6918         info_ctr.level = 1;
6919         info_ctr.info.info1 = &info1;
6920
6921         if (ex) {
6922                 torture_assert(tctx,
6923                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6924                         "failed to test AddPrinterDriverEx level 1");
6925         } else {
6926                 torture_assert(tctx,
6927                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6928                         "failed to test AddPrinterDriver level 1");
6929         }
6930
6931         info1.driver_name = r->driver_name;
6932
6933         if (ex) {
6934                 torture_assert(tctx,
6935                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6936                         "failed to test AddPrinterDriverEx level 1");
6937         } else {
6938                 torture_assert(tctx,
6939                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6940                         "failed to test AddPrinterDriver level 1");
6941         }
6942
6943         return true;
6944 }
6945
6946 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
6947                                                struct dcerpc_binding_handle *b,
6948                                                const char *server_name,
6949                                                struct spoolss_AddDriverInfo8 *r,
6950                                                uint32_t flags,
6951                                                bool ex)
6952 {
6953         struct spoolss_AddDriverInfoCtr info_ctr;
6954         struct spoolss_AddDriverInfo2 info2;
6955
6956         ZERO_STRUCT(info2);
6957
6958         info_ctr.level = 2;
6959         info_ctr.info.info2 = &info2;
6960
6961         if (ex) {
6962                 torture_assert(tctx,
6963                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6964                         "failed to test AddPrinterDriverEx level 2");
6965         } else {
6966                 torture_assert(tctx,
6967                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6968                         "failed to test AddPrinterDriver level 2");
6969         }
6970
6971         info2.driver_name = r->driver_name;
6972
6973         if (ex) {
6974                 torture_assert(tctx,
6975                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6976                         "failed to test AddPrinterDriverEx level 2");
6977         } else {
6978                 torture_assert(tctx,
6979                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6980                         "failed to test AddPrinterDriver level 2");
6981         }
6982
6983         info2.version = r->version;
6984
6985         if (ex) {
6986                 torture_assert(tctx,
6987                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6988                         "failed to test AddPrinterDriverEx level 2");
6989         } else {
6990                 torture_assert(tctx,
6991                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6992                         "failed to test AddPrinterDriver level 2");
6993         }
6994
6995         info2.architecture = r->architecture;
6996
6997         if (ex) {
6998                 torture_assert(tctx,
6999                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7000                         "failed to test AddPrinterDriverEx level 2");
7001         } else {
7002                 torture_assert(tctx,
7003                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7004                         "failed to test AddPrinterDriver level 2");
7005         }
7006
7007         info2.driver_path = r->driver_path;
7008
7009         if (ex) {
7010                 torture_assert(tctx,
7011                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7012                         "failed to test AddPrinterDriverEx level 2");
7013         } else {
7014                 torture_assert(tctx,
7015                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7016                         "failed to test AddPrinterDriver level 2");
7017         }
7018
7019         info2.data_file = r->data_file;
7020
7021         if (ex) {
7022                 torture_assert(tctx,
7023                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7024                         "failed to test AddPrinterDriverEx level 2");
7025         } else {
7026                 torture_assert(tctx,
7027                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7028                         "failed to test AddPrinterDriver level 2");
7029         }
7030
7031         info2.config_file = r->config_file;
7032
7033         if (ex) {
7034                 torture_assert(tctx,
7035                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7036                         "failed to test AddPrinterDriverEx");
7037         }
7038
7039         if (ex) {
7040                 torture_assert(tctx,
7041                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7042                         "failed to test AddPrinterDriverEx level 2");
7043         } else {
7044                 torture_assert(tctx,
7045                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7046                         "failed to test AddPrinterDriver level 2");
7047         }
7048
7049         torture_assert(tctx,
7050                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7051                 "failed to find added printer driver");
7052
7053         return true;
7054 }
7055
7056 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7057                                                struct dcerpc_binding_handle *b,
7058                                                const char *server_name,
7059                                                struct spoolss_AddDriverInfo8 *r,
7060                                                uint32_t flags,
7061                                                bool ex)
7062 {
7063         struct spoolss_AddDriverInfoCtr info_ctr;
7064         struct spoolss_AddDriverInfo3 info3;
7065
7066         info3.driver_name       = r->driver_name;
7067         info3.version           = r->version;
7068         info3.architecture      = r->architecture;
7069         info3.driver_path       = r->driver_path;
7070         info3.data_file         = r->data_file;
7071         info3.config_file       = r->config_file;
7072         info3.help_file         = r->help_file;
7073         info3.monitor_name      = r->monitor_name;
7074         info3.default_datatype  = r->default_datatype;
7075         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7076         info3.dependent_files   = r->dependent_files;
7077
7078         info_ctr.level = 3;
7079         info_ctr.info.info3 = &info3;
7080
7081         if (ex) {
7082                 torture_assert(tctx,
7083                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7084                         "failed to test AddPrinterDriverEx level 3");
7085         } else {
7086                 torture_assert(tctx,
7087                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7088                         "failed to test AddPrinterDriver level 3");
7089         }
7090
7091         torture_assert(tctx,
7092                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7093                 "failed to find added printer driver");
7094
7095         return true;
7096 }
7097
7098 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7099                                                struct dcerpc_binding_handle *b,
7100                                                const char *server_name,
7101                                                struct spoolss_AddDriverInfo8 *r,
7102                                                uint32_t flags,
7103                                                bool ex)
7104 {
7105         struct spoolss_AddDriverInfoCtr info_ctr;
7106         struct spoolss_AddDriverInfo4 info4;
7107
7108         info4.version           = r->version;
7109         info4.driver_name       = r->driver_name;
7110         info4.architecture      = r->architecture;
7111         info4.driver_path       = r->driver_path;
7112         info4.data_file         = r->data_file;
7113         info4.config_file       = r->config_file;
7114         info4.help_file         = r->help_file;
7115         info4.monitor_name      = r->monitor_name;
7116         info4.default_datatype  = r->default_datatype;
7117         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7118         info4.dependent_files   = r->dependent_files;
7119         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7120         info4.previous_names = r->previous_names;
7121
7122         info_ctr.level = 4;
7123         info_ctr.info.info4 = &info4;
7124
7125         if (ex) {
7126                 torture_assert(tctx,
7127                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7128                         "failed to test AddPrinterDriverEx level 4");
7129         } else {
7130                 torture_assert(tctx,
7131                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7132                         "failed to test AddPrinterDriver level 4");
7133         }
7134
7135         torture_assert(tctx,
7136                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7137                 "failed to find added printer driver");
7138
7139         return true;
7140 }
7141
7142 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7143                                                struct dcerpc_binding_handle *b,
7144                                                const char *server_name,
7145                                                struct spoolss_AddDriverInfo8 *r,
7146                                                uint32_t flags,
7147                                                bool ex)
7148 {
7149         struct spoolss_AddDriverInfoCtr info_ctr;
7150         struct spoolss_AddDriverInfo6 info6;
7151
7152         info6.version           = r->version;
7153         info6.driver_name       = r->driver_name;
7154         info6.architecture      = r->architecture;
7155         info6.driver_path       = r->driver_path;
7156         info6.data_file         = r->data_file;
7157         info6.config_file       = r->config_file;
7158         info6.help_file         = r->help_file;
7159         info6.monitor_name      = r->monitor_name;
7160         info6.default_datatype  = r->default_datatype;
7161         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7162         info6.dependent_files   = r->dependent_files;
7163         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7164         info6.previous_names    = r->previous_names;
7165         info6.driver_date       = r->driver_date;
7166         info6.driver_version    = r->driver_version;
7167         info6.manufacturer_name = r->manufacturer_name;
7168         info6.manufacturer_url  = r->manufacturer_url;
7169         info6.hardware_id       = r->hardware_id;
7170         info6.provider          = r->provider;
7171
7172         info_ctr.level = 6;
7173         info_ctr.info.info6 = &info6;
7174
7175         if (ex) {
7176                 torture_assert(tctx,
7177                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7178                         "failed to test AddPrinterDriverEx level 6");
7179         } else {
7180                 torture_assert(tctx,
7181                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7182                         "failed to test AddPrinterDriver level 6");
7183         }
7184
7185         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7186
7187         if (!ex) {
7188                 return true;
7189         }
7190
7191         torture_assert(tctx,
7192                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7193                 "failed to find added printer driver");
7194
7195         return true;
7196 }
7197
7198 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7199                                                struct dcerpc_binding_handle *b,
7200                                                const char *server_name,
7201                                                struct spoolss_AddDriverInfo8 *r,
7202                                                uint32_t flags,
7203                                                bool ex)
7204 {
7205         struct spoolss_AddDriverInfoCtr info_ctr;
7206
7207         info_ctr.level = 8;
7208         info_ctr.info.info8 = r;
7209
7210         if (ex) {
7211                 torture_assert(tctx,
7212                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7213                         "failed to test AddPrinterDriverEx level 8");
7214         } else {
7215                 torture_assert(tctx,
7216                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7217                         "failed to test AddPrinterDriver level 8");
7218         }
7219
7220         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7221
7222         if (!ex) {
7223                 return true;
7224         }
7225
7226         torture_assert(tctx,
7227                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7228                 "failed to find added printer driver");
7229
7230         return true;
7231 }
7232
7233 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7234                                          struct dcerpc_binding_handle *b,
7235                                          const char *server,
7236                                          const char *driver,
7237                                          const char *environment,
7238                                          WERROR expected_result)
7239 {
7240         struct spoolss_DeletePrinterDriver r;
7241
7242         r.in.server = server;
7243         r.in.architecture = environment;
7244         r.in.driver = driver;
7245
7246         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7247
7248         torture_assert_ntstatus_ok(tctx,
7249                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7250                 "DeletePrinterDriver failed");
7251         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7252                 "DeletePrinterDriver failed with unexpected result");
7253
7254         return true;
7255 }
7256
7257 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7258                                            struct dcerpc_binding_handle *b,
7259                                            const char *server,
7260                                            const char *driver,
7261                                            const char *environment,
7262                                            uint32_t delete_flags,
7263                                            uint32_t version,
7264                                            WERROR expected_result)
7265 {
7266         struct spoolss_DeletePrinterDriverEx r;
7267
7268         r.in.server = server;
7269         r.in.architecture = environment;
7270         r.in.driver = driver;
7271         r.in.delete_flags = delete_flags;
7272         r.in.version = version;
7273
7274         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7275
7276         torture_assert_ntstatus_ok(tctx,
7277                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7278                 "DeletePrinterDriverEx failed");
7279         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7280                 "DeletePrinterDriverEx failed with unexpected result");
7281
7282         return true;
7283 }
7284
7285 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7286                                      struct dcerpc_binding_handle *b,
7287                                      const char *server_name,
7288                                      const char *driver,
7289                                      const char *environment)
7290 {
7291         torture_assert(tctx,
7292                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7293                 "failed to delete driver");
7294
7295         torture_assert(tctx,
7296                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7297                 "failed to delete driver");
7298
7299         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7300                 torture_fail(tctx, "deleted driver still enumerated");
7301         }
7302
7303         torture_assert(tctx,
7304                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7305                 "2nd delete failed");
7306
7307         return true;
7308 }
7309
7310 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7311                                        struct dcerpc_binding_handle *b,
7312                                        const char *server_name,
7313                                        const char *driver,
7314                                        const char *environment,
7315                                        uint32_t delete_flags,
7316                                        uint32_t version)
7317 {
7318         torture_assert(tctx,
7319                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7320                 "failed to delete driver");
7321
7322         torture_assert(tctx,
7323                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7324                 "failed to delete driver");
7325
7326         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7327                 torture_fail(tctx, "deleted driver still enumerated");
7328         }
7329
7330         torture_assert(tctx,
7331                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7332                 "2nd delete failed");
7333
7334         return true;
7335 }
7336
7337 static bool test_PrinterDriver_args(struct torture_context *tctx,
7338                                     struct dcerpc_binding_handle *b,
7339                                     const char *server_name,
7340                                     uint32_t level,
7341                                     struct spoolss_AddDriverInfo8 *r,
7342                                     uint32_t add_flags,
7343                                     uint32_t delete_flags,
7344                                     uint32_t delete_version,
7345                                     bool ex)
7346 {
7347         bool ret = true;
7348
7349         switch (level) {
7350         case 1:
7351                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7352                 break;
7353         case 2:
7354                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7355                 break;
7356         case 3:
7357                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7358                 break;
7359         case 4:
7360                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7361                 break;
7362         case 6:
7363                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7364                 break;
7365         case 8:
7366                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7367                 break;
7368         default:
7369                 return false;
7370         }
7371
7372         if (ret == false) {
7373                 return ret;
7374         }
7375
7376         if (level == 1) {
7377                 return ret;
7378         }
7379
7380         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7381
7382         if (!ex && (level == 6 || level == 8)) {
7383                 return ret;
7384         }
7385
7386         if (ex) {
7387                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
7388         } else {
7389                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
7390         }
7391 }
7392
7393 static bool fillup_printserver_info(struct torture_context *tctx,
7394                                     struct dcerpc_pipe *p,
7395                                     struct torture_driver_context *d)
7396 {
7397         struct policy_handle server_handle;
7398         struct dcerpc_binding_handle *b = p->binding_handle;
7399         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7400
7401         torture_assert(tctx,
7402                 test_OpenPrinter_server(tctx, p, &server_handle),
7403                 "failed to open printserver");
7404         torture_assert(tctx,
7405                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
7406                 "failed to get environment");
7407         torture_assert(tctx,
7408                 test_ClosePrinter(tctx, b, &server_handle),
7409                 "failed to close printserver");
7410
7411         torture_assert(tctx,
7412                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
7413                         d->local.environment ? d->local.environment : d->remote.environment,
7414                         &d->remote.driver_directory),
7415                 "failed to get driver directory");
7416
7417         return true;
7418 }
7419
7420 static const char *driver_directory_dir(const char *driver_directory)
7421 {
7422         char *p;
7423
7424         p = strrchr(driver_directory, '\\');
7425         if (p) {
7426                 return p+1;
7427         }
7428
7429         return NULL;
7430 }
7431
7432 static const char *driver_directory_share(struct torture_context *tctx,
7433                                           const char *driver_directory)
7434 {
7435         const char *p;
7436         char *tok;
7437
7438         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
7439                 driver_directory += 2;
7440         }
7441
7442         p = talloc_strdup(tctx, driver_directory);
7443
7444         torture_assert(tctx,
7445                 next_token_talloc(tctx, &p, &tok, "\\"),
7446                 "cannot explode uri");
7447         torture_assert(tctx,
7448                 next_token_talloc(tctx, &p, &tok, "\\"),
7449                 "cannot explode uri");
7450
7451         return tok;
7452 }
7453
7454 static bool upload_printer_driver_file(struct torture_context *tctx,
7455                                        struct smbcli_state *cli,
7456                                        struct torture_driver_context *d,
7457                                        const char *file_name)
7458 {
7459         XFILE *f;
7460         int fnum;
7461         uint8_t *buf;
7462         int maxwrite = 64512;
7463         off_t nread = 0;
7464         size_t start = 0;
7465         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7466         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
7467         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7468
7469         if (!file_name) {
7470                 return true;
7471         }
7472
7473         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
7474
7475         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
7476         if (fnum == -1) {
7477                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
7478         }
7479
7480         f = x_fopen(local_name, O_RDONLY, 0);
7481         if (f == NULL) {
7482                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
7483         }
7484
7485         buf = talloc_array(tctx, uint8_t, maxwrite);
7486         if (!buf) {
7487                 return false;
7488         }
7489
7490         while (!x_feof(f)) {
7491                 int n = maxwrite;
7492                 int ret;
7493
7494                 if ((n = x_fread(buf, 1, n, f)) < 1) {
7495                         if((n == 0) && x_feof(f))
7496                                 break; /* Empty local file. */
7497
7498                         torture_warning(tctx,
7499                                 "failed to read file: %s\n", strerror(errno));
7500                         break;
7501                 }
7502
7503                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
7504
7505                 if (n != ret) {
7506                         torture_warning(tctx,
7507                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
7508                         break;
7509                 }
7510
7511                 nread += n;
7512         }
7513
7514         x_fclose(f);
7515
7516         torture_assert_ntstatus_ok(tctx,
7517                 smbcli_close(cli->tree, fnum),
7518                 "failed to close file");
7519
7520         return true;
7521 }
7522
7523 static bool connect_printer_driver_share(struct torture_context *tctx,
7524                                          const char *server_name,
7525                                          const char *share_name,
7526                                          struct smbcli_state **cli)
7527 {
7528         struct smbcli_options smb_options;
7529         struct smbcli_session_options smb_session_options;
7530
7531         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
7532                 share_name, server_name);
7533
7534         lp_smbcli_options(tctx->lp_ctx, &smb_options);
7535         lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
7536
7537         torture_assert_ntstatus_ok(tctx,
7538                 smbcli_full_connection(tctx, cli, server_name,
7539                                         lp_smb_ports(tctx->lp_ctx),
7540                                         share_name, NULL,
7541                                         lp_socket_options(tctx->lp_ctx),
7542                                         cmdline_credentials,
7543                                         lp_resolve_context(tctx->lp_ctx),
7544                                         tctx->ev,
7545                                         &smb_options,
7546                                         &smb_session_options,
7547                                         lp_iconv_convenience(tctx->lp_ctx),
7548                                         lp_gensec_settings(tctx, tctx->lp_ctx)),
7549                 "failed to open driver share");
7550
7551         return true;
7552 }
7553
7554 static bool upload_printer_driver(struct torture_context *tctx,
7555                                   const char *server_name,
7556                                   struct torture_driver_context *d)
7557 {
7558         struct smbcli_state *cli;
7559         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7560         int i;
7561
7562         torture_assert(tctx,
7563                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7564                 "failed to connect to driver share");
7565
7566         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
7567                 server_name, share_name);
7568
7569         torture_assert(tctx,
7570                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7571                 "failed to upload driver_path");
7572         torture_assert(tctx,
7573                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
7574                 "failed to upload data_file");
7575         torture_assert(tctx,
7576                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
7577                 "failed to upload config_file");
7578         torture_assert(tctx,
7579                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
7580                 "failed to upload help_file");
7581         if (d->info8.dependent_files) {
7582                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7583                         torture_assert(tctx,
7584                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7585                                 "failed to upload dependent_files");
7586                 }
7587         }
7588
7589         talloc_free(cli);
7590
7591         return true;
7592 }
7593
7594 static bool remove_printer_driver_file(struct torture_context *tctx,
7595                                        struct smbcli_state *cli,
7596                                        struct torture_driver_context *d,
7597                                        const char *file_name)
7598 {
7599         const char *remote_name;
7600         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
7601
7602         if (!file_name) {
7603                 return true;
7604         }
7605
7606         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7607
7608         torture_comment(tctx, "Removing %s\n", remote_name);
7609
7610         torture_assert_ntstatus_ok(tctx,
7611                 smbcli_unlink(cli->tree, remote_name),
7612                 "failed to unlink");
7613
7614         return true;
7615 }
7616
7617 static bool remove_printer_driver(struct torture_context *tctx,
7618                                   const char *server_name,
7619                                   struct torture_driver_context *d)
7620 {
7621         struct smbcli_state *cli;
7622         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7623         int i;
7624
7625         torture_assert(tctx,
7626                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7627                 "failed to connect to driver share");
7628
7629         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
7630                 server_name, share_name);
7631
7632         torture_assert(tctx,
7633                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7634                 "failed to remove driver_path");
7635         torture_assert(tctx,
7636                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
7637                 "failed to remove data_file");
7638         torture_assert(tctx,
7639                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
7640                 "failed to remove config_file");
7641         torture_assert(tctx,
7642                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
7643                 "failed to remove help_file");
7644         if (d->info8.dependent_files) {
7645                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7646                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
7647                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
7648                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
7649                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
7650                                 continue;
7651                         }
7652                         torture_assert(tctx,
7653                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7654                                 "failed to remove dependent_files");
7655                 }
7656         }
7657
7658         talloc_free(cli);
7659
7660         return true;
7661
7662 }
7663
7664 static bool test_add_driver_arg(struct torture_context *tctx,
7665                                 struct dcerpc_pipe *p,
7666                                 struct torture_driver_context *d)
7667 {
7668         bool ret = true;
7669         struct dcerpc_binding_handle *b = p->binding_handle;
7670         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7671         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
7672         int i;
7673         struct spoolss_AddDriverInfo8 info8;
7674         uint32_t add_flags = APD_COPY_NEW_FILES;
7675         uint32_t delete_flags = 0;
7676
7677         ZERO_STRUCT(info8);
7678
7679         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
7680                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
7681
7682         torture_assert(tctx,
7683                 fillup_printserver_info(tctx, p, d),
7684                 "failed to fillup printserver info");
7685
7686         if (!directory_exist(d->local.driver_directory)) {
7687                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
7688         }
7689
7690         torture_assert(tctx,
7691                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
7692                 "failed to upload printer driver");
7693
7694         info8.version           = d->info8.version;
7695         info8.driver_name       = d->info8.driver_name;
7696         info8.architecture      = d->local.environment;
7697         info8.driver_path       = d->info8.driver_path;
7698         info8.data_file         = d->info8.data_file;
7699         info8.config_file       = d->info8.config_file;
7700
7701         for (i=0; i < ARRAY_SIZE(levels); i++) {
7702
7703                 if (torture_setting_bool(tctx, "samba3", false)) {
7704                         switch (levels[i]) {
7705                         case 2:
7706                         case 4:
7707                         case 8:
7708                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7709                                 continue;
7710                         default:
7711                                 break;
7712                         }
7713                 }
7714
7715                 torture_comment(tctx,
7716                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
7717                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7718
7719                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7720         }
7721
7722         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
7723         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
7724         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
7725
7726         for (i=0; i < ARRAY_SIZE(levels); i++) {
7727
7728                 if (torture_setting_bool(tctx, "samba3", false)) {
7729                         switch (levels[i]) {
7730                         case 2:
7731                         case 4:
7732                         case 8:
7733                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7734                                 continue;
7735                         default:
7736                                 break;
7737                         }
7738                 }
7739
7740
7741                 torture_comment(tctx,
7742                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
7743                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7744
7745                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7746         }
7747
7748         torture_assert(tctx,
7749                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
7750                 "failed to remove printer driver");
7751
7752         torture_comment(tctx, "\n");
7753
7754         return ret;
7755 }
7756
7757 static bool test_add_driver_ex_64(struct torture_context *tctx,
7758                                   struct dcerpc_pipe *p,
7759                                   void *private_data)
7760 {
7761         struct torture_driver_context *d =
7762                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7763
7764         d->local.environment            = talloc_strdup(d, "Windows x64");
7765         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7766         d->info8.driver_name            = TORTURE_DRIVER_EX;
7767         d->ex                           = true;
7768
7769         return test_add_driver_arg(tctx, p, d);
7770 }
7771
7772 static bool test_add_driver_ex_32(struct torture_context *tctx,
7773                                   struct dcerpc_pipe *p,
7774                                   void *private_data)
7775 {
7776         struct torture_driver_context *d =
7777                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7778
7779         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7780         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7781         d->info8.driver_name            = TORTURE_DRIVER_EX;
7782         d->ex                           = true;
7783
7784         return test_add_driver_arg(tctx, p, d);
7785 }
7786
7787 static bool test_add_driver_64(struct torture_context *tctx,
7788                                struct dcerpc_pipe *p,
7789                                void *private_data)
7790 {
7791         struct torture_driver_context *d =
7792                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7793
7794         d->local.environment            = talloc_strdup(d, "Windows x64");
7795         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7796         d->info8.driver_name            = TORTURE_DRIVER;
7797         d->ex                           = false;
7798
7799         return test_add_driver_arg(tctx, p, d);
7800 }
7801
7802 static bool test_add_driver_32(struct torture_context *tctx,
7803                                struct dcerpc_pipe *p,
7804                                void *private_data)
7805 {
7806         struct torture_driver_context *d =
7807                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7808
7809         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7810         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7811         d->info8.driver_name            = TORTURE_DRIVER;
7812         d->ex                           = false;
7813
7814         return test_add_driver_arg(tctx, p, d);
7815 }
7816
7817 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
7818 {
7819         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
7820
7821         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
7822                                                         "driver", &ndr_table_spoolss);
7823         struct torture_driver_context *t;
7824
7825         t = talloc_zero(mem_ctx, struct torture_driver_context);
7826
7827         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
7828         t->info8.driver_name    = NULL;
7829         t->info8.architecture   = NULL;
7830         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
7831         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
7832         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
7833
7834         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
7835         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
7836
7837         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
7838         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
7839
7840         return suite;
7841 }