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