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