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