s4-smbtorture: fix build and handle in spoolss test.
[metze/samba/wip.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/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_comment(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_comment(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                 WERROR result;
3203                 uint32_t value_needed, data_needed;
3204
3205                 torture_assert(tctx,
3206                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3207                                              &type, &value_needed, &data_needed,
3208                                              &value_name, &data, &result),
3209                         "EnumPrinterData failed");
3210
3211                 if (i -1 == count) {
3212                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3213                                 "unexpected result");
3214                         break;
3215                 } else {
3216                         torture_assert_werr_ok(tctx, result, "unexpected result");
3217                 }
3218
3219                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3220                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3221                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3222                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3223                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3224         }
3225
3226         return true;
3227 }
3228
3229 static bool test_DeletePrinterData(struct torture_context *tctx,
3230                                    struct dcerpc_pipe *p,
3231                                    struct policy_handle *handle,
3232                                    const char *value_name)
3233 {
3234         NTSTATUS status;
3235         struct spoolss_DeletePrinterData r;
3236
3237         r.in.handle = handle;
3238         r.in.value_name = value_name;
3239
3240         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3241                 r.in.value_name);
3242
3243         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3244
3245         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3246         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3247
3248         return true;
3249 }
3250
3251 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3252                                      struct dcerpc_pipe *p,
3253                                      struct policy_handle *handle,
3254                                      const char *key_name,
3255                                      const char *value_name)
3256 {
3257         struct spoolss_DeletePrinterDataEx r;
3258
3259         r.in.handle = handle;
3260         r.in.key_name = key_name;
3261         r.in.value_name = value_name;
3262
3263         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3264                 r.in.key_name, r.in.value_name);
3265
3266         torture_assert_ntstatus_ok(tctx,
3267                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3268                 "DeletePrinterDataEx failed");
3269         torture_assert_werr_ok(tctx, r.out.result,
3270                 "DeletePrinterDataEx failed");
3271
3272         return true;
3273 }
3274
3275 static bool test_DeletePrinterKey(struct torture_context *tctx,
3276                                   struct dcerpc_pipe *p,
3277                                   struct policy_handle *handle,
3278                                   const char *key_name)
3279 {
3280         struct spoolss_DeletePrinterKey r;
3281
3282         r.in.handle = handle;
3283         r.in.key_name = key_name;
3284
3285         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3286
3287         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3288                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3289                 return true;
3290         }
3291
3292         torture_assert_ntstatus_ok(tctx,
3293                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3294                 "DeletePrinterKey failed");
3295         torture_assert_werr_ok(tctx, r.out.result,
3296                 "DeletePrinterKey failed");
3297
3298         return true;
3299 }
3300
3301 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3302                                  struct dcerpc_pipe *p,
3303                                  struct policy_handle *handle)
3304 {
3305         struct winreg_OpenHKLM r;
3306
3307         r.in.system_name = NULL;
3308         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3309         r.out.handle = handle;
3310
3311         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3312
3313         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3314         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3315
3316         return true;
3317 }
3318
3319 static void init_winreg_String(struct winreg_String *name, const char *s)
3320 {
3321         name->name = s;
3322         if (s) {
3323                 name->name_len = 2 * (strlen_m(s) + 1);
3324                 name->name_size = name->name_len;
3325         } else {
3326                 name->name_len = 0;
3327                 name->name_size = 0;
3328         }
3329 }
3330
3331 static bool test_winreg_OpenKey(struct torture_context *tctx,
3332                                 struct dcerpc_pipe *p,
3333                                 struct policy_handle *hive_handle,
3334                                 const char *keyname,
3335                                 struct policy_handle *key_handle)
3336 {
3337         struct winreg_OpenKey r;
3338
3339         r.in.parent_handle = hive_handle;
3340         init_winreg_String(&r.in.keyname, keyname);
3341         r.in.options = REG_KEYTYPE_NON_VOLATILE;
3342         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3343         r.out.handle = key_handle;
3344
3345         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3346
3347         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3348         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3349
3350         return true;
3351 }
3352
3353 static bool test_winreg_CloseKey(struct torture_context *tctx,
3354                                  struct dcerpc_pipe *p,
3355                                  struct policy_handle *handle)
3356 {
3357         struct winreg_CloseKey r;
3358
3359         r.in.handle = handle;
3360         r.out.handle = handle;
3361
3362         torture_comment(tctx, "Testing winreg_CloseKey\n");
3363
3364         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3365         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3366
3367         return true;
3368 }
3369
3370 bool test_winreg_QueryValue(struct torture_context *tctx,
3371                             struct dcerpc_pipe *p,
3372                             struct policy_handle *handle,
3373                             const char *value_name,
3374                             enum winreg_Type *type_p,
3375                             uint32_t *data_size_p,
3376                             uint32_t *data_length_p,
3377                             uint8_t **data_p)
3378 {
3379         struct winreg_QueryValue r;
3380         enum winreg_Type type = REG_NONE;
3381         uint32_t data_size = 0;
3382         uint32_t data_length = 0;
3383         struct winreg_String valuename;
3384         uint8_t *data = NULL;
3385
3386         init_winreg_String(&valuename, value_name);
3387
3388         data = talloc_zero_array(tctx, uint8_t, 0);
3389
3390         r.in.handle = handle;
3391         r.in.value_name = &valuename;
3392         r.in.type = &type;
3393         r.in.data_size = &data_size;
3394         r.in.data_length = &data_length;
3395         r.in.data = data;
3396         r.out.type = &type;
3397         r.out.data = data;
3398         r.out.data_size = &data_size;
3399         r.out.data_length = &data_length;
3400
3401         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3402
3403         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3404         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3405                 *r.in.data_size = *r.out.data_size;
3406                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3407                 r.in.data = data;
3408                 r.out.data = data;
3409                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3410         }
3411         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3412
3413         if (type_p) {
3414                 *type_p = *r.out.type;
3415         }
3416         if (data_size_p) {
3417                 *data_size_p = *r.out.data_size;
3418         }
3419         if (data_length_p) {
3420                 *data_length_p = *r.out.data_length;
3421         }
3422         if (data_p) {
3423                 *data_p = r.out.data;
3424         }
3425
3426         return true;
3427 }
3428
3429 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3430                                           struct dcerpc_pipe *p,
3431                                           struct policy_handle *handle,
3432                                           const char *printer_name,
3433                                           const char *key_name,
3434                                           const char *value_name,
3435                                           enum winreg_Type *w_type,
3436                                           uint32_t *w_size,
3437                                           uint32_t *w_length,
3438                                           uint8_t **w_data)
3439 {
3440         const char *printer_key;
3441         struct policy_handle key_handle;
3442
3443         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3444                 TOP_LEVEL_PRINTER_KEY, printer_name, key_name);
3445
3446         torture_assert(tctx,
3447                 test_winreg_OpenKey(tctx, p, handle, printer_key, &key_handle), "");
3448
3449         torture_assert(tctx,
3450                 test_winreg_QueryValue(tctx, p, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3451
3452         torture_assert(tctx,
3453                 test_winreg_CloseKey(tctx, p, &key_handle), "");
3454
3455         return true;
3456 }
3457
3458 static bool test_SetPrinterData(struct torture_context *tctx,
3459                                 struct dcerpc_pipe *p,
3460                                 struct policy_handle *handle,
3461                                 const char *value_name,
3462                                 enum winreg_Type type,
3463                                 uint8_t *data,
3464                                 uint32_t offered)
3465 {
3466         struct spoolss_SetPrinterData r;
3467
3468         r.in.handle = handle;
3469         r.in.value_name = value_name;
3470         r.in.type = type;
3471         r.in.data = data;
3472         r.in.offered = offered;
3473
3474         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3475                 r.in.value_name);
3476
3477         torture_assert_ntstatus_ok(tctx,
3478                 dcerpc_spoolss_SetPrinterData(p, tctx, &r),
3479                 "SetPrinterData failed");
3480         torture_assert_werr_ok(tctx, r.out.result,
3481                 "SetPrinterData failed");
3482
3483         return true;
3484 }
3485
3486 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
3487                                        struct dcerpc_pipe *p,
3488                                        struct policy_handle *handle,
3489                                        const char *printer_name,
3490                                        struct dcerpc_pipe *winreg_pipe,
3491                                        struct policy_handle *hive_handle)
3492 {
3493         const char *values[] = {
3494                 "spootyfoot",
3495                 "spooty\\foot",
3496 #if 0
3497         /* FIXME: not working with s3 atm. */
3498                 "spooty,foot",
3499                 "spooty,fo,ot",
3500 #endif
3501                 "spooty foot",
3502 #if 0
3503         /* FIXME: not working with s3 atm. */
3504                 "spooty\\fo,ot",
3505                 "spooty,fo\\ot"
3506 #endif
3507         };
3508         int i;
3509
3510         for (i=0; i < ARRAY_SIZE(values); i++) {
3511
3512                 enum winreg_Type type;
3513                 DATA_BLOB blob;
3514                 uint8_t *data;
3515                 uint32_t needed;
3516
3517                 torture_assert(tctx,
3518                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3519                                           "REG_SZ", "dog", &type, &blob), "");
3520
3521                 torture_assert(tctx,
3522                         test_SetPrinterData(tctx, p, handle, values[i], REG_SZ, blob.data, blob.length),
3523                         "SetPrinterData failed");
3524
3525                 torture_assert(tctx,
3526                         test_GetPrinterData(tctx, p, handle, values[i], &type, &data, &needed),
3527                         "GetPrinterData failed");
3528
3529                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
3530                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
3531                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
3532
3533                 if (winreg_pipe && hive_handle) {
3534
3535                         enum winreg_Type w_type;
3536                         uint32_t w_size;
3537                         uint32_t w_length;
3538                         uint8_t *w_data;
3539
3540                         torture_assert(tctx,
3541                                 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3542                                         printer_name, "PrinterDriverData", values[i],
3543                                         &w_type, &w_size, &w_length, &w_data), "");
3544
3545                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
3546                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
3547                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
3548                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
3549                 }
3550
3551                 torture_assert(tctx,
3552                         test_DeletePrinterData(tctx, p, handle, values[i]),
3553                         "DeletePrinterData failed");
3554         }
3555
3556         return true;
3557 }
3558
3559
3560 static bool test_EnumPrinterKey(struct torture_context *tctx,
3561                                 struct dcerpc_pipe *p,
3562                                 struct policy_handle *handle,
3563                                 const char *key_name,
3564                                 const char ***array);
3565
3566 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3567                                   struct dcerpc_pipe *p,
3568                                   struct policy_handle *handle,
3569                                   const char *key_name,
3570                                   const char *value_name,
3571                                   enum winreg_Type type,
3572                                   uint8_t *data,
3573                                   uint32_t offered)
3574 {
3575         NTSTATUS status;
3576         struct spoolss_SetPrinterDataEx r;
3577
3578         r.in.handle = handle;
3579         r.in.key_name = key_name;
3580         r.in.value_name = value_name;
3581         r.in.type = type;
3582         r.in.data = data;
3583         r.in.offered = offered;
3584
3585         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3586                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3587
3588         status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3589
3590         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3591         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3592
3593         return true;
3594 }
3595
3596 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3597                                          struct dcerpc_pipe *p,
3598                                          struct policy_handle *handle,
3599                                          const char *printername,
3600                                          struct dcerpc_pipe *winreg_pipe,
3601                                          struct policy_handle *hive_handle)
3602 {
3603         const char *value_name = "dog";
3604         const char *keys[] = {
3605                 "torturedataex",
3606                 "torture data ex",
3607 #if 0
3608         /* FIXME: not working with s3 atm. */
3609                 "torturedataex_with_subkey\\subkey",
3610                 "torturedataex_with_subkey\\subkey:0",
3611                 "torturedataex_with_subkey\\subkey:1",
3612                 "torturedataex_with_subkey\\subkey\\subsubkey",
3613                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3614                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3615 #endif
3616                 "torture,data",
3617 #if 0
3618         /* FIXME: not working with s3 atm. */
3619
3620                 "torture,data,ex",
3621                 "torture,data\\ex",
3622                 "torture\\data,ex"
3623 #endif
3624         };
3625         enum winreg_Type types[] = {
3626                 REG_SZ,
3627                 REG_DWORD,
3628                 REG_BINARY
3629         };
3630         const char *str = "abcdefghijklmnopqrstuvwxzy";
3631         int i, t, s;
3632
3633
3634         for (i=0; i < ARRAY_SIZE(keys); i++) {
3635         for (t=0; t < ARRAY_SIZE(types); t++) {
3636         for (s=0; s < strlen(str); s++) {
3637
3638                 char *c;
3639                 const char *key;
3640                 enum winreg_Type type;
3641                 const char *string = talloc_strndup(tctx, str, s);
3642                 DATA_BLOB blob = data_blob_string_const(string);
3643                 const char **subkeys;
3644                 DATA_BLOB data;
3645                 uint8_t *data_out;
3646                 uint32_t needed, offered = 0;
3647                 uint32_t ecount;
3648                 struct spoolss_PrinterEnumValues *einfo;
3649
3650                 switch (types[t]) {
3651                 case REG_BINARY:
3652                 case REG_DWORD:
3653                         data = blob;
3654                         offered = blob.length;
3655                         break;
3656                 case REG_SZ:
3657                         torture_assert(tctx,
3658                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3659                                                   "REG_SZ", string, &type, &data), "");
3660                         offered = data.length;
3661                         /*strlen_m_term(data.string)*2;*/
3662                         break;
3663                 default:
3664                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3665                 }
3666
3667                 torture_assert(tctx,
3668                         test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3669                         "failed to call SetPrinterDataEx");
3670
3671                 torture_assert(tctx,
3672                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
3673                         "failed to call GetPrinterDataEx");
3674
3675                 torture_assert(tctx,
3676                         test_EnumPrinterDataEx(tctx, p, handle, keys[i], &ecount, &einfo),
3677                         "failed to call EnumPrinterDataEx");
3678
3679                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3680                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3681                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3682
3683                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
3684                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
3685                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
3686                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
3687                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
3688                 if (einfo[0].data_length > 0) {
3689                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
3690                 }
3691
3692                 if (winreg_pipe && hive_handle) {
3693
3694                         enum winreg_Type w_type;
3695                         uint32_t w_size;
3696                         uint32_t w_length;
3697                         uint8_t *w_data;
3698
3699                         torture_assert(tctx,
3700                                 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3701                                         printername, keys[i], value_name,
3702                                         &w_type, &w_size, &w_length, &w_data), "");
3703
3704                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3705                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3706                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
3707                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3708                 }
3709
3710                 key = talloc_strdup(tctx, keys[i]);
3711
3712                 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3713                         return false;
3714                 }
3715
3716                 c = strchr(key, '\\');
3717                 if (c) {
3718                         int k;
3719
3720                         /* we have subkeys */
3721
3722                         *c = 0;
3723
3724                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3725                                 return false;
3726                         }
3727
3728                         for (k=0; subkeys && subkeys[k]; k++) {
3729
3730                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
3731
3732                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3733                                         return false;
3734                                 }
3735                         }
3736
3737                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3738                                 return false;
3739                         }
3740
3741                 } else {
3742                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3743                                 return false;
3744                         }
3745                 }
3746         }
3747         }
3748         }
3749
3750         return true;
3751 }
3752
3753 static bool test_PrinterData_winreg(struct torture_context *tctx,
3754                                     struct dcerpc_pipe *p,
3755                                     struct policy_handle *handle,
3756                                     const char *printer_name)
3757 {
3758         struct dcerpc_pipe *p2;
3759         bool ret = true;
3760         struct policy_handle hive_handle;
3761
3762         torture_assert_ntstatus_ok(tctx,
3763                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3764                 "could not open winreg pipe");
3765
3766         torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3767
3768         ret &= test_SetPrinterData_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3769         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3770
3771         test_winreg_CloseKey(tctx, p2, &hive_handle);
3772
3773         talloc_free(p2);
3774
3775         return ret;
3776 }
3777
3778 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3779                                          struct dcerpc_pipe *p,
3780                                          struct policy_handle *handle,
3781                                          uint32_t *change_id)
3782 {
3783         enum winreg_Type type;
3784         uint8_t *data;
3785         uint32_t needed;
3786
3787         torture_assert(tctx,
3788                 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3789                 "failed to call GetPrinterData");
3790
3791         torture_assert(tctx, type == REG_DWORD, "unexpected type");
3792         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3793
3794         *change_id = IVAL(data, 0);
3795
3796         return true;
3797 }
3798
3799 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3800                                            struct dcerpc_pipe *p,
3801                                            struct policy_handle *handle,
3802                                            uint32_t *change_id)
3803 {
3804         enum winreg_Type type;
3805         uint8_t *data;
3806         uint32_t needed;
3807
3808         torture_assert(tctx,
3809                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3810                 "failed to call GetPrinterData");
3811
3812         torture_assert(tctx, type == REG_DWORD, "unexpected type");
3813         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3814
3815         *change_id = IVAL(data, 0);
3816
3817         return true;
3818 }
3819
3820 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3821                                          struct dcerpc_pipe *p,
3822                                          struct policy_handle *handle,
3823                                          uint32_t *change_id)
3824 {
3825         union spoolss_PrinterInfo info;
3826
3827         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3828                 "failed to query Printer level 0");
3829
3830         *change_id = info.info0.change_id;
3831
3832         return true;
3833 }
3834
3835 static bool test_ChangeID(struct torture_context *tctx,
3836                           struct dcerpc_pipe *p,
3837                           struct policy_handle *handle)
3838 {
3839         uint32_t change_id, change_id_ex, change_id_info;
3840         uint32_t change_id2, change_id_ex2, change_id_info2;
3841         union spoolss_PrinterInfo info;
3842         const char *comment;
3843
3844
3845         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3846
3847         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3848                 "failed to query for ChangeID");
3849         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3850                 "failed to query for ChangeID");
3851         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3852                 "failed to query for ChangeID");
3853
3854         torture_assert_int_equal(tctx, change_id, change_id_ex,
3855                 "change_ids should all be equal");
3856         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3857                 "change_ids should all be equal");
3858
3859
3860         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3861
3862         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3863                 "failed to query for ChangeID");
3864         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3865                 "failed to query Printer level 2");
3866         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3867                 "failed to query for ChangeID");
3868         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3869                 "failed to query for ChangeID");
3870         torture_assert_int_equal(tctx, change_id, change_id_ex,
3871                 "change_id should not have changed");
3872         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3873                 "change_id should not have changed");
3874
3875
3876         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3877
3878         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3879                 "failed to query for ChangeID");
3880         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3881                 "failed to query for ChangeID");
3882         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3883                 "failed to query for ChangeID");
3884         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3885                 "failed to query Printer level 2");
3886         comment = talloc_strdup(tctx, info.info2.comment);
3887
3888         {
3889                 struct spoolss_SetPrinterInfoCtr info_ctr;
3890                 struct spoolss_DevmodeContainer devmode_ctr;
3891                 struct sec_desc_buf secdesc_ctr;
3892                 struct spoolss_SetPrinterInfo2 info2;
3893
3894                 ZERO_STRUCT(info_ctr);
3895                 ZERO_STRUCT(devmode_ctr);
3896                 ZERO_STRUCT(secdesc_ctr);
3897
3898                 info2.servername        = info.info2.servername;
3899                 info2.printername       = info.info2.printername;
3900                 info2.sharename         = info.info2.sharename;
3901                 info2.portname          = info.info2.portname;
3902                 info2.drivername        = info.info2.drivername;
3903                 info2.comment           = "torture_comment";
3904                 info2.location          = info.info2.location;
3905                 info2.devmode_ptr       = 0;
3906                 info2.sepfile           = info.info2.sepfile;
3907                 info2.printprocessor    = info.info2.printprocessor;
3908                 info2.datatype          = info.info2.datatype;
3909                 info2.parameters        = info.info2.parameters;
3910                 info2.secdesc_ptr       = 0;
3911                 info2.attributes        = info.info2.attributes;
3912                 info2.priority          = info.info2.priority;
3913                 info2.defaultpriority   = info.info2.defaultpriority;
3914                 info2.starttime         = info.info2.starttime;
3915                 info2.untiltime         = info.info2.untiltime;
3916                 info2.status            = info.info2.status;
3917                 info2.cjobs             = info.info2.cjobs;
3918                 info2.averageppm        = info.info2.averageppm;
3919
3920                 info_ctr.level = 2;
3921                 info_ctr.info.info2 = &info2;
3922
3923                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3924                         "failed to call SetPrinter");
3925
3926                 info2.comment           = comment;
3927
3928                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3929                         "failed to call SetPrinter");
3930
3931         }
3932
3933         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3934                 "failed to query for ChangeID");
3935         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3936                 "failed to query for ChangeID");
3937         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3938                 "failed to query for ChangeID");
3939
3940         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3941                 "change_ids should all be equal");
3942         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3943                 "change_ids should all be equal");
3944
3945         torture_assert(tctx, (change_id < change_id2),
3946                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3947                 change_id2, change_id));
3948         torture_assert(tctx, (change_id_ex < change_id_ex2),
3949                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3950                 change_id_ex2, change_id_ex));
3951         torture_assert(tctx, (change_id_info < change_id_info2),
3952                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3953                 change_id_info2, change_id_info));
3954
3955         return true;
3956 }
3957
3958 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3959                                        struct dcerpc_pipe *p,
3960                                        struct policy_handle *handle)
3961 {
3962         NTSTATUS status;
3963         struct dcerpc_binding *b;
3964         struct dcerpc_pipe *p2;
3965         struct spoolss_ClosePrinter cp;
3966
3967         /* only makes sense on SMB */
3968         if (p->conn->transport.transport != NCACN_NP) {
3969                 return true;
3970         }
3971
3972         torture_comment(tctx, "testing close on secondary pipe\n");
3973
3974         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3975         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3976
3977         status = dcerpc_secondary_connection(p, &p2, b);
3978         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3979
3980         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3981         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3982
3983         cp.in.handle = handle;
3984         cp.out.handle = handle;
3985
3986         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3987         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3988                         "ERROR: Allowed close on secondary connection");
3989
3990         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3991                                  "Unexpected fault code");
3992
3993         talloc_free(p2);
3994
3995         return true;
3996 }
3997
3998 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3999                                      struct dcerpc_pipe *p, const char *name)
4000 {
4001         NTSTATUS status;
4002         struct spoolss_OpenPrinter op;
4003         struct spoolss_OpenPrinterEx opEx;
4004         struct policy_handle handle;
4005         bool ret = true;
4006
4007         op.in.printername       = name;
4008         op.in.datatype          = NULL;
4009         op.in.devmode_ctr.devmode= NULL;
4010         op.in.access_mask       = 0;
4011         op.out.handle           = &handle;
4012
4013         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
4014
4015         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
4016         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4017         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
4018                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
4019                         name, win_errstr(op.out.result));
4020         }
4021
4022         if (W_ERROR_IS_OK(op.out.result)) {
4023                 ret &=test_ClosePrinter(tctx, p, &handle);
4024         }
4025
4026         opEx.in.printername             = name;
4027         opEx.in.datatype                = NULL;
4028         opEx.in.devmode_ctr.devmode     = NULL;
4029         opEx.in.access_mask             = 0;
4030         opEx.in.level                   = 1;
4031         opEx.in.userlevel.level1        = NULL;
4032         opEx.out.handle                 = &handle;
4033
4034         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4035
4036         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
4037         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4038         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
4039                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
4040                         name, win_errstr(opEx.out.result));
4041         }
4042
4043         if (W_ERROR_IS_OK(opEx.out.result)) {
4044                 ret &=test_ClosePrinter(tctx, p, &handle);
4045         }
4046
4047         return ret;
4048 }
4049
4050 static bool test_OpenPrinter(struct torture_context *tctx,
4051                              struct dcerpc_pipe *p,
4052                              const char *name,
4053                              const char *environment)
4054 {
4055         NTSTATUS status;
4056         struct spoolss_OpenPrinter r;
4057         struct policy_handle handle;
4058         bool ret = true;
4059
4060         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4061         r.in.datatype           = NULL;
4062         r.in.devmode_ctr.devmode= NULL;
4063         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4064         r.out.handle            = &handle;
4065
4066         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4067
4068         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
4069
4070         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4071
4072         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4073
4074         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4075                 ret = false;
4076         }
4077
4078         if (!torture_setting_bool(tctx, "samba3", false)) {
4079                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4080                         ret = false;
4081                 }
4082         }
4083
4084         if (!test_ClosePrinter(tctx, p, &handle)) {
4085                 ret = false;
4086         }
4087
4088         return ret;
4089 }
4090
4091 static bool call_OpenPrinterEx(struct torture_context *tctx,
4092                                struct dcerpc_pipe *p,
4093                                const char *name,
4094                                struct spoolss_DeviceMode *devmode,
4095                                struct policy_handle *handle)
4096 {
4097         struct spoolss_OpenPrinterEx r;
4098         struct spoolss_UserLevel1 userlevel1;
4099         NTSTATUS status;
4100
4101         if (name && name[0]) {
4102                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4103                                                    dcerpc_server_name(p), name);
4104         } else {
4105                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4106                                                    dcerpc_server_name(p));
4107         }
4108
4109         r.in.datatype           = NULL;
4110         r.in.devmode_ctr.devmode= devmode;
4111         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4112         r.in.level              = 1;
4113         r.in.userlevel.level1   = &userlevel1;
4114         r.out.handle = handle;
4115
4116         userlevel1.size = 1234;
4117         userlevel1.client = "hello";
4118         userlevel1.user = "spottyfoot!";
4119         userlevel1.build = 1;
4120         userlevel1.major = 2;
4121         userlevel1.minor = 3;
4122         userlevel1.processor = 4;
4123
4124         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4125
4126         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
4127
4128         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4129
4130         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4131
4132         return true;
4133 }
4134
4135 static bool test_OpenPrinterEx(struct torture_context *tctx,
4136                                struct dcerpc_pipe *p,
4137                                const char *name,
4138                                const char *environment)
4139 {
4140         struct policy_handle handle;
4141         bool ret = true;
4142
4143         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4144                 return false;
4145         }
4146
4147         if (!test_PrinterInfo_SD(tctx, p, &handle)) {
4148                 ret = false;
4149         }
4150
4151         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4152                 ret = false;
4153         }
4154
4155         if (!test_EnumForms(tctx, p, &handle, false)) {
4156                 ret = false;
4157         }
4158
4159         if (!test_AddForm(tctx, p, &handle, false)) {
4160                 ret = false;
4161         }
4162
4163         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4164                 ret = false;
4165         }
4166
4167         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData", NULL, NULL)) {
4168                 ret = false;
4169         }
4170
4171         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4172                 ret = false;
4173         }
4174
4175         if (!test_printer_keys(tctx, p, &handle)) {
4176                 ret = false;
4177         }
4178
4179         if (!test_PausePrinter(tctx, p, &handle)) {
4180                 ret = false;
4181         }
4182
4183         if (!test_DoPrintTest(tctx, p, &handle)) {
4184                 ret = false;
4185         }
4186
4187         if (!test_ResumePrinter(tctx, p, &handle)) {
4188                 ret = false;
4189         }
4190
4191         if (!test_SetPrinterData_matrix(tctx, p, &handle, name, NULL, NULL)) {
4192                 ret = false;
4193         }
4194
4195         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4196                 ret = false;
4197         }
4198
4199         if (!torture_setting_bool(tctx, "samba3", false)) {
4200                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4201                         ret = false;
4202                 }
4203         }
4204
4205         if (!test_ClosePrinter(tctx, p, &handle)) {
4206                 ret = false;
4207         }
4208
4209         return ret;
4210 }
4211
4212 static bool test_EnumPrinters_old(struct torture_context *tctx,
4213                                   struct dcerpc_pipe *p,
4214                                   const char *environment)
4215 {
4216         struct spoolss_EnumPrinters r;
4217         NTSTATUS status;
4218         uint16_t levels[] = {1, 2, 4, 5};
4219         int i;
4220         bool ret = true;
4221
4222         for (i=0;i<ARRAY_SIZE(levels);i++) {
4223                 union spoolss_PrinterInfo *info;
4224                 int j;
4225                 uint32_t needed;
4226                 uint32_t count;
4227
4228                 r.in.flags      = PRINTER_ENUM_LOCAL;
4229                 r.in.server     = "";
4230                 r.in.level      = levels[i];
4231                 r.in.buffer     = NULL;
4232                 r.in.offered    = 0;
4233                 r.out.needed    = &needed;
4234                 r.out.count     = &count;
4235                 r.out.info      = &info;
4236
4237                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4238
4239                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4240                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4241
4242                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4243                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4244                         data_blob_clear(&blob);
4245                         r.in.buffer = &blob;
4246                         r.in.offered = needed;
4247                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4248                 }
4249
4250                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4251
4252                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4253
4254                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4255
4256                 if (!info) {
4257                         torture_comment(tctx, "No printers returned\n");
4258                         return true;
4259                 }
4260
4261                 for (j=0;j<count;j++) {
4262                         if (r.in.level == 1) {
4263                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
4264                                 char *slash, *name;
4265                                 name = unc;
4266                                 if (unc[0] == '\\' && unc[1] == '\\') {
4267                                         unc +=2;
4268                                 }
4269                                 slash = strchr(unc, '\\');
4270                                 if (slash) {
4271                                         slash++;
4272                                         name = slash;
4273                                 }
4274                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
4275                                         ret = false;
4276                                 }
4277                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4278                                         ret = false;
4279                                 }
4280                         }
4281                 }
4282         }
4283
4284         return ret;
4285 }
4286
4287 static bool test_GetPrinterDriver(struct torture_context *tctx,
4288                                   struct dcerpc_pipe *p,
4289                                   struct policy_handle *handle,
4290                                   const char *driver_name)
4291 {
4292         struct spoolss_GetPrinterDriver r;
4293         uint32_t needed;
4294
4295         r.in.handle = handle;
4296         r.in.architecture = "W32X86";
4297         r.in.level = 1;
4298         r.in.buffer = NULL;
4299         r.in.offered = 0;
4300         r.out.needed = &needed;
4301
4302         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4303
4304         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4305                 "failed to call GetPrinterDriver");
4306         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4307                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4308                 data_blob_clear(&blob);
4309                 r.in.buffer = &blob;
4310                 r.in.offered = needed;
4311                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4312                         "failed to call GetPrinterDriver");
4313         }
4314
4315         torture_assert_werr_ok(tctx, r.out.result,
4316                 "failed to call GetPrinterDriver");
4317
4318         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4319
4320         return true;
4321 }
4322
4323 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4324                                    struct dcerpc_pipe *p,
4325                                    struct policy_handle *handle,
4326                                    const char *driver_name,
4327                                    const char *architecture)
4328 {
4329         struct spoolss_GetPrinterDriver2 r;
4330         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4331         uint32_t needed;
4332         uint32_t server_major_version;
4333         uint32_t server_minor_version;
4334         int i;
4335
4336         r.in.handle = handle;
4337         r.in.architecture = architecture;
4338         r.in.client_major_version = 3;
4339         r.in.client_minor_version = 0;
4340         r.out.needed = &needed;
4341         r.out.server_major_version = &server_major_version;
4342         r.out.server_minor_version = &server_minor_version;
4343
4344         for (i=0;i<ARRAY_SIZE(levels);i++) {
4345
4346                 r.in.buffer = NULL;
4347                 r.in.offered = 0;
4348                 r.in.level = levels[i];
4349
4350                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4351                         driver_name, r.in.level);
4352
4353                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4354                         "failed to call GetPrinterDriver2");
4355                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4356                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4357                         data_blob_clear(&blob);
4358                         r.in.buffer = &blob;
4359                         r.in.offered = needed;
4360                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4361                                 "failed to call GetPrinterDriver2");
4362                 }
4363
4364                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4365                         switch (r.in.level) {
4366                         case 101:
4367                         case 8:
4368                                 continue;
4369                         default:
4370                                 break;
4371                         }
4372                 }
4373
4374                 torture_assert_werr_ok(tctx, r.out.result,
4375                         "failed to call GetPrinterDriver2");
4376
4377                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4378         }
4379
4380         return true;
4381 }
4382
4383 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4384                                         struct dcerpc_pipe *p,
4385                                         const char *environment)
4386 {
4387         struct spoolss_EnumPrinterDrivers r;
4388         NTSTATUS status;
4389         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4390         int i;
4391
4392         for (i=0;i<ARRAY_SIZE(levels);i++) {
4393
4394                 uint32_t needed;
4395                 uint32_t count;
4396                 union spoolss_DriverInfo *info;
4397
4398                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4399                 r.in.environment = environment;
4400                 r.in.level = levels[i];
4401                 r.in.buffer = NULL;
4402                 r.in.offered = 0;
4403                 r.out.needed = &needed;
4404                 r.out.count = &count;
4405                 r.out.info = &info;
4406
4407                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4408
4409                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4410
4411                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4412
4413                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4414                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4415                         data_blob_clear(&blob);
4416                         r.in.buffer = &blob;
4417                         r.in.offered = needed;
4418                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4419                 }
4420
4421                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4422
4423                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4424
4425                 if (!info) {
4426                         torture_comment(tctx, "No printer drivers returned\n");
4427                         break;
4428                 }
4429
4430                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4431         }
4432
4433         return true;
4434 }
4435
4436 static bool test_DeletePrinter(struct torture_context *tctx,
4437                                struct dcerpc_pipe *p,
4438                                struct policy_handle *handle)
4439 {
4440         struct spoolss_DeletePrinter r;
4441
4442         torture_comment(tctx, "Testing DeletePrinter\n");
4443
4444         r.in.handle = handle;
4445
4446         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4447                 "failed to delete printer");
4448         torture_assert_werr_ok(tctx, r.out.result,
4449                 "failed to delete printer");
4450
4451         return true;
4452 }
4453
4454 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4455                                        struct dcerpc_pipe *p,
4456                                        uint32_t flags,
4457                                        uint32_t level,
4458                                        const char *name,
4459                                        bool *found)
4460 {
4461         struct spoolss_EnumPrinters e;
4462         uint32_t count;
4463         union spoolss_PrinterInfo *info;
4464         uint32_t needed;
4465         int i;
4466
4467         *found = false;
4468
4469         e.in.flags = flags;
4470         e.in.server = NULL;
4471         e.in.level = level;
4472         e.in.buffer = NULL;
4473         e.in.offered = 0;
4474         e.out.count = &count;
4475         e.out.info = &info;
4476         e.out.needed = &needed;
4477
4478         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4479                 "failed to enum printers");
4480
4481         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4482                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4483                 data_blob_clear(&blob);
4484                 e.in.buffer = &blob;
4485                 e.in.offered = needed;
4486
4487                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4488                         "failed to enum printers");
4489         }
4490
4491         torture_assert_werr_ok(tctx, e.out.result,
4492                 "failed to enum printers");
4493
4494         for (i=0; i < count; i++) {
4495
4496                 const char *current = NULL;
4497                 const char *q;
4498
4499                 switch (level) {
4500                 case 1:
4501                         current = info[i].info1.name;
4502                         break;
4503                 }
4504
4505                 if (strequal(current, name)) {
4506                         *found = true;
4507                         break;
4508                 }
4509
4510                 q = strrchr(current, '\\');
4511                 if (q) {
4512                         if (!e.in.server) {
4513                                 torture_warning(tctx,
4514                                         "server returns printername %s incl. servername although we did not set servername", current);
4515                         }
4516                         q++;
4517                         if (strequal(q, name)) {
4518                                 *found = true;
4519                                 break;
4520                         }
4521                 }
4522         }
4523
4524         return true;
4525 }
4526
4527 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4528                                       struct dcerpc_pipe *p,
4529                                       const char *printername,
4530                                       bool ex)
4531 {
4532         WERROR result;
4533         struct spoolss_AddPrinter r;
4534         struct spoolss_AddPrinterEx rex;
4535         struct spoolss_SetPrinterInfoCtr info_ctr;
4536         struct spoolss_SetPrinterInfo1 info1;
4537         struct spoolss_DevmodeContainer devmode_ctr;
4538         struct sec_desc_buf secdesc_ctr;
4539         struct spoolss_UserLevelCtr userlevel_ctr;
4540         struct policy_handle handle;
4541         bool found = false;
4542
4543         ZERO_STRUCT(devmode_ctr);
4544         ZERO_STRUCT(secdesc_ctr);
4545         ZERO_STRUCT(userlevel_ctr);
4546         ZERO_STRUCT(info1);
4547
4548         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4549
4550         /* try to add printer to wellknown printer list (level 1) */
4551
4552         userlevel_ctr.level = 1;
4553
4554         info_ctr.info.info1 = &info1;
4555         info_ctr.level = 1;
4556
4557         rex.in.server = NULL;
4558         rex.in.info_ctr = &info_ctr;
4559         rex.in.devmode_ctr = &devmode_ctr;
4560         rex.in.secdesc_ctr = &secdesc_ctr;
4561         rex.in.userlevel_ctr = &userlevel_ctr;
4562         rex.out.handle = &handle;
4563
4564         r.in.server = NULL;
4565         r.in.info_ctr = &info_ctr;
4566         r.in.devmode_ctr = &devmode_ctr;
4567         r.in.secdesc_ctr = &secdesc_ctr;
4568         r.out.handle = &handle;
4569
4570         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4571                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4572                 "failed to add printer");
4573         result = ex ? rex.out.result : r.out.result;
4574         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4575                 "unexpected result code");
4576
4577         info1.name = printername;
4578         info1.flags = PRINTER_ATTRIBUTE_SHARED;
4579
4580         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4581                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4582                 "failed to add printer");
4583         result = ex ? rex.out.result : r.out.result;
4584         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4585                 "unexpected result code");
4586
4587         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4588            better do a real check to see the printer is really there */
4589
4590         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4591                                                         PRINTER_ENUM_NETWORK, 1,
4592                                                         printername,
4593                                                         &found),
4594                         "failed to enum printers");
4595
4596         torture_assert(tctx, found, "failed to find newly added printer");
4597
4598         info1.flags = 0;
4599
4600         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4601                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4602                 "failed to add printer");
4603         result = ex ? rex.out.result : r.out.result;
4604         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4605                 "unexpected result code");
4606
4607         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4608            better do a real check to see the printer has really been removed
4609            from the well known printer list */
4610
4611         found = false;
4612
4613         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4614                                                         PRINTER_ENUM_NETWORK, 1,
4615                                                         printername,
4616                                                         &found),
4617                         "failed to enum printers");
4618 #if 0
4619         torture_assert(tctx, !found, "printer still in well known printer list");
4620 #endif
4621         return true;
4622 }
4623
4624 static bool test_AddPrinter_normal(struct torture_context *tctx,
4625                                    struct dcerpc_pipe *p,
4626                                    struct policy_handle *handle_p,
4627                                    const char *printername,
4628                                    const char *drivername,
4629                                    const char *portname,
4630                                    bool ex)
4631 {
4632         WERROR result;
4633         struct spoolss_AddPrinter r;
4634         struct spoolss_AddPrinterEx rex;
4635         struct spoolss_SetPrinterInfoCtr info_ctr;
4636         struct spoolss_SetPrinterInfo2 info2;
4637         struct spoolss_DevmodeContainer devmode_ctr;
4638         struct sec_desc_buf secdesc_ctr;
4639         struct spoolss_UserLevelCtr userlevel_ctr;
4640         struct policy_handle handle;
4641         bool found = false;
4642         bool existing_printer_deleted = false;
4643
4644         ZERO_STRUCT(devmode_ctr);
4645         ZERO_STRUCT(secdesc_ctr);
4646         ZERO_STRUCT(userlevel_ctr);
4647
4648         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4649
4650         userlevel_ctr.level = 1;
4651
4652         rex.in.server = NULL;
4653         rex.in.info_ctr = &info_ctr;
4654         rex.in.devmode_ctr = &devmode_ctr;
4655         rex.in.secdesc_ctr = &secdesc_ctr;
4656         rex.in.userlevel_ctr = &userlevel_ctr;
4657         rex.out.handle = &handle;
4658
4659         r.in.server = NULL;
4660         r.in.info_ctr = &info_ctr;
4661         r.in.devmode_ctr = &devmode_ctr;
4662         r.in.secdesc_ctr = &secdesc_ctr;
4663         r.out.handle = &handle;
4664
4665  again:
4666
4667         /* try to add printer to printer list (level 2) */
4668
4669         ZERO_STRUCT(info2);
4670
4671         info_ctr.info.info2 = &info2;
4672         info_ctr.level = 2;
4673
4674         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4675                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4676                 "failed to add printer");
4677         result = ex ? rex.out.result : r.out.result;
4678         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4679                 "unexpected result code");
4680
4681         info2.printername = printername;
4682
4683         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4684                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4685                 "failed to add printer");
4686         result = ex ? rex.out.result : r.out.result;
4687
4688         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4689                 struct policy_handle printer_handle;
4690
4691                 if (existing_printer_deleted) {
4692                         torture_fail(tctx, "already deleted printer still existing?");
4693                 }
4694
4695                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4696                         "failed to open printer handle");
4697
4698                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4699                         "failed to delete printer");
4700
4701                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4702                         "failed to close server handle");
4703
4704                 existing_printer_deleted = true;
4705
4706                 goto again;
4707         }
4708
4709         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4710                 "unexpected result code");
4711
4712         info2.portname = portname;
4713
4714         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4715                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4716                 "failed to add printer");
4717         result = ex ? rex.out.result : r.out.result;
4718         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4719                 "unexpected result code");
4720
4721         info2.drivername = drivername;
4722
4723         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4724                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4725                 "failed to add printer");
4726         result = ex ? rex.out.result : r.out.result;
4727
4728         /* w2k8r2 allows to add printer w/o defining printprocessor */
4729
4730         if (!W_ERROR_IS_OK(result)) {
4731                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4732                         "unexpected result code");
4733
4734                 info2.printprocessor = "winprint";
4735
4736                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4737                                                       dcerpc_spoolss_AddPrinter(p, tctx, &r),
4738                         "failed to add printer");
4739                 result = ex ? rex.out.result : r.out.result;
4740                 torture_assert_werr_ok(tctx, result,
4741                         "failed to add printer");
4742         }
4743
4744         *handle_p = handle;
4745
4746         /* we are paranoid, really check if the printer is there now */
4747
4748         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4749                                                         PRINTER_ENUM_LOCAL, 1,
4750                                                         printername,
4751                                                         &found),
4752                         "failed to enum printers");
4753         torture_assert(tctx, found, "failed to find newly added printer");
4754
4755         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4756                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4757                 "failed to add printer");
4758         result = ex ? rex.out.result : r.out.result;
4759         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4760                 "unexpected result code");
4761
4762         return true;
4763 }
4764
4765 static bool test_AddPrinterEx(struct torture_context *tctx,
4766                               struct dcerpc_pipe *p,
4767                               struct policy_handle *handle_p,
4768                               const char *printername,
4769                               const char *drivername,
4770                               const char *portname)
4771 {
4772         bool ret = true;
4773
4774         if (!torture_setting_bool(tctx, "samba3", false)) {
4775                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4776                         torture_comment(tctx, "failed to add printer to well known list\n");
4777                         ret = false;
4778                 }
4779         }
4780
4781         if (!test_AddPrinter_normal(tctx, p, handle_p,
4782                                     printername, drivername, portname,
4783                                     true)) {
4784                 torture_comment(tctx, "failed to add printer to printer list\n");
4785                 ret = false;
4786         }
4787
4788         return ret;
4789 }
4790
4791 static bool test_AddPrinter(struct torture_context *tctx,
4792                             struct dcerpc_pipe *p,
4793                             struct policy_handle *handle_p,
4794                             const char *printername,
4795                             const char *drivername,
4796                             const char *portname)
4797 {
4798         bool ret = true;
4799
4800         if (!torture_setting_bool(tctx, "samba3", false)) {
4801                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4802                         torture_comment(tctx, "failed to add printer to well known list\n");
4803                         ret = false;
4804                 }
4805         }
4806
4807         if (!test_AddPrinter_normal(tctx, p, handle_p,
4808                                     printername, drivername, portname,
4809                                     false)) {
4810                 torture_comment(tctx, "failed to add printer to printer list\n");
4811                 ret = false;
4812         }
4813
4814         return ret;
4815 }
4816
4817 static bool test_printer_info(struct torture_context *tctx,
4818                               struct dcerpc_pipe *p,
4819                               struct policy_handle *handle)
4820 {
4821         bool ret = true;
4822
4823         if (torture_setting_bool(tctx, "samba3", false)) {
4824                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4825         }
4826
4827         if (!test_PrinterInfo(tctx, p, handle)) {
4828                 ret = false;
4829         }
4830
4831         if (!test_SetPrinter_errors(tctx, p, handle)) {
4832                 ret = false;
4833         }
4834
4835         return ret;
4836 }
4837
4838 static bool test_EnumPrinterKey(struct torture_context *tctx,
4839                                 struct dcerpc_pipe *p,
4840                                 struct policy_handle *handle,
4841                                 const char *key_name,
4842                                 const char ***array)
4843 {
4844         struct spoolss_EnumPrinterKey r;
4845         uint32_t needed = 0;
4846         union spoolss_KeyNames key_buffer;
4847         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4848         uint32_t _ndr_size;
4849         int i;
4850
4851         r.in.handle = handle;
4852         r.in.key_name = key_name;
4853         r.out.key_buffer = &key_buffer;
4854         r.out.needed = &needed;
4855         r.out._ndr_size = &_ndr_size;
4856
4857         for (i=0; i < ARRAY_SIZE(offered); i++) {
4858
4859                 if (offered[i] < 0 && needed) {
4860                         if (needed <= 4) {
4861                                 continue;
4862                         }
4863                         r.in.offered = needed + offered[i];
4864                 } else {
4865                         r.in.offered = offered[i];
4866                 }
4867
4868                 ZERO_STRUCT(key_buffer);
4869
4870                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4871
4872                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4873                         "failed to call EnumPrinterKey");
4874                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4875
4876                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
4877                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4878                                         _ndr_size, r.in.offered/2));
4879
4880                         r.in.offered = needed;
4881                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4882                                 "failed to call EnumPrinterKey");
4883                 }
4884
4885                 if (offered[i] > 0) {
4886                         torture_assert_werr_ok(tctx, r.out.result,
4887                                 "failed to call EnumPrinterKey");
4888                 }
4889
4890                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4891                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4892                                 _ndr_size, r.in.offered/2));
4893
4894                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4895                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4896
4897                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4898                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4899
4900                 if (key_buffer.string_array) {
4901                         uint32_t calc_needed = 0;
4902                         int s;
4903                         for (s=0; key_buffer.string_array[s]; s++) {
4904                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4905                         }
4906                         if (!key_buffer.string_array[0]) {
4907                                 calc_needed += 2;
4908                         }
4909                         calc_needed += 2;
4910
4911                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4912                                 "EnumPrinterKey unexpected size");
4913                 }
4914         }
4915
4916         if (array) {
4917                 *array = key_buffer.string_array;
4918         }
4919
4920         return true;
4921 }
4922
4923 bool test_printer_keys(struct torture_context *tctx,
4924                        struct dcerpc_pipe *p,
4925                        struct policy_handle *handle)
4926 {
4927         const char **key_array = NULL;
4928         int i;
4929
4930         torture_comment(tctx, "\nTesting Printer Keys\n");
4931
4932         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4933                 "failed to call test_EnumPrinterKey");
4934
4935         for (i=0; key_array && key_array[i]; i++) {
4936                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4937                         "failed to call test_EnumPrinterKey");
4938         }
4939         for (i=0; key_array && key_array[i]; i++) {
4940                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i], NULL, NULL),
4941                         "failed to call test_EnumPrinterDataEx");
4942         }
4943
4944         return true;
4945 }
4946
4947 static bool test_one_printer(struct torture_context *tctx,
4948                              struct dcerpc_pipe *p,
4949                              struct policy_handle *handle,
4950                              const char *name)
4951 {
4952         bool ret = true;
4953
4954         if (!test_printer_info(tctx, p, handle)) {
4955                 ret = false;
4956         }
4957
4958         if (!test_PrinterInfo_SD(tctx, p, handle)) {
4959                 ret = false;
4960         }
4961
4962         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
4963                 ret = false;
4964         }
4965
4966         if (!test_ChangeID(tctx, p, handle)) {
4967                 ret = false;
4968         }
4969
4970         if (!test_printer_keys(tctx, p, handle)) {
4971                 ret = false;
4972         }
4973
4974         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
4975                 ret = false;
4976         }
4977
4978         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
4979                 ret = false;
4980         }
4981
4982         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
4983                 ret = false;
4984         }
4985
4986         return ret;
4987 }
4988
4989 static bool test_printer(struct torture_context *tctx,
4990                          struct dcerpc_pipe *p)
4991 {
4992         bool ret = true;
4993         struct policy_handle handle[2];
4994         bool found = false;
4995         const char *drivername = "Microsoft XPS Document Writer";
4996         const char *portname = "LPT1:";
4997
4998         /* test printer created via AddPrinter */
4999
5000         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5001                 return false;
5002         }
5003
5004         if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5005                 ret = false;
5006         }
5007
5008         if (!test_DeletePrinter(tctx, p, &handle[0])) {
5009                 ret = false;
5010         }
5011
5012         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5013                                         TORTURE_PRINTER, &found)) {
5014                 ret = false;
5015         }
5016
5017         torture_assert(tctx, !found, "deleted printer still there");
5018
5019         /* test printer created via AddPrinterEx */
5020
5021         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5022                 return false;
5023         }
5024
5025         if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5026                 ret = false;
5027         }
5028
5029         if (!test_DeletePrinter(tctx, p, &handle[1])) {
5030                 ret = false;
5031         }
5032
5033         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5034                                         TORTURE_PRINTER_EX, &found)) {
5035                 ret = false;
5036         }
5037
5038         torture_assert(tctx, !found, "deleted printer still there");
5039
5040         return ret;
5041 }
5042
5043 static bool test_architecture_buffer(struct torture_context *tctx,
5044                                      struct dcerpc_pipe *p)
5045 {
5046         struct spoolss_OpenPrinterEx r;
5047         struct spoolss_UserLevel1 u1;
5048         struct policy_handle handle;
5049         uint32_t architectures[] = {
5050                 PROCESSOR_ARCHITECTURE_INTEL,
5051                 PROCESSOR_ARCHITECTURE_IA64,
5052                 PROCESSOR_ARCHITECTURE_AMD64
5053         };
5054         uint32_t needed[3];
5055         int i;
5056
5057         for (i=0; i < ARRAY_SIZE(architectures); i++) {
5058
5059                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5060
5061                 u1.size = 0;
5062                 u1.client = NULL;
5063                 u1.user = NULL;
5064                 u1.build = 0;
5065                 u1.major = 3;
5066                 u1.minor = 0;
5067                 u1.processor = architectures[i];
5068
5069                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5070                 r.in.datatype           = NULL;
5071                 r.in.devmode_ctr.devmode= NULL;
5072                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5073                 r.in.level               = 1;
5074                 r.in.userlevel.level1   = &u1;
5075                 r.out.handle            = &handle;
5076
5077                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
5078                 torture_assert_werr_ok(tctx, r.out.result, "");
5079
5080                 {
5081                         struct spoolss_EnumPrinters e;
5082                         uint32_t count;
5083                         union spoolss_PrinterInfo *info;
5084
5085                         e.in.flags = PRINTER_ENUM_LOCAL;
5086                         e.in.server = NULL;
5087                         e.in.level = 2;
5088                         e.in.buffer = NULL;
5089                         e.in.offered = 0;
5090                         e.out.count = &count;
5091                         e.out.info = &info;
5092                         e.out.needed = &needed[i];
5093
5094                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
5095 #if 0
5096                         torture_comment(tctx, "needed was %d\n", needed[i]);
5097 #endif
5098                 }
5099
5100                 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
5101         }
5102
5103         for (i=1; i < ARRAY_SIZE(architectures); i++) {
5104                 if (needed[i-1] != needed[i]) {
5105                         torture_fail(tctx,
5106                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5107                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5108                 }
5109         }
5110
5111         return true;
5112 }
5113
5114 bool torture_rpc_spoolss(struct torture_context *torture)
5115 {
5116         NTSTATUS status;
5117         struct dcerpc_pipe *p;
5118         bool ret = true;
5119         struct test_spoolss_context *ctx;
5120         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5121
5122         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5123         if (!NT_STATUS_IS_OK(status)) {
5124                 return false;
5125         }
5126
5127         ctx = talloc_zero(torture, struct test_spoolss_context);
5128
5129         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5130         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5131         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
5132         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
5133         ret &= test_EnumPorts(torture, p, ctx);
5134         ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
5135         ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
5136         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5137         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5138         ret &= test_EnumMonitors(torture, p, ctx);
5139         ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
5140         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
5141         ret &= test_EnumPrinters(torture, p, ctx);
5142         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
5143         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
5144         ret &= test_OpenPrinter_badname(torture, p, "");
5145         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
5146         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
5147         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5148         ret &= test_OpenPrinter_badname(torture, p,
5149                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5150
5151
5152         ret &= test_AddPort(torture, p);
5153         ret &= test_EnumPorts_old(torture, p);
5154         ret &= test_EnumPrinters_old(torture, p, environment);
5155         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5156         ret &= test_architecture_buffer(torture, p);
5157
5158         return ret;
5159 }
5160
5161 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5162 {
5163         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5164
5165         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5166                                                         "printer", &ndr_table_spoolss);
5167
5168         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
5169
5170         return suite;
5171 }