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