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