s4-smbtorture: add some security descriptor tests to RPC-SPOOLSS and RPC-SPOOLSS...
[abartlet/samba.git/.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_SetPrinter r;
1582         struct spoolss_SetPrinterInfoCtr info_ctr;
1583         struct spoolss_DevmodeContainer devmode_ctr;
1584         struct sec_desc_buf secdesc_ctr;
1585
1586         ZERO_STRUCT(devmode_ctr);
1587         ZERO_STRUCT(secdesc_ctr);
1588
1589         switch (level) {
1590         case 2: {
1591                 union spoolss_PrinterInfo info;
1592                 struct spoolss_SetPrinterInfo2 info2;
1593                 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1594
1595                 info2.servername        = info.info2.servername;
1596                 info2.printername       = info.info2.printername;
1597                 info2.sharename         = info.info2.sharename;
1598                 info2.portname          = info.info2.portname;
1599                 info2.drivername        = info.info2.drivername;
1600                 info2.comment           = info.info2.comment;
1601                 info2.location          = info.info2.location;
1602                 info2.devmode_ptr       = 0;
1603                 info2.sepfile           = info.info2.sepfile;
1604                 info2.printprocessor    = info.info2.printprocessor;
1605                 info2.datatype          = info.info2.datatype;
1606                 info2.parameters        = info.info2.parameters;
1607                 info2.secdesc_ptr       = 0;
1608                 info2.attributes        = info.info2.attributes;
1609                 info2.priority          = info.info2.priority;
1610                 info2.defaultpriority   = info.info2.defaultpriority;
1611                 info2.starttime         = info.info2.starttime;
1612                 info2.untiltime         = info.info2.untiltime;
1613                 info2.status            = info.info2.status;
1614                 info2.cjobs             = info.info2.cjobs;
1615                 info2.averageppm        = info.info2.averageppm;
1616
1617                 info_ctr.level = 2;
1618                 info_ctr.info.info2 = &info2;
1619
1620                 break;
1621         }
1622         case 3: {
1623                 struct spoolss_SetPrinterInfo3 info3;
1624
1625                 info3.sec_desc_ptr = 0;
1626
1627                 info_ctr.level = 3;
1628                 info_ctr.info.info3 = &info3;
1629
1630                 break;
1631         }
1632         default:
1633                 return false;
1634         }
1635
1636         secdesc_ctr.sd = sd;
1637
1638         r.in.handle = handle;
1639         r.in.info_ctr = &info_ctr;
1640         r.in.devmode_ctr = &devmode_ctr;
1641         r.in.secdesc_ctr = &secdesc_ctr;
1642         r.in.command = 0;
1643
1644         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r), "SetPrinter failed");
1645         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1646
1647         return true;
1648 }
1649
1650 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1651                                  struct dcerpc_pipe *p,
1652                                  struct policy_handle *handle)
1653 {
1654         union spoolss_PrinterInfo info;
1655         union spoolss_PrinterInfo info_2;
1656         struct security_descriptor *sd1, *sd2;
1657         int i;
1658
1659         /* level 2 */
1660
1661         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1662
1663         sd1 = security_descriptor_copy(tctx, info.info2.secdesc);
1664
1665         torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1666
1667         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info_2), "");
1668
1669         sd2 = security_descriptor_copy(tctx, info_2.info2.secdesc);
1670
1671         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1672                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED from 1st for comparison\n");
1673                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1674         }
1675
1676         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1677
1678         /* level 3 */
1679
1680         sd1 = sd2;
1681
1682         for (i=0; i < 93; i++) {
1683                 struct security_ace a;
1684                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1685                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1686                 a.flags = 0;
1687                 a.size = 0; /* autogenerated */
1688                 a.access_mask = 0;
1689                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1690                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1691         }
1692
1693         torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1694
1695         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info_2), "");
1696         sd2 = security_descriptor_copy(tctx, info_2.info2.secdesc);
1697
1698         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1699
1700         return true;
1701 }
1702
1703 /*
1704  * wrapper call that saves original sd, runs tests, and restores sd
1705  */
1706
1707 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1708                                 struct dcerpc_pipe *p,
1709                                 struct policy_handle *handle)
1710 {
1711         union spoolss_PrinterInfo info;
1712         struct spoolss_SetPrinter r;
1713         struct spoolss_SetPrinterInfo3 info3;
1714         struct spoolss_SetPrinterInfoCtr info_ctr;
1715         struct spoolss_DevmodeContainer devmode_ctr;
1716         struct sec_desc_buf secdesc_ctr;
1717         struct security_descriptor *sd;
1718         bool ret = true;
1719
1720         /* save original sd */
1721
1722         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1723
1724         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1725
1726         /* run tests */
1727
1728         ret = test_PrinterInfo_SDs(tctx, p, handle);
1729
1730         /* restore original sd */
1731
1732         ZERO_STRUCT(devmode_ctr);
1733         ZERO_STRUCT(secdesc_ctr);
1734
1735         info3.sec_desc_ptr = 0;
1736
1737         info_ctr.level = 3;
1738         info_ctr.info.info3 = &info3;
1739
1740         secdesc_ctr.sd = sd;
1741
1742         r.in.handle = handle;
1743         r.in.info_ctr = &info_ctr;
1744         r.in.devmode_ctr = &devmode_ctr;
1745         r.in.secdesc_ctr = &secdesc_ctr;
1746         r.in.command = 0;
1747
1748         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r), "SetPrinter failed");
1749         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1750
1751         return ret;
1752 }
1753
1754 static bool test_ClosePrinter(struct torture_context *tctx,
1755                               struct dcerpc_pipe *p,
1756                               struct policy_handle *handle)
1757 {
1758         NTSTATUS status;
1759         struct spoolss_ClosePrinter r;
1760
1761         r.in.handle = handle;
1762         r.out.handle = handle;
1763
1764         torture_comment(tctx, "Testing ClosePrinter\n");
1765
1766         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1767         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1768         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1769
1770         return true;
1771 }
1772
1773 static bool test_GetForm(struct torture_context *tctx,
1774                          struct dcerpc_pipe *p,
1775                          struct policy_handle *handle,
1776                          const char *form_name,
1777                          uint32_t level)
1778 {
1779         NTSTATUS status;
1780         struct spoolss_GetForm r;
1781         uint32_t needed;
1782
1783         r.in.handle = handle;
1784         r.in.form_name = form_name;
1785         r.in.level = level;
1786         r.in.buffer = NULL;
1787         r.in.offered = 0;
1788         r.out.needed = &needed;
1789
1790         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1791
1792         status = dcerpc_spoolss_GetForm(p, tctx, &r);
1793         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1794
1795         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1796                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1797                 data_blob_clear(&blob);
1798                 r.in.buffer = &blob;
1799                 r.in.offered = needed;
1800                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1801                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1802
1803                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1804
1805                 torture_assert(tctx, r.out.info, "No form info returned");
1806         }
1807
1808         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1809
1810         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1811
1812         return true;
1813 }
1814
1815 static bool test_EnumForms(struct torture_context *tctx,
1816                            struct dcerpc_pipe *p,
1817                            struct policy_handle *handle, bool print_server)
1818 {
1819         NTSTATUS status;
1820         struct spoolss_EnumForms r;
1821         bool ret = true;
1822         uint32_t needed;
1823         uint32_t count;
1824         uint32_t levels[] = { 1, 2 };
1825         int i;
1826
1827         for (i=0; i<ARRAY_SIZE(levels); i++) {
1828
1829                 union spoolss_FormInfo *info;
1830
1831                 r.in.handle = handle;
1832                 r.in.level = levels[i];
1833                 r.in.buffer = NULL;
1834                 r.in.offered = 0;
1835                 r.out.needed = &needed;
1836                 r.out.count = &count;
1837                 r.out.info = &info;
1838
1839                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1840
1841                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1842                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1843
1844                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1845                         break;
1846                 }
1847
1848                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1849                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1850
1851                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1852                         int j;
1853                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1854                         data_blob_clear(&blob);
1855                         r.in.buffer = &blob;
1856                         r.in.offered = needed;
1857
1858                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1859
1860                         torture_assert(tctx, info, "No forms returned");
1861
1862                         for (j = 0; j < count; j++) {
1863                                 if (!print_server)
1864                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1865                         }
1866                 }
1867
1868                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1869
1870                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1871
1872                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1873         }
1874
1875         return true;
1876 }
1877
1878 static bool test_DeleteForm(struct torture_context *tctx,
1879                             struct dcerpc_pipe *p,
1880                             struct policy_handle *handle,
1881                             const char *form_name)
1882 {
1883         NTSTATUS status;
1884         struct spoolss_DeleteForm r;
1885
1886         r.in.handle = handle;
1887         r.in.form_name = form_name;
1888
1889         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1890
1891         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1892
1893         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1894
1895         return true;
1896 }
1897
1898 static bool test_AddForm(struct torture_context *tctx,
1899                          struct dcerpc_pipe *p,
1900                          struct policy_handle *handle, bool print_server)
1901 {
1902         struct spoolss_AddForm r;
1903         struct spoolss_AddFormInfo1 addform;
1904         const char *form_name = "testform3";
1905         NTSTATUS status;
1906         bool ret = true;
1907
1908         r.in.handle     = handle;
1909         r.in.level      = 1;
1910         r.in.info.info1 = &addform;
1911         addform.flags           = SPOOLSS_FORM_USER;
1912         addform.form_name       = form_name;
1913         addform.size.width      = 50;
1914         addform.size.height     = 25;
1915         addform.area.left       = 5;
1916         addform.area.top        = 10;
1917         addform.area.right      = 45;
1918         addform.area.bottom     = 15;
1919
1920         status = dcerpc_spoolss_AddForm(p, tctx, &r);
1921
1922         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1923
1924         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1925
1926         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1927
1928         {
1929                 struct spoolss_SetForm sf;
1930                 struct spoolss_AddFormInfo1 setform;
1931
1932                 sf.in.handle    = handle;
1933                 sf.in.form_name = form_name;
1934                 sf.in.level     = 1;
1935                 sf.in.info.info1= &setform;
1936                 setform.flags           = addform.flags;
1937                 setform.form_name       = addform.form_name;
1938                 setform.size            = addform.size;
1939                 setform.area            = addform.area;
1940
1941                 setform.size.width      = 1234;
1942
1943                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1944
1945                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1946
1947                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1948         }
1949
1950         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1951
1952         {
1953                 struct spoolss_EnumForms e;
1954                 union spoolss_FormInfo *info;
1955                 uint32_t needed;
1956                 uint32_t count;
1957                 bool found = false;
1958
1959                 e.in.handle = handle;
1960                 e.in.level = 1;
1961                 e.in.buffer = NULL;
1962                 e.in.offered = 0;
1963                 e.out.needed = &needed;
1964                 e.out.count = &count;
1965                 e.out.info = &info;
1966
1967                 torture_comment(tctx, "Testing EnumForms level 1\n");
1968
1969                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1970                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1971
1972                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1973                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1974
1975                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1976                         int j;
1977                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1978                         data_blob_clear(&blob);
1979                         e.in.buffer = &blob;
1980                         e.in.offered = needed;
1981
1982                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1983
1984                         torture_assert(tctx, info, "No forms returned");
1985
1986                         for (j = 0; j < count; j++) {
1987                                 if (strequal(form_name, info[j].info1.form_name)) {
1988                                         found = true;
1989                                         break;
1990                                 }
1991                         }
1992                 }
1993                 torture_assert(tctx, found, "Newly added form not found in enum call");
1994         }
1995
1996         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1997                 ret = false;
1998         }
1999
2000         return ret;
2001 }
2002
2003 static bool test_EnumPorts_old(struct torture_context *tctx,
2004                                struct dcerpc_pipe *p)
2005 {
2006         NTSTATUS status;
2007         struct spoolss_EnumPorts r;
2008         uint32_t needed;
2009         uint32_t count;
2010         union spoolss_PortInfo *info;
2011
2012         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2013                                           dcerpc_server_name(p));
2014         r.in.level = 2;
2015         r.in.buffer = NULL;
2016         r.in.offered = 0;
2017         r.out.needed = &needed;
2018         r.out.count = &count;
2019         r.out.info = &info;
2020
2021         torture_comment(tctx, "Testing EnumPorts\n");
2022
2023         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2024
2025         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2026
2027         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2028                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2029                 data_blob_clear(&blob);
2030                 r.in.buffer = &blob;
2031                 r.in.offered = needed;
2032
2033                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2034                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2035                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2036
2037                 torture_assert(tctx, info, "No ports returned");
2038         }
2039
2040         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2041
2042         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2043
2044         return true;
2045 }
2046
2047 static bool test_AddPort(struct torture_context *tctx,
2048                          struct dcerpc_pipe *p)
2049 {
2050         NTSTATUS status;
2051         struct spoolss_AddPort r;
2052
2053         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2054                                            dcerpc_server_name(p));
2055         r.in.unknown = 0;
2056         r.in.monitor_name = "foo";
2057
2058         torture_comment(tctx, "Testing AddPort\n");
2059
2060         status = dcerpc_spoolss_AddPort(p, tctx, &r);
2061
2062         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2063
2064         /* win2k3 returns WERR_NOT_SUPPORTED */
2065
2066 #if 0
2067
2068         if (!W_ERROR_IS_OK(r.out.result)) {
2069                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2070                 return false;
2071         }
2072
2073 #endif
2074
2075         return true;
2076 }
2077
2078 static bool test_GetJob(struct torture_context *tctx,
2079                         struct dcerpc_pipe *p,
2080                         struct policy_handle *handle, uint32_t job_id)
2081 {
2082         NTSTATUS status;
2083         struct spoolss_GetJob r;
2084         union spoolss_JobInfo info;
2085         uint32_t needed;
2086         uint32_t levels[] = {1, 2 /* 3, 4 */};
2087         uint32_t i;
2088
2089         r.in.handle = handle;
2090         r.in.job_id = job_id;
2091         r.in.level = 0;
2092         r.in.buffer = NULL;
2093         r.in.offered = 0;
2094         r.out.needed = &needed;
2095         r.out.info = &info;
2096
2097         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2098
2099         status = dcerpc_spoolss_GetJob(p, tctx, &r);
2100         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2101
2102         for (i = 0; i < ARRAY_SIZE(levels); i++) {
2103
2104                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2105
2106                 needed = 0;
2107
2108                 r.in.level = levels[i];
2109                 r.in.offered = 0;
2110                 r.in.buffer = NULL;
2111
2112                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2113                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2114
2115                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2116                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2117                         data_blob_clear(&blob);
2118                         r.in.buffer = &blob;
2119                         r.in.offered = needed;
2120
2121                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
2122                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2123
2124                 }
2125                 torture_assert(tctx, r.out.info, "No job info returned");
2126                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2127
2128                 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2129         }
2130
2131         return true;
2132 }
2133
2134 static bool test_SetJob(struct torture_context *tctx,
2135                         struct dcerpc_pipe *p,
2136                         struct policy_handle *handle, uint32_t job_id,
2137                         enum spoolss_JobControl command)
2138 {
2139         NTSTATUS status;
2140         struct spoolss_SetJob r;
2141
2142         r.in.handle     = handle;
2143         r.in.job_id     = job_id;
2144         r.in.ctr        = NULL;
2145         r.in.command    = command;
2146
2147         switch (command) {
2148         case SPOOLSS_JOB_CONTROL_PAUSE:
2149                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2150                 break;
2151         case SPOOLSS_JOB_CONTROL_RESUME:
2152                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2153                 break;
2154         case SPOOLSS_JOB_CONTROL_CANCEL:
2155                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2156                 break;
2157         case SPOOLSS_JOB_CONTROL_RESTART:
2158                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2159                 break;
2160         case SPOOLSS_JOB_CONTROL_DELETE:
2161                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2162                 break;
2163         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2164                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2165                 break;
2166         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2167                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2168                 break;
2169         case SPOOLSS_JOB_CONTROL_RETAIN:
2170                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2171                 break;
2172         case SPOOLSS_JOB_CONTROL_RELEASE:
2173                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2174                 break;
2175         default:
2176                 torture_comment(tctx, "Testing SetJob\n");
2177                 break;
2178         }
2179
2180         status = dcerpc_spoolss_SetJob(p, tctx, &r);
2181         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2182         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2183
2184         return true;
2185 }
2186
2187 static bool test_AddJob(struct torture_context *tctx,
2188                         struct dcerpc_pipe *p,
2189                         struct policy_handle *handle)
2190 {
2191         NTSTATUS status;
2192         struct spoolss_AddJob r;
2193         uint32_t needed;
2194
2195         r.in.level = 0;
2196         r.in.handle = handle;
2197         r.in.offered = 0;
2198         r.out.needed = &needed;
2199         r.in.buffer = r.out.buffer = NULL;
2200
2201         torture_comment(tctx, "Testing AddJob\n");
2202
2203         status = dcerpc_spoolss_AddJob(p, tctx, &r);
2204         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2205
2206         r.in.level = 1;
2207
2208         status = dcerpc_spoolss_AddJob(p, tctx, &r);
2209         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2210
2211         return true;
2212 }
2213
2214
2215 static bool test_EnumJobs(struct torture_context *tctx,
2216                           struct dcerpc_pipe *p,
2217                           struct policy_handle *handle)
2218 {
2219         NTSTATUS status;
2220         struct spoolss_EnumJobs r;
2221         uint32_t needed;
2222         uint32_t count;
2223         union spoolss_JobInfo *info;
2224
2225         r.in.handle = handle;
2226         r.in.firstjob = 0;
2227         r.in.numjobs = 0xffffffff;
2228         r.in.level = 1;
2229         r.in.buffer = NULL;
2230         r.in.offered = 0;
2231         r.out.needed = &needed;
2232         r.out.count = &count;
2233         r.out.info = &info;
2234
2235         torture_comment(tctx, "Testing EnumJobs\n");
2236
2237         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2238
2239         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2240
2241         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2242                 int j;
2243                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2244                 data_blob_clear(&blob);
2245                 r.in.buffer = &blob;
2246                 r.in.offered = needed;
2247
2248                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2249
2250                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2251                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2252                 torture_assert(tctx, info, "No jobs returned");
2253
2254                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2255
2256                 for (j = 0; j < count; j++) {
2257
2258                         torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2259                                 "failed to call test_GetJob");
2260
2261                         /* FIXME - gd */
2262                         if (!torture_setting_bool(tctx, "samba3", false)) {
2263                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2264                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2265                         }
2266                 }
2267
2268         } else {
2269                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2270         }
2271
2272         return true;
2273 }
2274
2275 static bool test_DoPrintTest(struct torture_context *tctx,
2276                              struct dcerpc_pipe *p,
2277                              struct policy_handle *handle)
2278 {
2279         bool ret = true;
2280         NTSTATUS status;
2281         struct spoolss_StartDocPrinter s;
2282         struct spoolss_DocumentInfo1 info1;
2283         struct spoolss_StartPagePrinter sp;
2284         struct spoolss_WritePrinter w;
2285         struct spoolss_EndPagePrinter ep;
2286         struct spoolss_EndDocPrinter e;
2287         int i;
2288         uint32_t job_id;
2289         uint32_t num_written;
2290
2291         torture_comment(tctx, "Testing StartDocPrinter\n");
2292
2293         s.in.handle             = handle;
2294         s.in.level              = 1;
2295         s.in.info.info1         = &info1;
2296         s.out.job_id            = &job_id;
2297         info1.document_name     = "TorturePrintJob";
2298         info1.output_file       = NULL;
2299         info1.datatype          = "RAW";
2300
2301         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2302         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2303         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2304
2305         for (i=1; i < 4; i++) {
2306                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2307
2308                 sp.in.handle            = handle;
2309
2310                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2311                 torture_assert_ntstatus_ok(tctx, status,
2312                                            "dcerpc_spoolss_StartPagePrinter failed");
2313                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2314
2315                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2316
2317                 w.in.handle             = handle;
2318                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2319                 w.out.num_written       = &num_written;
2320
2321                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2322                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2323                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2324
2325                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2326
2327                 ep.in.handle            = handle;
2328
2329                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2330                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2331                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2332         }
2333
2334         torture_comment(tctx, "Testing EndDocPrinter\n");
2335
2336         e.in.handle = handle;
2337
2338         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2339         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2340         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2341
2342         ret &= test_AddJob(tctx, p, handle);
2343         ret &= test_EnumJobs(tctx, p, handle);
2344
2345         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2346
2347         return ret;
2348 }
2349
2350 static bool test_PausePrinter(struct torture_context *tctx,
2351                               struct dcerpc_pipe *p,
2352                               struct policy_handle *handle)
2353 {
2354         NTSTATUS status;
2355         struct spoolss_SetPrinter r;
2356         struct spoolss_SetPrinterInfoCtr info_ctr;
2357         struct spoolss_DevmodeContainer devmode_ctr;
2358         struct sec_desc_buf secdesc_ctr;
2359
2360         info_ctr.level = 0;
2361         info_ctr.info.info0 = NULL;
2362
2363         ZERO_STRUCT(devmode_ctr);
2364         ZERO_STRUCT(secdesc_ctr);
2365
2366         r.in.handle             = handle;
2367         r.in.info_ctr           = &info_ctr;
2368         r.in.devmode_ctr        = &devmode_ctr;
2369         r.in.secdesc_ctr        = &secdesc_ctr;
2370         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
2371
2372         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2373
2374         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2375
2376         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2377
2378         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2379
2380         return true;
2381 }
2382
2383 static bool test_ResumePrinter(struct torture_context *tctx,
2384                                struct dcerpc_pipe *p,
2385                                struct policy_handle *handle)
2386 {
2387         NTSTATUS status;
2388         struct spoolss_SetPrinter r;
2389         struct spoolss_SetPrinterInfoCtr info_ctr;
2390         struct spoolss_DevmodeContainer devmode_ctr;
2391         struct sec_desc_buf secdesc_ctr;
2392
2393         info_ctr.level = 0;
2394         info_ctr.info.info0 = NULL;
2395
2396         ZERO_STRUCT(devmode_ctr);
2397         ZERO_STRUCT(secdesc_ctr);
2398
2399         r.in.handle             = handle;
2400         r.in.info_ctr           = &info_ctr;
2401         r.in.devmode_ctr        = &devmode_ctr;
2402         r.in.secdesc_ctr        = &secdesc_ctr;
2403         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
2404
2405         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2406
2407         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2408
2409         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2410
2411         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2412
2413         return true;
2414 }
2415
2416 static bool test_GetPrinterData(struct torture_context *tctx,
2417                                 struct dcerpc_pipe *p,
2418                                 struct policy_handle *handle,
2419                                 const char *value_name,
2420                                 enum winreg_Type *type_p,
2421                                 union spoolss_PrinterData *data_p)
2422 {
2423         NTSTATUS status;
2424         struct spoolss_GetPrinterData r;
2425         uint32_t needed;
2426         enum winreg_Type type;
2427         union spoolss_PrinterData data;
2428
2429         r.in.handle = handle;
2430         r.in.value_name = value_name;
2431         r.in.offered = 0;
2432         r.out.needed = &needed;
2433         r.out.type = &type;
2434         r.out.data = &data;
2435
2436         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2437
2438         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2439         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2440
2441         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2442                 r.in.offered = needed;
2443
2444                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2445                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2446         }
2447
2448         torture_assert_werr_ok(tctx, r.out.result,
2449                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2450
2451         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2452
2453         if (type_p) {
2454                 *type_p = type;
2455         }
2456
2457         if (data_p) {
2458                 *data_p = data;
2459         }
2460
2461         return true;
2462 }
2463
2464 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2465                                   struct dcerpc_pipe *p,
2466                                   struct policy_handle *handle,
2467                                   const char *key_name,
2468                                   const char *value_name,
2469                                   enum winreg_Type *type_p,
2470                                   union spoolss_PrinterData *data_p)
2471 {
2472         NTSTATUS status;
2473         struct spoolss_GetPrinterDataEx r;
2474         enum winreg_Type type;
2475         uint32_t needed;
2476         union spoolss_PrinterData data;
2477
2478         r.in.handle = handle;
2479         r.in.key_name = key_name;
2480         r.in.value_name = value_name;
2481         r.in.offered = 0;
2482         r.out.type = &type;
2483         r.out.needed = &needed;
2484         r.out.data = &data;
2485
2486         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2487                 r.in.key_name, r.in.value_name);
2488
2489         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2490         if (!NT_STATUS_IS_OK(status)) {
2491                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2492                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2493                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2494                 }
2495                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2496         }
2497
2498         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2499                 r.in.offered = needed;
2500                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2501                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2502         }
2503
2504         torture_assert_werr_ok(tctx, r.out.result,
2505                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2506
2507         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2508
2509         if (type_p) {
2510                 *type_p = type;
2511         }
2512
2513         if (data_p) {
2514                 *data_p = data;
2515         }
2516
2517         return true;
2518 }
2519
2520 static bool test_GetPrinterData_list(struct torture_context *tctx,
2521                                      struct dcerpc_pipe *p,
2522                                      struct policy_handle *handle)
2523 {
2524         const char *list[] = {
2525                 "W3SvcInstalled",
2526                 "BeepEnabled",
2527                 "EventLog",
2528                 /* "NetPopup", not on w2k8 */
2529                 /* "NetPopupToComputer", not on w2k8 */
2530                 "MajorVersion",
2531                 "MinorVersion",
2532                 "DefaultSpoolDirectory",
2533                 "Architecture",
2534                 "DsPresent",
2535                 "OSVersion",
2536                 /* "OSVersionEx", not on s3 */
2537                 "DNSMachineName"
2538         };
2539         int i;
2540
2541         for (i=0; i < ARRAY_SIZE(list); i++) {
2542                 enum winreg_Type type, type_ex;
2543                 union spoolss_PrinterData data, data_ex;
2544
2545                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2546                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2547                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2548                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2549                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2550                 switch (type) {
2551                 case REG_SZ:
2552                         torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2553                         break;
2554                 case REG_DWORD:
2555                         torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2556                         break;
2557                 case REG_BINARY:
2558                         torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2559                         break;
2560                 default:
2561                         break;
2562                 }
2563         }
2564
2565         return true;
2566 }
2567
2568 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2569                                  struct policy_handle *handle)
2570 {
2571         NTSTATUS status;
2572         struct spoolss_EnumPrinterData r;
2573
2574         ZERO_STRUCT(r);
2575         r.in.handle = handle;
2576         r.in.enum_index = 0;
2577
2578         do {
2579                 uint32_t value_size = 0;
2580                 uint32_t data_size = 0;
2581                 enum winreg_Type type = 0;
2582
2583                 r.in.value_offered = value_size;
2584                 r.out.value_needed = &value_size;
2585                 r.in.data_offered = data_size;
2586                 r.out.data_needed = &data_size;
2587
2588                 r.out.type = &type;
2589                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2590
2591                 torture_comment(tctx, "Testing EnumPrinterData\n");
2592
2593                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2594
2595                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2596                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2597                         break;
2598                 }
2599                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2600
2601                 r.in.value_offered = value_size;
2602                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2603                 r.in.data_offered = data_size;
2604                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2605
2606                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2607
2608                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2609                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2610                         break;
2611                 }
2612
2613                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2614
2615                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2616                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2617
2618                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2619                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2620
2621                 r.in.enum_index++;
2622
2623         } while (W_ERROR_IS_OK(r.out.result));
2624
2625         return true;
2626 }
2627
2628 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2629                                    struct dcerpc_pipe *p,
2630                                    struct policy_handle *handle,
2631                                    const char *key_name)
2632 {
2633         struct spoolss_EnumPrinterDataEx r;
2634         struct spoolss_PrinterEnumValues *info;
2635         uint32_t needed;
2636         uint32_t count;
2637
2638         r.in.handle = handle;
2639         r.in.key_name = key_name;
2640         r.in.offered = 0;
2641         r.out.needed = &needed;
2642         r.out.count = &count;
2643         r.out.info = &info;
2644
2645         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2646
2647         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2648                 "EnumPrinterDataEx failed");
2649         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2650                 r.in.offered = needed;
2651                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2652                         "EnumPrinterDataEx failed");
2653         }
2654
2655         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2656
2657         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2658
2659         return true;
2660 }
2661
2662
2663 static bool test_DeletePrinterData(struct torture_context *tctx,
2664                                    struct dcerpc_pipe *p,
2665                                    struct policy_handle *handle,
2666                                    const char *value_name)
2667 {
2668         NTSTATUS status;
2669         struct spoolss_DeletePrinterData r;
2670
2671         r.in.handle = handle;
2672         r.in.value_name = value_name;
2673
2674         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2675                 r.in.value_name);
2676
2677         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2678
2679         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2680         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2681
2682         return true;
2683 }
2684
2685 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2686                                      struct dcerpc_pipe *p,
2687                                      struct policy_handle *handle,
2688                                      const char *key_name,
2689                                      const char *value_name)
2690 {
2691         struct spoolss_DeletePrinterDataEx r;
2692
2693         r.in.handle = handle;
2694         r.in.key_name = key_name;
2695         r.in.value_name = value_name;
2696
2697         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2698                 r.in.key_name, r.in.value_name);
2699
2700         torture_assert_ntstatus_ok(tctx,
2701                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2702                 "DeletePrinterDataEx failed");
2703         torture_assert_werr_ok(tctx, r.out.result,
2704                 "DeletePrinterDataEx failed");
2705
2706         return true;
2707 }
2708
2709 static bool test_DeletePrinterKey(struct torture_context *tctx,
2710                                   struct dcerpc_pipe *p,
2711                                   struct policy_handle *handle,
2712                                   const char *key_name)
2713 {
2714         struct spoolss_DeletePrinterKey r;
2715
2716         r.in.handle = handle;
2717         r.in.key_name = key_name;
2718
2719         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2720
2721         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2722                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2723                 return true;
2724         }
2725
2726         torture_assert_ntstatus_ok(tctx,
2727                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2728                 "DeletePrinterKey failed");
2729         torture_assert_werr_ok(tctx, r.out.result,
2730                 "DeletePrinterKey failed");
2731
2732         return true;
2733 }
2734
2735 static bool test_SetPrinterData(struct torture_context *tctx,
2736                                 struct dcerpc_pipe *p,
2737                                 struct policy_handle *handle)
2738 {
2739         NTSTATUS status;
2740         struct spoolss_SetPrinterData r;
2741         const char *values[] = {
2742                 "spootyfoot",
2743                 "spooty\\foot",
2744 #if 0
2745         /* FIXME: not working with s3 atm. */
2746                 "spooty,foot",
2747                 "spooty,fo,ot",
2748 #endif
2749                 "spooty foot",
2750 #if 0
2751         /* FIXME: not working with s3 atm. */
2752                 "spooty\\fo,ot",
2753                 "spooty,fo\\ot"
2754 #endif
2755         };
2756         int i;
2757
2758         for (i=0; i < ARRAY_SIZE(values); i++) {
2759
2760                 enum winreg_Type type;
2761                 union spoolss_PrinterData data;
2762
2763                 r.in.handle = handle;
2764                 r.in.value_name = values[i];
2765                 r.in.type = REG_SZ;
2766                 r.in.data.string = "dog";
2767
2768                 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2769                         r.in.value_name);
2770
2771                 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2772
2773                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2774                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2775
2776                 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2777                         return false;
2778                 }
2779
2780                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2781                 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2782
2783                 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2784                         return false;
2785                 }
2786         }
2787
2788         return true;
2789 }
2790
2791 static bool test_EnumPrinterKey(struct torture_context *tctx,
2792                                 struct dcerpc_pipe *p,
2793                                 struct policy_handle *handle,
2794                                 const char *key_name,
2795                                 const char ***array);
2796
2797 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2798                                   struct dcerpc_pipe *p,
2799                                   struct policy_handle *handle)
2800 {
2801         NTSTATUS status;
2802         struct spoolss_SetPrinterDataEx r;
2803         const char *value_name = "dog";
2804         const char *keys[] = {
2805                 "torturedataex",
2806                 "torture data ex",
2807 #if 0
2808         /* FIXME: not working with s3 atm. */
2809                 "torturedataex_with_subkey\\subkey",
2810                 "torturedataex_with_subkey\\subkey:0",
2811                 "torturedataex_with_subkey\\subkey:1",
2812                 "torturedataex_with_subkey\\subkey\\subsubkey",
2813                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2814                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2815 #endif
2816                 "torture,data",
2817 #if 0
2818         /* FIXME: not working with s3 atm. */
2819
2820                 "torture,data,ex",
2821                 "torture,data\\ex",
2822                 "torture\\data,ex"
2823 #endif
2824         };
2825         int i;
2826         DATA_BLOB blob = data_blob_string_const("catfoobar");
2827
2828
2829         for (i=0; i < ARRAY_SIZE(keys); i++) {
2830
2831                 char *c;
2832                 const char *key;
2833                 enum winreg_Type type;
2834                 const char **subkeys;
2835                 union spoolss_PrinterData data;
2836
2837                 r.in.handle = handle;
2838                 r.in.key_name = keys[i];
2839                 r.in.value_name = value_name;
2840                 r.in.type = REG_BINARY;
2841                 r.in.data.binary = blob;
2842
2843                 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2844
2845                 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2846
2847                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2848                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2849
2850                 key = talloc_strdup(tctx, r.in.key_name);
2851
2852                 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2853                         return false;
2854                 }
2855
2856                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2857                 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2858
2859                 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2860                         return false;
2861                 }
2862
2863                 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2864                         return false;
2865                 }
2866
2867                 c = strchr(key, '\\');
2868                 if (c) {
2869                         int i;
2870
2871                         /* we have subkeys */
2872
2873                         *c = 0;
2874
2875                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2876                                 return false;
2877                         }
2878
2879                         for (i=0; subkeys && subkeys[i]; i++) {
2880
2881                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2882
2883                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2884                                         return false;
2885                                 }
2886                         }
2887
2888                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2889                                 return false;
2890                         }
2891
2892                 } else {
2893                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2894                                 return false;
2895                         }
2896                 }
2897         }
2898
2899         return true;
2900 }
2901
2902 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
2903                                          struct dcerpc_pipe *p,
2904                                          struct policy_handle *handle,
2905                                          uint32_t *change_id)
2906 {
2907         enum winreg_Type type;
2908         union spoolss_PrinterData data;
2909
2910         torture_assert(tctx,
2911                 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data),
2912                 "failed to call GetPrinterData");
2913
2914         torture_assert(tctx, type == REG_DWORD, "unexpected type");
2915
2916         *change_id = data.value;
2917
2918         return true;
2919 }
2920
2921 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
2922                                            struct dcerpc_pipe *p,
2923                                            struct policy_handle *handle,
2924                                            uint32_t *change_id)
2925 {
2926         enum winreg_Type type;
2927         union spoolss_PrinterData data;
2928
2929         torture_assert(tctx,
2930                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data),
2931                 "failed to call GetPrinterData");
2932
2933         torture_assert(tctx, type == REG_DWORD, "unexpected type");
2934
2935         *change_id = data.value;
2936
2937         return true;
2938 }
2939
2940 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
2941                                          struct dcerpc_pipe *p,
2942                                          struct policy_handle *handle,
2943                                          uint32_t *change_id)
2944 {
2945         union spoolss_PrinterInfo info;
2946
2947         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
2948                 "failed to query Printer level 0");
2949
2950         *change_id = info.info0.change_id;
2951
2952         return true;
2953 }
2954
2955 static bool test_ChangeID(struct torture_context *tctx,
2956                           struct dcerpc_pipe *p,
2957                           struct policy_handle *handle)
2958 {
2959         uint32_t change_id, change_id_ex, change_id_info;
2960         uint32_t change_id2, change_id_ex2, change_id_info2;
2961         union spoolss_PrinterInfo info;
2962         const char *comment;
2963
2964
2965         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
2966
2967         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2968                 "failed to query for ChangeID");
2969         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
2970                 "failed to query for ChangeID");
2971         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
2972                 "failed to query for ChangeID");
2973
2974         torture_assert_int_equal(tctx, change_id, change_id_ex,
2975                 "change_ids should all be equal");
2976         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
2977                 "change_ids should all be equal");
2978
2979
2980         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
2981
2982         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2983                 "failed to query for ChangeID");
2984         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
2985                 "failed to query Printer level 2");
2986         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
2987                 "failed to query for ChangeID");
2988         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
2989                 "failed to query for ChangeID");
2990         torture_assert_int_equal(tctx, change_id, change_id_ex,
2991                 "change_id should not have changed");
2992         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
2993                 "change_id should not have changed");
2994
2995
2996         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
2997
2998         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2999                 "failed to query for ChangeID");
3000         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3001                 "failed to query for ChangeID");
3002         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3003                 "failed to query for ChangeID");
3004         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3005                 "failed to query Printer level 2");
3006         comment = talloc_strdup(tctx, info.info2.comment);
3007
3008         {
3009                 struct spoolss_SetPrinterInfoCtr info_ctr;
3010                 struct spoolss_DevmodeContainer devmode_ctr;
3011                 struct sec_desc_buf secdesc_ctr;
3012                 struct spoolss_SetPrinterInfo2 info2;
3013
3014                 ZERO_STRUCT(info_ctr);
3015                 ZERO_STRUCT(devmode_ctr);
3016                 ZERO_STRUCT(secdesc_ctr);
3017
3018                 info2.servername        = info.info2.servername;
3019                 info2.printername       = info.info2.printername;
3020                 info2.sharename         = info.info2.sharename;
3021                 info2.portname          = info.info2.portname;
3022                 info2.drivername        = info.info2.drivername;
3023                 info2.comment           = "torture_comment";
3024                 info2.location          = info.info2.location;
3025                 info2.devmode_ptr       = 0;
3026                 info2.sepfile           = info.info2.sepfile;
3027                 info2.printprocessor    = info.info2.printprocessor;
3028                 info2.datatype          = info.info2.datatype;
3029                 info2.parameters        = info.info2.parameters;
3030                 info2.secdesc_ptr       = 0;
3031                 info2.attributes        = info.info2.attributes;
3032                 info2.priority          = info.info2.priority;
3033                 info2.defaultpriority   = info.info2.defaultpriority;
3034                 info2.starttime         = info.info2.starttime;
3035                 info2.untiltime         = info.info2.untiltime;
3036                 info2.status            = info.info2.status;
3037                 info2.cjobs             = info.info2.cjobs;
3038                 info2.averageppm        = info.info2.averageppm;
3039
3040                 info_ctr.level = 2;
3041                 info_ctr.info.info2 = &info2;
3042
3043                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3044                         "failed to call SetPrinter");
3045
3046                 info2.comment           = comment;
3047
3048                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3049                         "failed to call SetPrinter");
3050
3051         }
3052
3053         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3054                 "failed to query for ChangeID");
3055         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3056                 "failed to query for ChangeID");
3057         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3058                 "failed to query for ChangeID");
3059
3060         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3061                 "change_ids should all be equal");
3062         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3063                 "change_ids should all be equal");
3064
3065         torture_assert(tctx, (change_id < change_id2),
3066                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3067                 change_id2, change_id));
3068         torture_assert(tctx, (change_id_ex < change_id_ex2),
3069                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3070                 change_id_ex2, change_id_ex));
3071         torture_assert(tctx, (change_id_info < change_id_info2),
3072                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3073                 change_id_info2, change_id_info));
3074
3075         return true;
3076 }
3077
3078 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3079                                        struct dcerpc_pipe *p,
3080                                        struct policy_handle *handle)
3081 {
3082         NTSTATUS status;
3083         struct dcerpc_binding *b;
3084         struct dcerpc_pipe *p2;
3085         struct spoolss_ClosePrinter cp;
3086
3087         /* only makes sense on SMB */
3088         if (p->conn->transport.transport != NCACN_NP) {
3089                 return true;
3090         }
3091
3092         torture_comment(tctx, "testing close on secondary pipe\n");
3093
3094         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3095         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3096
3097         status = dcerpc_secondary_connection(p, &p2, b);
3098         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3099
3100         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3101         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3102
3103         cp.in.handle = handle;
3104         cp.out.handle = handle;
3105
3106         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3107         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3108                         "ERROR: Allowed close on secondary connection");
3109
3110         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3111                                  "Unexpected fault code");
3112
3113         talloc_free(p2);
3114
3115         return true;
3116 }
3117
3118 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3119                                      struct dcerpc_pipe *p, const char *name)
3120 {
3121         NTSTATUS status;
3122         struct spoolss_OpenPrinter op;
3123         struct spoolss_OpenPrinterEx opEx;
3124         struct policy_handle handle;
3125         bool ret = true;
3126
3127         op.in.printername       = name;
3128         op.in.datatype          = NULL;
3129         op.in.devmode_ctr.devmode= NULL;
3130         op.in.access_mask       = 0;
3131         op.out.handle           = &handle;
3132
3133         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3134
3135         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3136         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3137         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3138                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3139                         name, win_errstr(op.out.result));
3140         }
3141
3142         if (W_ERROR_IS_OK(op.out.result)) {
3143                 ret &=test_ClosePrinter(tctx, p, &handle);
3144         }
3145
3146         opEx.in.printername             = name;
3147         opEx.in.datatype                = NULL;
3148         opEx.in.devmode_ctr.devmode     = NULL;
3149         opEx.in.access_mask             = 0;
3150         opEx.in.level                   = 1;
3151         opEx.in.userlevel.level1        = NULL;
3152         opEx.out.handle                 = &handle;
3153
3154         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3155
3156         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3157         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3158         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3159                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3160                         name, win_errstr(opEx.out.result));
3161         }
3162
3163         if (W_ERROR_IS_OK(opEx.out.result)) {
3164                 ret &=test_ClosePrinter(tctx, p, &handle);
3165         }
3166
3167         return ret;
3168 }
3169
3170 static bool test_OpenPrinter(struct torture_context *tctx,
3171                              struct dcerpc_pipe *p,
3172                              const char *name)
3173 {
3174         NTSTATUS status;
3175         struct spoolss_OpenPrinter r;
3176         struct policy_handle handle;
3177         bool ret = true;
3178
3179         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3180         r.in.datatype           = NULL;
3181         r.in.devmode_ctr.devmode= NULL;
3182         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
3183         r.out.handle            = &handle;
3184
3185         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3186
3187         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3188
3189         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3190
3191         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3192
3193         if (!test_GetPrinter(tctx, p, &handle)) {
3194                 ret = false;
3195         }
3196
3197         if (!torture_setting_bool(tctx, "samba3", false)) {
3198                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3199                         ret = false;
3200                 }
3201         }
3202
3203         if (!test_ClosePrinter(tctx, p, &handle)) {
3204                 ret = false;
3205         }
3206
3207         return ret;
3208 }
3209
3210 static bool call_OpenPrinterEx(struct torture_context *tctx,
3211                                struct dcerpc_pipe *p,
3212                                const char *name, struct policy_handle *handle)
3213 {
3214         struct spoolss_OpenPrinterEx r;
3215         struct spoolss_UserLevel1 userlevel1;
3216         NTSTATUS status;
3217
3218         if (name && name[0]) {
3219                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3220                                                    dcerpc_server_name(p), name);
3221         } else {
3222                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3223                                                    dcerpc_server_name(p));
3224         }
3225
3226         r.in.datatype           = NULL;
3227         r.in.devmode_ctr.devmode= NULL;
3228         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
3229         r.in.level              = 1;
3230         r.in.userlevel.level1   = &userlevel1;
3231         r.out.handle = handle;
3232
3233         userlevel1.size = 1234;
3234         userlevel1.client = "hello";
3235         userlevel1.user = "spottyfoot!";
3236         userlevel1.build = 1;
3237         userlevel1.major = 2;
3238         userlevel1.minor = 3;
3239         userlevel1.processor = 4;
3240
3241         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3242
3243         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3244
3245         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3246
3247         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3248
3249         return true;
3250 }
3251
3252 static bool test_OpenPrinterEx(struct torture_context *tctx,
3253                                struct dcerpc_pipe *p,
3254                                const char *name)
3255 {
3256         struct policy_handle handle;
3257         bool ret = true;
3258
3259         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
3260                 return false;
3261         }
3262
3263         if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3264                 ret = false;
3265         }
3266
3267         if (!test_GetPrinter(tctx, p, &handle)) {
3268                 ret = false;
3269         }
3270
3271         if (!test_EnumForms(tctx, p, &handle, false)) {
3272                 ret = false;
3273         }
3274
3275         if (!test_AddForm(tctx, p, &handle, false)) {
3276                 ret = false;
3277         }
3278
3279         if (!test_EnumPrinterData(tctx, p, &handle)) {
3280                 ret = false;
3281         }
3282
3283         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3284                 ret = false;
3285         }
3286
3287         if (!test_printer_keys(tctx, p, &handle)) {
3288                 ret = false;
3289         }
3290
3291         if (!test_PausePrinter(tctx, p, &handle)) {
3292                 ret = false;
3293         }
3294
3295         if (!test_DoPrintTest(tctx, p, &handle)) {
3296                 ret = false;
3297         }
3298
3299         if (!test_ResumePrinter(tctx, p, &handle)) {
3300                 ret = false;
3301         }
3302
3303         if (!test_SetPrinterData(tctx, p, &handle)) {
3304                 ret = false;
3305         }
3306
3307         if (!test_SetPrinterDataEx(tctx, p, &handle)) {
3308                 ret = false;
3309         }
3310
3311         if (!test_ChangeID(tctx, p, &handle)) {
3312                 ret = false;
3313         }
3314
3315         if (!torture_setting_bool(tctx, "samba3", false)) {
3316                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3317                         ret = false;
3318                 }
3319         }
3320
3321         if (!test_ClosePrinter(tctx, p, &handle)) {
3322                 ret = false;
3323         }
3324
3325         return ret;
3326 }
3327
3328 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
3329 {
3330         struct spoolss_EnumPrinters r;
3331         NTSTATUS status;
3332         uint16_t levels[] = {1, 2, 4, 5};
3333         int i;
3334         bool ret = true;
3335
3336         for (i=0;i<ARRAY_SIZE(levels);i++) {
3337                 union spoolss_PrinterInfo *info;
3338                 int j;
3339                 uint32_t needed;
3340                 uint32_t count;
3341
3342                 r.in.flags      = PRINTER_ENUM_LOCAL;
3343                 r.in.server     = "";
3344                 r.in.level      = levels[i];
3345                 r.in.buffer     = NULL;
3346                 r.in.offered    = 0;
3347                 r.out.needed    = &needed;
3348                 r.out.count     = &count;
3349                 r.out.info      = &info;
3350
3351                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
3352
3353                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3354                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3355
3356                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3357                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3358                         data_blob_clear(&blob);
3359                         r.in.buffer = &blob;
3360                         r.in.offered = needed;
3361                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3362                 }
3363
3364                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3365
3366                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
3367
3368                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3369
3370                 if (!info) {
3371                         torture_comment(tctx, "No printers returned\n");
3372                         return true;
3373                 }
3374
3375                 for (j=0;j<count;j++) {
3376                         if (r.in.level == 1) {
3377                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
3378                                 char *slash, *name;
3379                                 name = unc;
3380                                 if (unc[0] == '\\' && unc[1] == '\\') {
3381                                         unc +=2;
3382                                 }
3383                                 slash = strchr(unc, '\\');
3384                                 if (slash) {
3385                                         slash++;
3386                                         name = slash;
3387                                 }
3388                                 if (!test_OpenPrinter(tctx, p, name)) {
3389                                         ret = false;
3390                                 }
3391                                 if (!test_OpenPrinterEx(tctx, p, name)) {
3392                                         ret = false;
3393                                 }
3394                         }
3395                 }
3396         }
3397
3398         return ret;
3399 }
3400
3401 static bool test_GetPrinterDriver(struct torture_context *tctx,
3402                                   struct dcerpc_pipe *p,
3403                                   struct policy_handle *handle,
3404                                   const char *driver_name)
3405 {
3406         struct spoolss_GetPrinterDriver r;
3407         uint32_t needed;
3408
3409         r.in.handle = handle;
3410         r.in.architecture = "W32X86";
3411         r.in.level = 1;
3412         r.in.buffer = NULL;
3413         r.in.offered = 0;
3414         r.out.needed = &needed;
3415
3416         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
3417
3418         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3419                 "failed to call GetPrinterDriver");
3420         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3421                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3422                 data_blob_clear(&blob);
3423                 r.in.buffer = &blob;
3424                 r.in.offered = needed;
3425                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3426                         "failed to call GetPrinterDriver");
3427         }
3428
3429         torture_assert_werr_ok(tctx, r.out.result,
3430                 "failed to call GetPrinterDriver");
3431
3432         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3433
3434         return true;
3435 }
3436
3437 static bool test_GetPrinterDriver2(struct torture_context *tctx,
3438                                    struct dcerpc_pipe *p,
3439                                    struct policy_handle *handle,
3440                                    const char *driver_name)
3441 {
3442         struct spoolss_GetPrinterDriver2 r;
3443         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
3444         uint32_t needed;
3445         uint32_t server_major_version;
3446         uint32_t server_minor_version;
3447         int i;
3448
3449         r.in.handle = handle;
3450         r.in.architecture = SPOOLSS_ARCHITECTURE_NT_X86;
3451         r.in.client_major_version = 3;
3452         r.in.client_minor_version = 0;
3453         r.out.needed = &needed;
3454         r.out.server_major_version = &server_major_version;
3455         r.out.server_minor_version = &server_minor_version;
3456
3457         for (i=0;i<ARRAY_SIZE(levels);i++) {
3458
3459                 r.in.buffer = NULL;
3460                 r.in.offered = 0;
3461                 r.in.level = levels[i];
3462
3463                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3464                         driver_name, r.in.level);
3465
3466                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3467                         "failed to call GetPrinterDriver2");
3468                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3469                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3470                         data_blob_clear(&blob);
3471                         r.in.buffer = &blob;
3472                         r.in.offered = needed;
3473                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3474                                 "failed to call GetPrinterDriver2");
3475                 }
3476
3477                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3478                         switch (r.in.level) {
3479                         case 101:
3480                         case 8:
3481                                 continue;
3482                         default:
3483                                 break;
3484                         }
3485                 }
3486
3487                 torture_assert_werr_ok(tctx, r.out.result,
3488                         "failed to call GetPrinterDriver2");
3489
3490                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3491         }
3492
3493         return true;
3494 }
3495
3496 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3497                                         struct dcerpc_pipe *p)
3498 {
3499         struct spoolss_EnumPrinterDrivers r;
3500         NTSTATUS status;
3501         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3502         int i;
3503
3504         for (i=0;i<ARRAY_SIZE(levels);i++) {
3505
3506                 uint32_t needed;
3507                 uint32_t count;
3508                 union spoolss_DriverInfo *info;
3509
3510                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3511                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3512                 r.in.level = levels[i];
3513                 r.in.buffer = NULL;
3514                 r.in.offered = 0;
3515                 r.out.needed = &needed;
3516                 r.out.count = &count;
3517                 r.out.info = &info;
3518
3519                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3520
3521                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3522
3523                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3524
3525                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3526                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3527                         data_blob_clear(&blob);
3528                         r.in.buffer = &blob;
3529                         r.in.offered = needed;
3530                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3531                 }
3532
3533                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3534
3535                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3536
3537                 if (!info) {
3538                         torture_comment(tctx, "No printer drivers returned\n");
3539                         break;
3540                 }
3541
3542                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3543         }
3544
3545         return true;
3546 }
3547
3548 static bool test_DeletePrinter(struct torture_context *tctx,
3549                                struct dcerpc_pipe *p,
3550                                struct policy_handle *handle)
3551 {
3552         struct spoolss_DeletePrinter r;
3553
3554         torture_comment(tctx, "Testing DeletePrinter\n");
3555
3556         r.in.handle = handle;
3557
3558         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3559                 "failed to delete printer");
3560         torture_assert_werr_ok(tctx, r.out.result,
3561                 "failed to delete printer");
3562
3563         return true;
3564 }
3565
3566 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3567                                        struct dcerpc_pipe *p,
3568                                        uint32_t flags,
3569                                        uint32_t level,
3570                                        const char *name,
3571                                        bool *found)
3572 {
3573         struct spoolss_EnumPrinters e;
3574         uint32_t count;
3575         union spoolss_PrinterInfo *info;
3576         uint32_t needed;
3577         int i;
3578
3579         *found = false;
3580
3581         e.in.flags = flags;
3582         e.in.server = NULL;
3583         e.in.level = level;
3584         e.in.buffer = NULL;
3585         e.in.offered = 0;
3586         e.out.count = &count;
3587         e.out.info = &info;
3588         e.out.needed = &needed;
3589
3590         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3591                 "failed to enum printers");
3592
3593         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3594                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3595                 data_blob_clear(&blob);
3596                 e.in.buffer = &blob;
3597                 e.in.offered = needed;
3598
3599                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3600                         "failed to enum printers");
3601         }
3602
3603         torture_assert_werr_ok(tctx, e.out.result,
3604                 "failed to enum printers");
3605
3606         for (i=0; i < count; i++) {
3607
3608                 const char *current = NULL;
3609
3610                 switch (level) {
3611                 case 1:
3612                         current = info[i].info1.name;
3613                         break;
3614                 }
3615
3616                 if (strequal(current, name)) {
3617                         *found = true;
3618                         break;
3619                 }
3620         }
3621
3622         return true;
3623 }
3624
3625 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3626                                       struct dcerpc_pipe *p,
3627                                       const char *printername,
3628                                       bool ex)
3629 {
3630         WERROR result;
3631         struct spoolss_AddPrinter r;
3632         struct spoolss_AddPrinterEx rex;
3633         struct spoolss_SetPrinterInfoCtr info_ctr;
3634         struct spoolss_SetPrinterInfo1 info1;
3635         struct spoolss_DevmodeContainer devmode_ctr;
3636         struct sec_desc_buf secdesc_ctr;
3637         struct spoolss_UserLevelCtr userlevel_ctr;
3638         struct policy_handle handle;
3639         bool found = false;
3640
3641         ZERO_STRUCT(devmode_ctr);
3642         ZERO_STRUCT(secdesc_ctr);
3643         ZERO_STRUCT(userlevel_ctr);
3644         ZERO_STRUCT(info1);
3645
3646         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3647
3648         /* try to add printer to wellknown printer list (level 1) */
3649
3650         userlevel_ctr.level = 1;
3651
3652         info_ctr.info.info1 = &info1;
3653         info_ctr.level = 1;
3654
3655         rex.in.server = NULL;
3656         rex.in.info_ctr = &info_ctr;
3657         rex.in.devmode_ctr = &devmode_ctr;
3658         rex.in.secdesc_ctr = &secdesc_ctr;
3659         rex.in.userlevel_ctr = &userlevel_ctr;
3660         rex.out.handle = &handle;
3661
3662         r.in.server = NULL;
3663         r.in.info_ctr = &info_ctr;
3664         r.in.devmode_ctr = &devmode_ctr;
3665         r.in.secdesc_ctr = &secdesc_ctr;
3666         r.out.handle = &handle;
3667
3668         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3669                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3670                 "failed to add printer");
3671         result = ex ? rex.out.result : r.out.result;
3672         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3673                 "unexpected result code");
3674
3675         info1.name = printername;
3676         info1.flags = PRINTER_ATTRIBUTE_SHARED;
3677
3678         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3679                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3680                 "failed to add printer");
3681         result = ex ? rex.out.result : r.out.result;
3682         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3683                 "unexpected result code");
3684
3685         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3686            better do a real check to see the printer is really there */
3687
3688         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3689                                                         PRINTER_ENUM_NETWORK, 1,
3690                                                         printername,
3691                                                         &found),
3692                         "failed to enum printers");
3693
3694         torture_assert(tctx, found, "failed to find newly added printer");
3695
3696         info1.flags = 0;
3697
3698         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3699                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3700                 "failed to add printer");
3701         result = ex ? rex.out.result : r.out.result;
3702         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3703                 "unexpected result code");
3704
3705         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3706            better do a real check to see the printer has really been removed
3707            from the well known printer list */
3708
3709         found = false;
3710
3711         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3712                                                         PRINTER_ENUM_NETWORK, 1,
3713                                                         printername,
3714                                                         &found),
3715                         "failed to enum printers");
3716 #if 0
3717         torture_assert(tctx, !found, "printer still in well known printer list");
3718 #endif
3719         return true;
3720 }
3721
3722 static bool test_AddPrinter_normal(struct torture_context *tctx,
3723                                    struct dcerpc_pipe *p,
3724                                    struct policy_handle *handle_p,
3725                                    const char *printername,
3726                                    const char *drivername,
3727                                    const char *portname,
3728                                    bool ex)
3729 {
3730         WERROR result;
3731         struct spoolss_AddPrinter r;
3732         struct spoolss_AddPrinterEx rex;
3733         struct spoolss_SetPrinterInfoCtr info_ctr;
3734         struct spoolss_SetPrinterInfo2 info2;
3735         struct spoolss_DevmodeContainer devmode_ctr;
3736         struct sec_desc_buf secdesc_ctr;
3737         struct spoolss_UserLevelCtr userlevel_ctr;
3738         struct policy_handle handle;
3739         bool found = false;
3740
3741         ZERO_STRUCT(devmode_ctr);
3742         ZERO_STRUCT(secdesc_ctr);
3743         ZERO_STRUCT(userlevel_ctr);
3744
3745         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3746
3747         userlevel_ctr.level = 1;
3748
3749         rex.in.server = NULL;
3750         rex.in.info_ctr = &info_ctr;
3751         rex.in.devmode_ctr = &devmode_ctr;
3752         rex.in.secdesc_ctr = &secdesc_ctr;
3753         rex.in.userlevel_ctr = &userlevel_ctr;
3754         rex.out.handle = &handle;
3755
3756         r.in.server = NULL;
3757         r.in.info_ctr = &info_ctr;
3758         r.in.devmode_ctr = &devmode_ctr;
3759         r.in.secdesc_ctr = &secdesc_ctr;
3760         r.out.handle = &handle;
3761
3762  again:
3763
3764         /* try to add printer to printer list (level 2) */
3765
3766         ZERO_STRUCT(info2);
3767
3768         info_ctr.info.info2 = &info2;
3769         info_ctr.level = 2;
3770
3771         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3772                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3773                 "failed to add printer");
3774         result = ex ? rex.out.result : r.out.result;
3775         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3776                 "unexpected result code");
3777
3778         info2.printername = printername;
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
3785         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3786                 struct policy_handle printer_handle;
3787
3788                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3789                         "failed to open printer handle");
3790
3791                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3792                         "failed to delete printer");
3793
3794                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3795                         "failed to close server handle");
3796
3797                 goto again;
3798         }
3799
3800         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3801                 "unexpected result code");
3802
3803         info2.portname = portname;
3804
3805         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3806                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3807                 "failed to add printer");
3808         result = ex ? rex.out.result : r.out.result;
3809         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3810                 "unexpected result code");
3811
3812         info2.drivername = drivername;
3813
3814         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3815                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3816                 "failed to add printer");
3817         result = ex ? rex.out.result : r.out.result;
3818         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3819                 "unexpected result code");
3820
3821         info2.printprocessor = "winprint";
3822
3823         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3824                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3825                 "failed to add printer");
3826         result = ex ? rex.out.result : r.out.result;
3827         torture_assert_werr_ok(tctx, result,
3828                 "failed to add printer");
3829
3830         *handle_p = handle;
3831
3832         /* we are paranoid, really check if the printer is there now */
3833
3834         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3835                                                         PRINTER_ENUM_LOCAL, 1,
3836                                                         printername,
3837                                                         &found),
3838                         "failed to enum printers");
3839         torture_assert(tctx, found, "failed to find newly added printer");
3840
3841         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3842                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3843                 "failed to add printer");
3844         result = ex ? rex.out.result : r.out.result;
3845         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3846                 "unexpected result code");
3847
3848         return true;
3849 }
3850
3851 static bool test_AddPrinterEx(struct torture_context *tctx,
3852                               struct dcerpc_pipe *p,
3853                               struct policy_handle *handle_p,
3854                               const char *printername,
3855                               const char *drivername,
3856                               const char *portname)
3857 {
3858         bool ret = true;
3859
3860         if (!torture_setting_bool(tctx, "samba3", false)) {
3861                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3862                         torture_comment(tctx, "failed to add printer to well known list\n");
3863                         ret = false;
3864                 }
3865         }
3866
3867         if (!test_AddPrinter_normal(tctx, p, handle_p,
3868                                     printername, drivername, portname,
3869                                     true)) {
3870                 torture_comment(tctx, "failed to add printer to printer list\n");
3871                 ret = false;
3872         }
3873
3874         return ret;
3875 }
3876
3877 static bool test_AddPrinter(struct torture_context *tctx,
3878                             struct dcerpc_pipe *p,
3879                             struct policy_handle *handle_p,
3880                             const char *printername,
3881                             const char *drivername,
3882                             const char *portname)
3883 {
3884         bool ret = true;
3885
3886         if (!torture_setting_bool(tctx, "samba3", false)) {
3887                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3888                         torture_comment(tctx, "failed to add printer to well known list\n");
3889                         ret = false;
3890                 }
3891         }
3892
3893         if (!test_AddPrinter_normal(tctx, p, handle_p,
3894                                     printername, drivername, portname,
3895                                     false)) {
3896                 torture_comment(tctx, "failed to add printer to printer list\n");
3897                 ret = false;
3898         }
3899
3900         return ret;
3901 }
3902
3903 static bool test_printer_info(struct torture_context *tctx,
3904                               struct dcerpc_pipe *p,
3905                               struct policy_handle *handle)
3906 {
3907         bool ret = true;
3908
3909         if (!test_PrinterInfo(tctx, p, handle)) {
3910                 ret = false;
3911         }
3912
3913         if (!test_SetPrinter_errors(tctx, p, handle)) {
3914                 ret = false;
3915         }
3916
3917         return ret;
3918 }
3919
3920 static bool test_EnumPrinterKey(struct torture_context *tctx,
3921                                 struct dcerpc_pipe *p,
3922                                 struct policy_handle *handle,
3923                                 const char *key_name,
3924                                 const char ***array)
3925 {
3926         struct spoolss_EnumPrinterKey r;
3927         uint32_t needed = 0;
3928         union spoolss_KeyNames key_buffer;
3929         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
3930         uint32_t _ndr_size;
3931         int i;
3932
3933         r.in.handle = handle;
3934         r.in.key_name = key_name;
3935         r.out.key_buffer = &key_buffer;
3936         r.out.needed = &needed;
3937         r.out._ndr_size = &_ndr_size;
3938
3939         for (i=0; i < ARRAY_SIZE(offered); i++) {
3940
3941                 if (offered[i] < 0 && needed) {
3942                         if (needed <= 4) {
3943                                 continue;
3944                         }
3945                         r.in.offered = needed + offered[i];
3946                 } else {
3947                         r.in.offered = offered[i];
3948                 }
3949
3950                 ZERO_STRUCT(key_buffer);
3951
3952                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
3953
3954                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3955                         "failed to call EnumPrinterKey");
3956                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3957
3958                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
3959                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3960                                         _ndr_size, r.in.offered/2));
3961
3962                         r.in.offered = needed;
3963                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3964                                 "failed to call EnumPrinterKey");
3965                 }
3966
3967                 if (offered[i] > 0) {
3968                         torture_assert_werr_ok(tctx, r.out.result,
3969                                 "failed to call EnumPrinterKey");
3970                 }
3971
3972                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
3973                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3974                                 _ndr_size, r.in.offered/2));
3975
3976                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
3977                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
3978
3979                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
3980                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
3981
3982                 if (key_buffer.string_array) {
3983                         uint32_t calc_needed = 0;
3984                         int s;
3985                         for (s=0; key_buffer.string_array[s]; s++) {
3986                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
3987                         }
3988                         if (!key_buffer.string_array[0]) {
3989                                 calc_needed += 2;
3990                         }
3991                         calc_needed += 2;
3992
3993                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
3994                                 "EnumPrinterKey unexpected size");
3995                 }
3996         }
3997
3998         if (array) {
3999                 *array = key_buffer.string_array;
4000         }
4001
4002         return true;
4003 }
4004
4005 bool test_printer_keys(struct torture_context *tctx,
4006                        struct dcerpc_pipe *p,
4007                        struct policy_handle *handle)
4008 {
4009         const char **key_array = NULL;
4010         int i;
4011
4012         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4013                 "failed to call test_EnumPrinterKey");
4014
4015         for (i=0; key_array && key_array[i]; i++) {
4016                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4017                         "failed to call test_EnumPrinterKey");
4018         }
4019         for (i=0; key_array && key_array[i]; i++) {
4020                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
4021                         "failed to call test_EnumPrinterDataEx");
4022         }
4023
4024         return true;
4025 }
4026
4027 static bool test_printer(struct torture_context *tctx,
4028                          struct dcerpc_pipe *p)
4029 {
4030         bool ret = true;
4031         struct policy_handle handle[2];
4032         bool found = false;
4033         const char *drivername = "Microsoft XPS Document Writer";
4034         const char *portname = "LPT1:";
4035
4036         /* test printer created via AddPrinter */
4037
4038         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4039                 return false;
4040         }
4041
4042         if (!test_printer_info(tctx, p, &handle[0])) {
4043                 ret = false;
4044         }
4045
4046         if (!test_PrinterInfo_SD(tctx, p, &handle[0])) {
4047                 ret = false;
4048         }
4049
4050         if (!test_printer_keys(tctx, p, &handle[0])) {
4051                 ret = false;
4052         }
4053
4054         if (!test_DeletePrinter(tctx, p, &handle[0])) {
4055                 ret = false;
4056         }
4057
4058         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4059                                         TORTURE_PRINTER, &found)) {
4060                 ret = false;
4061         }
4062
4063         torture_assert(tctx, !found, "deleted printer still there");
4064
4065         /* test printer created via AddPrinterEx */
4066
4067         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4068                 return false;
4069         }
4070
4071         if (!test_printer_info(tctx, p, &handle[1])) {
4072                 ret = false;
4073         }
4074
4075         if (!test_printer_keys(tctx, p, &handle[1])) {
4076                 ret = false;
4077         }
4078
4079         if (!test_DeletePrinter(tctx, p, &handle[1])) {
4080                 ret = false;
4081         }
4082
4083         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4084                                         TORTURE_PRINTER_EX, &found)) {
4085                 ret = false;
4086         }
4087
4088         torture_assert(tctx, !found, "deleted printer still there");
4089
4090         return ret;
4091 }
4092
4093 bool torture_rpc_spoolss(struct torture_context *torture)
4094 {
4095         NTSTATUS status;
4096         struct dcerpc_pipe *p;
4097         bool ret = true;
4098         struct test_spoolss_context *ctx;
4099
4100         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4101         if (!NT_STATUS_IS_OK(status)) {
4102                 return false;
4103         }
4104
4105         ctx = talloc_zero(torture, struct test_spoolss_context);
4106
4107         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4108         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4109         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4110         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4111         ret &= test_EnumPorts(torture, p, ctx);
4112         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
4113         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
4114         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
4115         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4116         ret &= test_EnumMonitors(torture, p, ctx);
4117         ret &= test_EnumPrintProcessors(torture, p, ctx);
4118         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4119         ret &= test_EnumPrinters(torture, p, ctx);
4120         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4121         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4122         ret &= test_OpenPrinter_badname(torture, p, "");
4123         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4124         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4125         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4126         ret &= test_OpenPrinter_badname(torture, p,
4127                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4128
4129
4130         ret &= test_AddPort(torture, p);
4131         ret &= test_EnumPorts_old(torture, p);
4132         ret &= test_EnumPrinters_old(torture, p);
4133         ret &= test_EnumPrinterDrivers_old(torture, p);
4134
4135         return ret;
4136 }
4137
4138 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4139 {
4140         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4141
4142         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4143                                                         "printer", &ndr_table_spoolss);
4144
4145         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
4146
4147         return suite;
4148 }