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