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