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