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