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