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