91364541d0c88a179a46484f4a7d8e9165d204b0
[kai/samba.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
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(struct torture_context *tctx,
869                             struct dcerpc_pipe *p,
870                      struct policy_handle *handle)
871 {
872         NTSTATUS status;
873         struct spoolss_GetPrinter r;
874         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
875         int i;
876         uint32_t needed;
877
878         for (i=0;i<ARRAY_SIZE(levels);i++) {
879                 r.in.handle = handle;
880                 r.in.level = levels[i];
881                 r.in.buffer = NULL;
882                 r.in.offered = 0;
883                 r.out.needed = &needed;
884
885                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
886
887                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
888                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
889
890                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
891                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
892                         data_blob_clear(&blob);
893                         r.in.buffer = &blob;
894                         r.in.offered = needed;
895                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
896                 }
897
898                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
899
900                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
901
902                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
903
904                 if ((r.in.level == 2) && r.out.info->info2.drivername && strlen(r.out.info->info2.drivername)) {
905                         torture_assert(tctx,
906                                 test_GetPrinterDriver2(tctx, p, handle, r.out.info->info2.drivername),
907                                 "failed to call test_GetPrinterDriver2");
908                 }
909         }
910
911         return true;
912 }
913
914 static bool test_SetPrinter_errors(struct torture_context *tctx,
915                                    struct dcerpc_pipe *p,
916                                    struct policy_handle *handle)
917 {
918         struct spoolss_SetPrinter r;
919         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
920         int i;
921
922         struct spoolss_SetPrinterInfoCtr info_ctr;
923         struct spoolss_DevmodeContainer devmode_ctr;
924         struct sec_desc_buf secdesc_ctr;
925
926         info_ctr.level = 0;
927         info_ctr.info.info0 = NULL;
928
929         ZERO_STRUCT(devmode_ctr);
930         ZERO_STRUCT(secdesc_ctr);
931
932         r.in.handle = handle;
933         r.in.info_ctr = &info_ctr;
934         r.in.devmode_ctr = &devmode_ctr;
935         r.in.secdesc_ctr = &secdesc_ctr;
936         r.in.command = 0;
937
938         torture_comment(tctx, "Testing SetPrinter all zero\n");
939
940         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
941                 "failed to call SetPrinter");
942         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
943                 "failed to call SetPrinter");
944
945  again:
946         for (i=0; i < ARRAY_SIZE(levels); i++) {
947
948                 struct spoolss_SetPrinterInfo0 info0;
949                 struct spoolss_SetPrinterInfo1 info1;
950                 struct spoolss_SetPrinterInfo2 info2;
951                 struct spoolss_SetPrinterInfo3 info3;
952                 struct spoolss_SetPrinterInfo4 info4;
953                 struct spoolss_SetPrinterInfo5 info5;
954                 struct spoolss_SetPrinterInfo6 info6;
955                 struct spoolss_SetPrinterInfo7 info7;
956                 struct spoolss_DeviceModeInfo info8;
957                 struct spoolss_DeviceModeInfo info9;
958
959
960                 info_ctr.level = levels[i];
961                 switch (levels[i]) {
962                 case 0:
963                         ZERO_STRUCT(info0);
964                         info_ctr.info.info0 = &info0;
965                         break;
966                 case 1:
967                         ZERO_STRUCT(info1);
968                         info_ctr.info.info1 = &info1;
969                         break;
970                 case 2:
971                         ZERO_STRUCT(info2);
972                         info_ctr.info.info2 = &info2;
973                         break;
974                 case 3:
975                         ZERO_STRUCT(info3);
976                         info_ctr.info.info3 = &info3;
977                         break;
978                 case 4:
979                         ZERO_STRUCT(info4);
980                         info_ctr.info.info4 = &info4;
981                         break;
982                 case 5:
983                         ZERO_STRUCT(info5);
984                         info_ctr.info.info5 = &info5;
985                         break;
986                 case 6:
987                         ZERO_STRUCT(info6);
988                         info_ctr.info.info6 = &info6;
989                         break;
990                 case 7:
991                         ZERO_STRUCT(info7);
992                         info_ctr.info.info7 = &info7;
993                         break;
994                 case 8:
995                         ZERO_STRUCT(info8);
996                         info_ctr.info.info8 = &info8;
997                         break;
998                 case 9:
999                         ZERO_STRUCT(info9);
1000                         info_ctr.info.info9 = &info9;
1001                         break;
1002                 }
1003
1004                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1005                         info_ctr.level, r.in.command);
1006
1007                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1008                         "failed to call SetPrinter");
1009
1010                 switch (r.in.command) {
1011                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1012                         /* is ignored for all levels other then 0 */
1013                         if (info_ctr.level > 0) {
1014                                 /* ignored then */
1015                                 break;
1016                         }
1017                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1018                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1019                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1020                         if (info_ctr.level > 0) {
1021                                 /* is invalid for all levels other then 0 */
1022                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1023                                         "unexpected error code returned");
1024                                 continue;
1025                         } else {
1026                                 torture_assert_werr_ok(tctx, r.out.result,
1027                                         "failed to call SetPrinter with non 0 command");
1028                                 continue;
1029                         }
1030                         break;
1031
1032                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1033                         /* FIXME: gd needs further investigation */
1034                 default:
1035                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1036                                 "unexpected error code returned");
1037                         continue;
1038                 }
1039
1040                 switch (info_ctr.level) {
1041                 case 1:
1042                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1043                                 "unexpected error code returned");
1044                         break;
1045                 case 2:
1046                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1047                                 "unexpected error code returned");
1048                         break;
1049                 case 3:
1050                 case 4:
1051                 case 5:
1052                 case 7:
1053                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1054                                 "unexpected error code returned");
1055                         break;
1056                 case 9:
1057                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1058                                 "unexpected error code returned");
1059                         break;
1060                 default:
1061                         torture_assert_werr_ok(tctx, r.out.result,
1062                                 "failed to call SetPrinter");
1063                         break;
1064                 }
1065         }
1066
1067         if (r.in.command < 5) {
1068                 r.in.command++;
1069                 goto again;
1070         }
1071
1072         return true;
1073 }
1074
1075 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1076 {
1077         if ((r->level == 2) && (r->info.info2)) {
1078                 r->info.info2->secdesc = NULL;
1079                 r->info.info2->devmode = NULL;
1080         }
1081 }
1082
1083 static bool test_PrinterInfo(struct torture_context *tctx,
1084                              struct dcerpc_pipe *p,
1085                              struct policy_handle *handle)
1086 {
1087         NTSTATUS status;
1088         struct spoolss_SetPrinter s;
1089         struct spoolss_GetPrinter q;
1090         struct spoolss_GetPrinter q0;
1091         struct spoolss_SetPrinterInfoCtr info_ctr;
1092         union spoolss_PrinterInfo info;
1093         struct spoolss_DevmodeContainer devmode_ctr;
1094         struct sec_desc_buf secdesc_ctr;
1095         uint32_t needed;
1096         bool ret = true;
1097         int i;
1098
1099         uint32_t status_list[] = {
1100                 /* these do not stick
1101                 PRINTER_STATUS_PAUSED,
1102                 PRINTER_STATUS_ERROR,
1103                 PRINTER_STATUS_PENDING_DELETION, */
1104                 PRINTER_STATUS_PAPER_JAM,
1105                 PRINTER_STATUS_PAPER_OUT,
1106                 PRINTER_STATUS_MANUAL_FEED,
1107                 PRINTER_STATUS_PAPER_PROBLEM,
1108                 PRINTER_STATUS_OFFLINE,
1109                 PRINTER_STATUS_IO_ACTIVE,
1110                 PRINTER_STATUS_BUSY,
1111                 PRINTER_STATUS_PRINTING,
1112                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1113                 PRINTER_STATUS_NOT_AVAILABLE,
1114                 PRINTER_STATUS_WAITING,
1115                 PRINTER_STATUS_PROCESSING,
1116                 PRINTER_STATUS_INITIALIZING,
1117                 PRINTER_STATUS_WARMING_UP,
1118                 PRINTER_STATUS_TONER_LOW,
1119                 PRINTER_STATUS_NO_TONER,
1120                 PRINTER_STATUS_PAGE_PUNT,
1121                 PRINTER_STATUS_USER_INTERVENTION,
1122                 PRINTER_STATUS_OUT_OF_MEMORY,
1123                 PRINTER_STATUS_DOOR_OPEN,
1124                 PRINTER_STATUS_SERVER_UNKNOWN,
1125                 PRINTER_STATUS_POWER_SAVE,
1126                 /* these do not stick
1127                 0x02000000,
1128                 0x04000000,
1129                 0x08000000,
1130                 0x10000000,
1131                 0x20000000,
1132                 0x40000000,
1133                 0x80000000 */
1134         };
1135         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1136         uint32_t attribute_list[] = {
1137                 PRINTER_ATTRIBUTE_QUEUED,
1138                 /* fails with WERR_INVALID_DATATYPE:
1139                 PRINTER_ATTRIBUTE_DIRECT, */
1140                 /* does not stick
1141                 PRINTER_ATTRIBUTE_DEFAULT, */
1142                 PRINTER_ATTRIBUTE_SHARED,
1143                 /* does not stick
1144                 PRINTER_ATTRIBUTE_NETWORK, */
1145                 PRINTER_ATTRIBUTE_HIDDEN,
1146                 PRINTER_ATTRIBUTE_LOCAL,
1147                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1148                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1149                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1150                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1151                 /* does not stick
1152                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1153                 /* fails with WERR_INVALID_DATATYPE:
1154                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1155                 /* these do not stick
1156                 PRINTER_ATTRIBUTE_PUBLISHED,
1157                 PRINTER_ATTRIBUTE_FAX,
1158                 PRINTER_ATTRIBUTE_TS,
1159                 0x00010000,
1160                 0x00020000,
1161                 0x00040000,
1162                 0x00080000,
1163                 0x00100000,
1164                 0x00200000,
1165                 0x00400000,
1166                 0x00800000,
1167                 0x01000000,
1168                 0x02000000,
1169                 0x04000000,
1170                 0x08000000,
1171                 0x10000000,
1172                 0x20000000,
1173                 0x40000000,
1174                 0x80000000 */
1175         };
1176
1177         ZERO_STRUCT(devmode_ctr);
1178         ZERO_STRUCT(secdesc_ctr);
1179
1180         s.in.handle = handle;
1181         s.in.command = 0;
1182         s.in.info_ctr = &info_ctr;
1183         s.in.devmode_ctr = &devmode_ctr;
1184         s.in.secdesc_ctr = &secdesc_ctr;
1185
1186         q.in.handle = handle;
1187         q.out.info = &info;
1188         q0 = q;
1189
1190 #define TESTGETCALL(call, r) \
1191                 r.in.buffer = NULL; \
1192                 r.in.offered = 0;\
1193                 r.out.needed = &needed; \
1194                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1195                 if (!NT_STATUS_IS_OK(status)) { \
1196                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1197                                r.in.level, nt_errstr(status), __location__); \
1198                         ret = false; \
1199                         break; \
1200                 }\
1201                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1202                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1203                         data_blob_clear(&blob); \
1204                         r.in.buffer = &blob; \
1205                         r.in.offered = needed; \
1206                 }\
1207                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1208                 if (!NT_STATUS_IS_OK(status)) { \
1209                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1210                                r.in.level, nt_errstr(status), __location__); \
1211                         ret = false; \
1212                         break; \
1213                 } \
1214                 if (!W_ERROR_IS_OK(r.out.result)) { \
1215                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1216                                r.in.level, win_errstr(r.out.result), __location__); \
1217                         ret = false; \
1218                         break; \
1219                 }
1220
1221
1222 #define TESTSETCALL_EXP(call, r, err) \
1223                 clear_info2(&info_ctr);\
1224                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1225                 if (!NT_STATUS_IS_OK(status)) { \
1226                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1227                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1228                         ret = false; \
1229                         break; \
1230                 } \
1231                 if (!W_ERROR_IS_OK(err)) { \
1232                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1233                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1234                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1235                                 ret = false; \
1236                         } \
1237                         break; \
1238                 } \
1239                 if (!W_ERROR_IS_OK(r.out.result)) { \
1240                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1241                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1242                         ret = false; \
1243                         break; \
1244                 }
1245
1246 #define TESTSETCALL(call, r) \
1247         TESTSETCALL_EXP(call, r, WERR_OK)
1248
1249 #define STRING_EQUAL(s1, s2, field) \
1250                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1251                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1252                                #field, s2, __location__); \
1253                         ret = false; \
1254                         break; \
1255                 }
1256
1257 #define MEM_EQUAL(s1, s2, length, field) \
1258                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1259                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1260                                #field, (const char *)s2, __location__); \
1261                         ret = false; \
1262                         break; \
1263                 }
1264
1265 #define INT_EQUAL(i1, i2, field) \
1266                 if (i1 != i2) { \
1267                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1268                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1269                         ret = false; \
1270                         break; \
1271                 }
1272
1273 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1274                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1275                 q.in.level = lvl1; \
1276                 TESTGETCALL(GetPrinter, q) \
1277                 info_ctr.level = lvl1; \
1278                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1279                 info_ctr.info.info ## lvl1->field1 = value;\
1280                 TESTSETCALL_EXP(SetPrinter, s, err) \
1281                 info_ctr.info.info ## lvl1->field1 = ""; \
1282                 TESTGETCALL(GetPrinter, q) \
1283                 info_ctr.info.info ## lvl1->field1 = value; \
1284                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1285                 q.in.level = lvl2; \
1286                 TESTGETCALL(GetPrinter, q) \
1287                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1288                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1289         } while (0)
1290
1291 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1292         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1293         } while (0);
1294
1295 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) 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(SetPrinter, s) \
1303                 info_ctr.info.info ## lvl1->field1 = 0; \
1304                 TESTGETCALL(GetPrinter, q) \
1305                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1306                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_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                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1311         } while (0)
1312
1313 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1314         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1315         } while (0)
1316
1317         q0.in.level = 0;
1318         do { TESTGETCALL(GetPrinter, q0) } while (0);
1319
1320         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1321         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1322
1323         /* level 0 printername does not stick */
1324 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1325         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1326         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1327         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1328         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1329 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1330         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1331         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1332         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1333         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1334 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1335         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1336         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1337         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1338         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1339
1340         /* servername can be set but does not stick
1341         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1342         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1343         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1344         */
1345
1346         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1347         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1348         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1349         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1350         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1351
1352         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1353         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1354         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1355         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1356         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1357         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1358         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1359         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1360         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1361         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1362
1363         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1364 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1365                         attribute_list[i],
1366                         (attribute_list[i] | default_attribute)
1367                         ); */
1368                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1369                         attribute_list[i],
1370                         (attribute_list[i] | default_attribute)
1371                         );
1372                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1373                         attribute_list[i],
1374                         (attribute_list[i] | default_attribute)
1375                         );
1376                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1377                         attribute_list[i],
1378                         (attribute_list[i] | default_attribute)
1379                         );
1380 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1381                         attribute_list[i],
1382                         (attribute_list[i] | default_attribute)
1383                         ); */
1384                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1385                         attribute_list[i],
1386                         (attribute_list[i] | default_attribute)
1387                         );
1388                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1389                         attribute_list[i],
1390                         (attribute_list[i] | default_attribute)
1391                         );
1392                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1393                         attribute_list[i],
1394                         (attribute_list[i] | default_attribute)
1395                         );
1396 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1397                         attribute_list[i],
1398                         (attribute_list[i] | default_attribute)
1399                         ); */
1400                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1401                         attribute_list[i],
1402                         (attribute_list[i] | default_attribute)
1403                         );
1404                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1405                         attribute_list[i],
1406                         (attribute_list[i] | default_attribute)
1407                         );
1408                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1409                         attribute_list[i],
1410                         (attribute_list[i] | default_attribute)
1411                         );
1412         }
1413
1414         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1415                 /* level 2 sets do not stick
1416                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1417                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1418                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1419                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1420                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1421                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1422         }
1423
1424         /* priorities need to be between 0 and 99
1425            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1426         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1427         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1428         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1429         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1430         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1431         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1432         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1433         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1434
1435         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1436         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1437
1438         /* does not stick
1439         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1440         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1441
1442         /* does not stick
1443         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1444         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1445
1446         /* FIXME: gd also test devmode and secdesc behavior */
1447
1448         {
1449                 /* verify composition of level 1 description field */
1450                 const char *description;
1451                 const char *tmp;
1452
1453                 q0.in.level = 1;
1454                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1455
1456                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1457
1458                 q0.in.level = 2;
1459                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1460
1461                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1462                         q0.out.info->info2.printername,
1463                         q0.out.info->info2.drivername,
1464                         q0.out.info->info2.location);
1465
1466                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1467         }
1468
1469         return ret;
1470 }
1471
1472
1473 static bool test_ClosePrinter(struct torture_context *tctx,
1474                               struct dcerpc_pipe *p,
1475                               struct policy_handle *handle)
1476 {
1477         NTSTATUS status;
1478         struct spoolss_ClosePrinter r;
1479
1480         r.in.handle = handle;
1481         r.out.handle = handle;
1482
1483         torture_comment(tctx, "Testing ClosePrinter\n");
1484
1485         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1486         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1487         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1488
1489         return true;
1490 }
1491
1492 static bool test_GetForm(struct torture_context *tctx,
1493                          struct dcerpc_pipe *p,
1494                          struct policy_handle *handle,
1495                          const char *form_name,
1496                          uint32_t level)
1497 {
1498         NTSTATUS status;
1499         struct spoolss_GetForm r;
1500         uint32_t needed;
1501
1502         r.in.handle = handle;
1503         r.in.form_name = form_name;
1504         r.in.level = level;
1505         r.in.buffer = NULL;
1506         r.in.offered = 0;
1507         r.out.needed = &needed;
1508
1509         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1510
1511         status = dcerpc_spoolss_GetForm(p, tctx, &r);
1512         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1513
1514         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1515                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1516                 data_blob_clear(&blob);
1517                 r.in.buffer = &blob;
1518                 r.in.offered = needed;
1519                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1520                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1521
1522                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1523
1524                 torture_assert(tctx, r.out.info, "No form info returned");
1525         }
1526
1527         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1528
1529         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1530
1531         return true;
1532 }
1533
1534 static bool test_EnumForms(struct torture_context *tctx,
1535                            struct dcerpc_pipe *p,
1536                            struct policy_handle *handle, bool print_server)
1537 {
1538         NTSTATUS status;
1539         struct spoolss_EnumForms r;
1540         bool ret = true;
1541         uint32_t needed;
1542         uint32_t count;
1543         uint32_t levels[] = { 1, 2 };
1544         int i;
1545
1546         for (i=0; i<ARRAY_SIZE(levels); i++) {
1547
1548                 union spoolss_FormInfo *info;
1549
1550                 r.in.handle = handle;
1551                 r.in.level = levels[i];
1552                 r.in.buffer = NULL;
1553                 r.in.offered = 0;
1554                 r.out.needed = &needed;
1555                 r.out.count = &count;
1556                 r.out.info = &info;
1557
1558                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1559
1560                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1561                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1562
1563                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1564                         break;
1565                 }
1566
1567                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1568                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1569
1570                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1571                         int j;
1572                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1573                         data_blob_clear(&blob);
1574                         r.in.buffer = &blob;
1575                         r.in.offered = needed;
1576
1577                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1578
1579                         torture_assert(tctx, info, "No forms returned");
1580
1581                         for (j = 0; j < count; j++) {
1582                                 if (!print_server)
1583                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1584                         }
1585                 }
1586
1587                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1588
1589                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1590
1591                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1592         }
1593
1594         return true;
1595 }
1596
1597 static bool test_DeleteForm(struct torture_context *tctx,
1598                             struct dcerpc_pipe *p,
1599                             struct policy_handle *handle,
1600                             const char *form_name)
1601 {
1602         NTSTATUS status;
1603         struct spoolss_DeleteForm r;
1604
1605         r.in.handle = handle;
1606         r.in.form_name = form_name;
1607
1608         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1609
1610         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1611
1612         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1613
1614         return true;
1615 }
1616
1617 static bool test_AddForm(struct torture_context *tctx,
1618                          struct dcerpc_pipe *p,
1619                          struct policy_handle *handle, bool print_server)
1620 {
1621         struct spoolss_AddForm r;
1622         struct spoolss_AddFormInfo1 addform;
1623         const char *form_name = "testform3";
1624         NTSTATUS status;
1625         bool ret = true;
1626
1627         r.in.handle     = handle;
1628         r.in.level      = 1;
1629         r.in.info.info1 = &addform;
1630         addform.flags           = SPOOLSS_FORM_USER;
1631         addform.form_name       = form_name;
1632         addform.size.width      = 50;
1633         addform.size.height     = 25;
1634         addform.area.left       = 5;
1635         addform.area.top        = 10;
1636         addform.area.right      = 45;
1637         addform.area.bottom     = 15;
1638
1639         status = dcerpc_spoolss_AddForm(p, tctx, &r);
1640
1641         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1642
1643         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1644
1645         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1646
1647         {
1648                 struct spoolss_SetForm sf;
1649                 struct spoolss_AddFormInfo1 setform;
1650
1651                 sf.in.handle    = handle;
1652                 sf.in.form_name = form_name;
1653                 sf.in.level     = 1;
1654                 sf.in.info.info1= &setform;
1655                 setform.flags           = addform.flags;
1656                 setform.form_name       = addform.form_name;
1657                 setform.size            = addform.size;
1658                 setform.area            = addform.area;
1659
1660                 setform.size.width      = 1234;
1661
1662                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1663
1664                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1665
1666                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1667         }
1668
1669         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1670
1671         {
1672                 struct spoolss_EnumForms e;
1673                 union spoolss_FormInfo *info;
1674                 uint32_t needed;
1675                 uint32_t count;
1676                 bool found = false;
1677
1678                 e.in.handle = handle;
1679                 e.in.level = 1;
1680                 e.in.buffer = NULL;
1681                 e.in.offered = 0;
1682                 e.out.needed = &needed;
1683                 e.out.count = &count;
1684                 e.out.info = &info;
1685
1686                 torture_comment(tctx, "Testing EnumForms level 1\n");
1687
1688                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1689                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1690
1691                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1692                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1693
1694                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1695                         int j;
1696                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1697                         data_blob_clear(&blob);
1698                         e.in.buffer = &blob;
1699                         e.in.offered = needed;
1700
1701                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1702
1703                         torture_assert(tctx, info, "No forms returned");
1704
1705                         for (j = 0; j < count; j++) {
1706                                 if (strequal(form_name, info[j].info1.form_name)) {
1707                                         found = true;
1708                                         break;
1709                                 }
1710                         }
1711                 }
1712                 torture_assert(tctx, found, "Newly added form not found in enum call");
1713         }
1714
1715         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1716                 ret = false;
1717         }
1718
1719         return ret;
1720 }
1721
1722 static bool test_EnumPorts_old(struct torture_context *tctx,
1723                                struct dcerpc_pipe *p)
1724 {
1725         NTSTATUS status;
1726         struct spoolss_EnumPorts r;
1727         uint32_t needed;
1728         uint32_t count;
1729         union spoolss_PortInfo *info;
1730
1731         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1732                                           dcerpc_server_name(p));
1733         r.in.level = 2;
1734         r.in.buffer = NULL;
1735         r.in.offered = 0;
1736         r.out.needed = &needed;
1737         r.out.count = &count;
1738         r.out.info = &info;
1739
1740         torture_comment(tctx, "Testing EnumPorts\n");
1741
1742         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1743
1744         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1745
1746         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1747                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1748                 data_blob_clear(&blob);
1749                 r.in.buffer = &blob;
1750                 r.in.offered = needed;
1751
1752                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1753                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1754                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1755
1756                 torture_assert(tctx, info, "No ports returned");
1757         }
1758
1759         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1760
1761         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1762
1763         return true;
1764 }
1765
1766 static bool test_AddPort(struct torture_context *tctx,
1767                          struct dcerpc_pipe *p)
1768 {
1769         NTSTATUS status;
1770         struct spoolss_AddPort r;
1771
1772         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1773                                            dcerpc_server_name(p));
1774         r.in.unknown = 0;
1775         r.in.monitor_name = "foo";
1776
1777         torture_comment(tctx, "Testing AddPort\n");
1778
1779         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1780
1781         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1782
1783         /* win2k3 returns WERR_NOT_SUPPORTED */
1784
1785 #if 0
1786
1787         if (!W_ERROR_IS_OK(r.out.result)) {
1788                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1789                 return false;
1790         }
1791
1792 #endif
1793
1794         return true;
1795 }
1796
1797 static bool test_GetJob(struct torture_context *tctx,
1798                         struct dcerpc_pipe *p,
1799                         struct policy_handle *handle, uint32_t job_id)
1800 {
1801         NTSTATUS status;
1802         struct spoolss_GetJob r;
1803         union spoolss_JobInfo info;
1804         uint32_t needed;
1805         uint32_t levels[] = {1, 2 /* 3, 4 */};
1806         uint32_t i;
1807
1808         r.in.handle = handle;
1809         r.in.job_id = job_id;
1810         r.in.level = 0;
1811         r.in.buffer = NULL;
1812         r.in.offered = 0;
1813         r.out.needed = &needed;
1814         r.out.info = &info;
1815
1816         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1817
1818         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1819         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1820
1821         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1822
1823                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1824
1825                 needed = 0;
1826
1827                 r.in.level = levels[i];
1828                 r.in.offered = 0;
1829                 r.in.buffer = NULL;
1830
1831                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1832                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1833
1834                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1835                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1836                         data_blob_clear(&blob);
1837                         r.in.buffer = &blob;
1838                         r.in.offered = needed;
1839
1840                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1841                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1842
1843                 }
1844                 torture_assert(tctx, r.out.info, "No job info returned");
1845                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1846
1847                 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1848         }
1849
1850         return true;
1851 }
1852
1853 static bool test_SetJob(struct torture_context *tctx,
1854                         struct dcerpc_pipe *p,
1855                         struct policy_handle *handle, uint32_t job_id,
1856                         enum spoolss_JobControl command)
1857 {
1858         NTSTATUS status;
1859         struct spoolss_SetJob r;
1860
1861         r.in.handle     = handle;
1862         r.in.job_id     = job_id;
1863         r.in.ctr        = NULL;
1864         r.in.command    = command;
1865
1866         switch (command) {
1867         case SPOOLSS_JOB_CONTROL_PAUSE:
1868                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1869                 break;
1870         case SPOOLSS_JOB_CONTROL_RESUME:
1871                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1872                 break;
1873         case SPOOLSS_JOB_CONTROL_CANCEL:
1874                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1875                 break;
1876         case SPOOLSS_JOB_CONTROL_RESTART:
1877                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1878                 break;
1879         case SPOOLSS_JOB_CONTROL_DELETE:
1880                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1881                 break;
1882         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1883                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1884                 break;
1885         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1886                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1887                 break;
1888         case SPOOLSS_JOB_CONTROL_RETAIN:
1889                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1890                 break;
1891         case SPOOLSS_JOB_CONTROL_RELEASE:
1892                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1893                 break;
1894         default:
1895                 torture_comment(tctx, "Testing SetJob\n");
1896                 break;
1897         }
1898
1899         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1900         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1901         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1902
1903         return true;
1904 }
1905
1906 static bool test_AddJob(struct torture_context *tctx,
1907                         struct dcerpc_pipe *p,
1908                         struct policy_handle *handle)
1909 {
1910         NTSTATUS status;
1911         struct spoolss_AddJob r;
1912         uint32_t needed;
1913
1914         r.in.level = 0;
1915         r.in.handle = handle;
1916         r.in.offered = 0;
1917         r.out.needed = &needed;
1918         r.in.buffer = r.out.buffer = NULL;
1919
1920         torture_comment(tctx, "Testing AddJob\n");
1921
1922         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1923         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1924
1925         r.in.level = 1;
1926
1927         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1928         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1929
1930         return true;
1931 }
1932
1933
1934 static bool test_EnumJobs(struct torture_context *tctx,
1935                           struct dcerpc_pipe *p,
1936                           struct policy_handle *handle)
1937 {
1938         NTSTATUS status;
1939         struct spoolss_EnumJobs r;
1940         uint32_t needed;
1941         uint32_t count;
1942         union spoolss_JobInfo *info;
1943
1944         r.in.handle = handle;
1945         r.in.firstjob = 0;
1946         r.in.numjobs = 0xffffffff;
1947         r.in.level = 1;
1948         r.in.buffer = NULL;
1949         r.in.offered = 0;
1950         r.out.needed = &needed;
1951         r.out.count = &count;
1952         r.out.info = &info;
1953
1954         torture_comment(tctx, "Testing EnumJobs\n");
1955
1956         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1957
1958         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1959
1960         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1961                 int j;
1962                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1963                 data_blob_clear(&blob);
1964                 r.in.buffer = &blob;
1965                 r.in.offered = needed;
1966
1967                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1968
1969                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1970                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1971                 torture_assert(tctx, info, "No jobs returned");
1972
1973                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1974
1975                 for (j = 0; j < count; j++) {
1976
1977                         torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
1978                                 "failed to call test_GetJob");
1979
1980                         /* FIXME - gd */
1981                         if (!torture_setting_bool(tctx, "samba3", false)) {
1982                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1983                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1984                         }
1985                 }
1986
1987         } else {
1988                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1989         }
1990
1991         return true;
1992 }
1993
1994 static bool test_DoPrintTest(struct torture_context *tctx,
1995                              struct dcerpc_pipe *p,
1996                              struct policy_handle *handle)
1997 {
1998         bool ret = true;
1999         NTSTATUS status;
2000         struct spoolss_StartDocPrinter s;
2001         struct spoolss_DocumentInfo1 info1;
2002         struct spoolss_StartPagePrinter sp;
2003         struct spoolss_WritePrinter w;
2004         struct spoolss_EndPagePrinter ep;
2005         struct spoolss_EndDocPrinter e;
2006         int i;
2007         uint32_t job_id;
2008         uint32_t num_written;
2009
2010         torture_comment(tctx, "Testing StartDocPrinter\n");
2011
2012         s.in.handle             = handle;
2013         s.in.level              = 1;
2014         s.in.info.info1         = &info1;
2015         s.out.job_id            = &job_id;
2016         info1.document_name     = "TorturePrintJob";
2017         info1.output_file       = NULL;
2018         info1.datatype          = "RAW";
2019
2020         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2021         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2022         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2023
2024         for (i=1; i < 4; i++) {
2025                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2026
2027                 sp.in.handle            = handle;
2028
2029                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2030                 torture_assert_ntstatus_ok(tctx, status,
2031                                            "dcerpc_spoolss_StartPagePrinter failed");
2032                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2033
2034                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2035
2036                 w.in.handle             = handle;
2037                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2038                 w.out.num_written       = &num_written;
2039
2040                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2041                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2042                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2043
2044                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2045
2046                 ep.in.handle            = handle;
2047
2048                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2049                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2050                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2051         }
2052
2053         torture_comment(tctx, "Testing EndDocPrinter\n");
2054
2055         e.in.handle = handle;
2056
2057         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2058         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2059         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2060
2061         ret &= test_AddJob(tctx, p, handle);
2062         ret &= test_EnumJobs(tctx, p, handle);
2063
2064         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2065
2066         return ret;
2067 }
2068
2069 static bool test_PausePrinter(struct torture_context *tctx,
2070                               struct dcerpc_pipe *p,
2071                               struct policy_handle *handle)
2072 {
2073         NTSTATUS status;
2074         struct spoolss_SetPrinter r;
2075         struct spoolss_SetPrinterInfoCtr info_ctr;
2076         struct spoolss_DevmodeContainer devmode_ctr;
2077         struct sec_desc_buf secdesc_ctr;
2078
2079         info_ctr.level = 0;
2080         info_ctr.info.info0 = NULL;
2081
2082         ZERO_STRUCT(devmode_ctr);
2083         ZERO_STRUCT(secdesc_ctr);
2084
2085         r.in.handle             = handle;
2086         r.in.info_ctr           = &info_ctr;
2087         r.in.devmode_ctr        = &devmode_ctr;
2088         r.in.secdesc_ctr        = &secdesc_ctr;
2089         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
2090
2091         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2092
2093         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2094
2095         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2096
2097         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2098
2099         return true;
2100 }
2101
2102 static bool test_ResumePrinter(struct torture_context *tctx,
2103                                struct dcerpc_pipe *p,
2104                                struct policy_handle *handle)
2105 {
2106         NTSTATUS status;
2107         struct spoolss_SetPrinter r;
2108         struct spoolss_SetPrinterInfoCtr info_ctr;
2109         struct spoolss_DevmodeContainer devmode_ctr;
2110         struct sec_desc_buf secdesc_ctr;
2111
2112         info_ctr.level = 0;
2113         info_ctr.info.info0 = NULL;
2114
2115         ZERO_STRUCT(devmode_ctr);
2116         ZERO_STRUCT(secdesc_ctr);
2117
2118         r.in.handle             = handle;
2119         r.in.info_ctr           = &info_ctr;
2120         r.in.devmode_ctr        = &devmode_ctr;
2121         r.in.secdesc_ctr        = &secdesc_ctr;
2122         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
2123
2124         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2125
2126         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2127
2128         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2129
2130         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2131
2132         return true;
2133 }
2134
2135 static bool test_GetPrinterData(struct torture_context *tctx,
2136                                 struct dcerpc_pipe *p,
2137                                 struct policy_handle *handle,
2138                                 const char *value_name,
2139                                 enum winreg_Type *type_p,
2140                                 union spoolss_PrinterData *data_p)
2141 {
2142         NTSTATUS status;
2143         struct spoolss_GetPrinterData r;
2144         uint32_t needed;
2145         enum winreg_Type type;
2146         union spoolss_PrinterData data;
2147
2148         r.in.handle = handle;
2149         r.in.value_name = value_name;
2150         r.in.offered = 0;
2151         r.out.needed = &needed;
2152         r.out.type = &type;
2153         r.out.data = &data;
2154
2155         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2156
2157         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2158         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2159
2160         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2161                 r.in.offered = needed;
2162
2163                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2164                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2165         }
2166
2167         torture_assert_werr_ok(tctx, r.out.result,
2168                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2169
2170         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2171
2172         if (type_p) {
2173                 *type_p = type;
2174         }
2175
2176         if (data_p) {
2177                 *data_p = data;
2178         }
2179
2180         return true;
2181 }
2182
2183 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2184                                   struct dcerpc_pipe *p,
2185                                   struct policy_handle *handle,
2186                                   const char *key_name,
2187                                   const char *value_name,
2188                                   enum winreg_Type *type_p,
2189                                   union spoolss_PrinterData *data_p)
2190 {
2191         NTSTATUS status;
2192         struct spoolss_GetPrinterDataEx r;
2193         enum winreg_Type type;
2194         uint32_t needed;
2195         union spoolss_PrinterData data;
2196
2197         r.in.handle = handle;
2198         r.in.key_name = key_name;
2199         r.in.value_name = value_name;
2200         r.in.offered = 0;
2201         r.out.type = &type;
2202         r.out.needed = &needed;
2203         r.out.data = &data;
2204
2205         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2206                 r.in.key_name, r.in.value_name);
2207
2208         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2209         if (!NT_STATUS_IS_OK(status)) {
2210                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2211                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2212                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2213                 }
2214                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2215         }
2216
2217         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2218                 r.in.offered = needed;
2219                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2220                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2221         }
2222
2223         torture_assert_werr_ok(tctx, r.out.result,
2224                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2225
2226         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2227
2228         if (type_p) {
2229                 *type_p = type;
2230         }
2231
2232         if (data_p) {
2233                 *data_p = data;
2234         }
2235
2236         return true;
2237 }
2238
2239 static bool test_GetPrinterData_list(struct torture_context *tctx,
2240                                      struct dcerpc_pipe *p,
2241                                      struct policy_handle *handle)
2242 {
2243         const char *list[] = {
2244                 "W3SvcInstalled",
2245                 "BeepEnabled",
2246                 "EventLog",
2247                 /* "NetPopup", not on w2k8 */
2248                 /* "NetPopupToComputer", not on w2k8 */
2249                 "MajorVersion",
2250                 "MinorVersion",
2251                 "DefaultSpoolDirectory",
2252                 "Architecture",
2253                 "DsPresent",
2254                 "OSVersion",
2255                 /* "OSVersionEx", not on s3 */
2256                 "DNSMachineName"
2257         };
2258         int i;
2259
2260         for (i=0; i < ARRAY_SIZE(list); i++) {
2261                 enum winreg_Type type, type_ex;
2262                 union spoolss_PrinterData data, data_ex;
2263
2264                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2265                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2266                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2267                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2268                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2269                 switch (type) {
2270                 case REG_SZ:
2271                         torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2272                         break;
2273                 case REG_DWORD:
2274                         torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2275                         break;
2276                 case REG_BINARY:
2277                         torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2278                         break;
2279                 default:
2280                         break;
2281                 }
2282         }
2283
2284         return true;
2285 }
2286
2287 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2288                                  struct policy_handle *handle)
2289 {
2290         NTSTATUS status;
2291         struct spoolss_EnumPrinterData r;
2292
2293         ZERO_STRUCT(r);
2294         r.in.handle = handle;
2295         r.in.enum_index = 0;
2296
2297         do {
2298                 uint32_t value_size = 0;
2299                 uint32_t data_size = 0;
2300                 enum winreg_Type type = 0;
2301
2302                 r.in.value_offered = value_size;
2303                 r.out.value_needed = &value_size;
2304                 r.in.data_offered = data_size;
2305                 r.out.data_needed = &data_size;
2306
2307                 r.out.type = &type;
2308                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2309
2310                 torture_comment(tctx, "Testing EnumPrinterData\n");
2311
2312                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2313
2314                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2315                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2316                         break;
2317                 }
2318                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2319
2320                 r.in.value_offered = value_size;
2321                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2322                 r.in.data_offered = data_size;
2323                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2324
2325                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2326
2327                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2328                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2329                         break;
2330                 }
2331
2332                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2333
2334                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2335                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2336
2337                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2338                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2339
2340                 r.in.enum_index++;
2341
2342         } while (W_ERROR_IS_OK(r.out.result));
2343
2344         return true;
2345 }
2346
2347 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2348                                    struct dcerpc_pipe *p,
2349                                    struct policy_handle *handle,
2350                                    const char *key_name)
2351 {
2352         struct spoolss_EnumPrinterDataEx r;
2353         struct spoolss_PrinterEnumValues *info;
2354         uint32_t needed;
2355         uint32_t count;
2356
2357         r.in.handle = handle;
2358         r.in.key_name = key_name;
2359         r.in.offered = 0;
2360         r.out.needed = &needed;
2361         r.out.count = &count;
2362         r.out.info = &info;
2363
2364         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2365
2366         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2367                 "EnumPrinterDataEx failed");
2368         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2369                 r.in.offered = needed;
2370                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2371                         "EnumPrinterDataEx failed");
2372         }
2373
2374         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2375
2376         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2377
2378         return true;
2379 }
2380
2381
2382 static bool test_DeletePrinterData(struct torture_context *tctx,
2383                                    struct dcerpc_pipe *p,
2384                                    struct policy_handle *handle,
2385                                    const char *value_name)
2386 {
2387         NTSTATUS status;
2388         struct spoolss_DeletePrinterData r;
2389
2390         r.in.handle = handle;
2391         r.in.value_name = value_name;
2392
2393         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2394                 r.in.value_name);
2395
2396         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2397
2398         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2399         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2400
2401         return true;
2402 }
2403
2404 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2405                                      struct dcerpc_pipe *p,
2406                                      struct policy_handle *handle,
2407                                      const char *key_name,
2408                                      const char *value_name)
2409 {
2410         struct spoolss_DeletePrinterDataEx r;
2411
2412         r.in.handle = handle;
2413         r.in.key_name = key_name;
2414         r.in.value_name = value_name;
2415
2416         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2417                 r.in.key_name, r.in.value_name);
2418
2419         torture_assert_ntstatus_ok(tctx,
2420                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2421                 "DeletePrinterDataEx failed");
2422         torture_assert_werr_ok(tctx, r.out.result,
2423                 "DeletePrinterDataEx failed");
2424
2425         return true;
2426 }
2427
2428 static bool test_DeletePrinterKey(struct torture_context *tctx,
2429                                   struct dcerpc_pipe *p,
2430                                   struct policy_handle *handle,
2431                                   const char *key_name)
2432 {
2433         struct spoolss_DeletePrinterKey r;
2434
2435         r.in.handle = handle;
2436         r.in.key_name = key_name;
2437
2438         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2439
2440         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2441                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2442                 return true;
2443         }
2444
2445         torture_assert_ntstatus_ok(tctx,
2446                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2447                 "DeletePrinterKey failed");
2448         torture_assert_werr_ok(tctx, r.out.result,
2449                 "DeletePrinterKey failed");
2450
2451         return true;
2452 }
2453
2454 static bool test_SetPrinterData(struct torture_context *tctx,
2455                                 struct dcerpc_pipe *p,
2456                                 struct policy_handle *handle)
2457 {
2458         NTSTATUS status;
2459         struct spoolss_SetPrinterData r;
2460         const char *values[] = {
2461                 "spootyfoot",
2462                 "spooty\\foot",
2463 #if 0
2464         /* FIXME: not working with s3 atm. */
2465                 "spooty,foot",
2466                 "spooty,fo,ot",
2467 #endif
2468                 "spooty foot",
2469 #if 0
2470         /* FIXME: not working with s3 atm. */
2471                 "spooty\\fo,ot",
2472                 "spooty,fo\\ot"
2473 #endif
2474         };
2475         int i;
2476
2477         for (i=0; i < ARRAY_SIZE(values); i++) {
2478
2479                 enum winreg_Type type;
2480                 union spoolss_PrinterData data;
2481
2482                 r.in.handle = handle;
2483                 r.in.value_name = values[i];
2484                 r.in.type = REG_SZ;
2485                 r.in.data.string = "dog";
2486
2487                 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2488                         r.in.value_name);
2489
2490                 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2491
2492                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2493                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2494
2495                 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2496                         return false;
2497                 }
2498
2499                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2500                 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2501
2502                 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2503                         return false;
2504                 }
2505         }
2506
2507         return true;
2508 }
2509
2510 static bool test_EnumPrinterKey(struct torture_context *tctx,
2511                                 struct dcerpc_pipe *p,
2512                                 struct policy_handle *handle,
2513                                 const char *key_name,
2514                                 const char ***array);
2515
2516 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2517                                   struct dcerpc_pipe *p,
2518                                   struct policy_handle *handle)
2519 {
2520         NTSTATUS status;
2521         struct spoolss_SetPrinterDataEx r;
2522         const char *value_name = "dog";
2523         const char *keys[] = {
2524                 "torturedataex",
2525                 "torture data ex",
2526 #if 0
2527         /* FIXME: not working with s3 atm. */
2528                 "torturedataex_with_subkey\\subkey",
2529                 "torturedataex_with_subkey\\subkey:0",
2530                 "torturedataex_with_subkey\\subkey:1",
2531                 "torturedataex_with_subkey\\subkey\\subsubkey",
2532                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2533                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2534 #endif
2535                 "torture,data",
2536 #if 0
2537         /* FIXME: not working with s3 atm. */
2538
2539                 "torture,data,ex",
2540                 "torture,data\\ex",
2541                 "torture\\data,ex"
2542 #endif
2543         };
2544         int i;
2545         DATA_BLOB blob = data_blob_string_const("catfoobar");
2546
2547
2548         for (i=0; i < ARRAY_SIZE(keys); i++) {
2549
2550                 char *c;
2551                 const char *key;
2552                 enum winreg_Type type;
2553                 const char **subkeys;
2554                 union spoolss_PrinterData data;
2555
2556                 r.in.handle = handle;
2557                 r.in.key_name = keys[i];
2558                 r.in.value_name = value_name;
2559                 r.in.type = REG_BINARY;
2560                 r.in.data.binary = blob;
2561
2562                 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2563
2564                 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2565
2566                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2567                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2568
2569                 key = talloc_strdup(tctx, r.in.key_name);
2570
2571                 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2572                         return false;
2573                 }
2574
2575                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2576                 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2577
2578                 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2579                         return false;
2580                 }
2581
2582                 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2583                         return false;
2584                 }
2585
2586                 c = strchr(key, '\\');
2587                 if (c) {
2588                         int i;
2589
2590                         /* we have subkeys */
2591
2592                         *c = 0;
2593
2594                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2595                                 return false;
2596                         }
2597
2598                         for (i=0; subkeys && subkeys[i]; i++) {
2599
2600                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2601
2602                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2603                                         return false;
2604                                 }
2605                         }
2606
2607                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2608                                 return false;
2609                         }
2610
2611                 } else {
2612                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2613                                 return false;
2614                         }
2615                 }
2616         }
2617
2618         return true;
2619 }
2620
2621
2622 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2623                                        struct dcerpc_pipe *p,
2624                                        struct policy_handle *handle)
2625 {
2626         NTSTATUS status;
2627         struct dcerpc_binding *b;
2628         struct dcerpc_pipe *p2;
2629         struct spoolss_ClosePrinter cp;
2630
2631         /* only makes sense on SMB */
2632         if (p->conn->transport.transport != NCACN_NP) {
2633                 return true;
2634         }
2635
2636         torture_comment(tctx, "testing close on secondary pipe\n");
2637
2638         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2639         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2640
2641         status = dcerpc_secondary_connection(p, &p2, b);
2642         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2643
2644         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2645         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2646
2647         cp.in.handle = handle;
2648         cp.out.handle = handle;
2649
2650         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2651         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2652                         "ERROR: Allowed close on secondary connection");
2653
2654         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2655                                  "Unexpected fault code");
2656
2657         talloc_free(p2);
2658
2659         return true;
2660 }
2661
2662 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2663                                      struct dcerpc_pipe *p, const char *name)
2664 {
2665         NTSTATUS status;
2666         struct spoolss_OpenPrinter op;
2667         struct spoolss_OpenPrinterEx opEx;
2668         struct policy_handle handle;
2669         bool ret = true;
2670
2671         op.in.printername       = name;
2672         op.in.datatype          = NULL;
2673         op.in.devmode_ctr.devmode= NULL;
2674         op.in.access_mask       = 0;
2675         op.out.handle           = &handle;
2676
2677         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2678
2679         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2680         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2681         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2682                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2683                         name, win_errstr(op.out.result));
2684         }
2685
2686         if (W_ERROR_IS_OK(op.out.result)) {
2687                 ret &=test_ClosePrinter(tctx, p, &handle);
2688         }
2689
2690         opEx.in.printername             = name;
2691         opEx.in.datatype                = NULL;
2692         opEx.in.devmode_ctr.devmode     = NULL;
2693         opEx.in.access_mask             = 0;
2694         opEx.in.level                   = 1;
2695         opEx.in.userlevel.level1        = NULL;
2696         opEx.out.handle                 = &handle;
2697
2698         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2699
2700         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2701         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2702         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2703                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2704                         name, win_errstr(opEx.out.result));
2705         }
2706
2707         if (W_ERROR_IS_OK(opEx.out.result)) {
2708                 ret &=test_ClosePrinter(tctx, p, &handle);
2709         }
2710
2711         return ret;
2712 }
2713
2714 static bool test_OpenPrinter(struct torture_context *tctx,
2715                              struct dcerpc_pipe *p,
2716                              const char *name)
2717 {
2718         NTSTATUS status;
2719         struct spoolss_OpenPrinter r;
2720         struct policy_handle handle;
2721         bool ret = true;
2722
2723         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2724         r.in.datatype           = NULL;
2725         r.in.devmode_ctr.devmode= NULL;
2726         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2727         r.out.handle            = &handle;
2728
2729         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2730
2731         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2732
2733         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2734
2735         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2736
2737         if (!test_GetPrinter(tctx, p, &handle)) {
2738                 ret = false;
2739         }
2740
2741         if (!torture_setting_bool(tctx, "samba3", false)) {
2742                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2743                         ret = false;
2744                 }
2745         }
2746
2747         if (!test_ClosePrinter(tctx, p, &handle)) {
2748                 ret = false;
2749         }
2750
2751         return ret;
2752 }
2753
2754 static bool call_OpenPrinterEx(struct torture_context *tctx,
2755                                struct dcerpc_pipe *p,
2756                                const char *name, struct policy_handle *handle)
2757 {
2758         struct spoolss_OpenPrinterEx r;
2759         struct spoolss_UserLevel1 userlevel1;
2760         NTSTATUS status;
2761
2762         if (name && name[0]) {
2763                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2764                                                    dcerpc_server_name(p), name);
2765         } else {
2766                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2767                                                    dcerpc_server_name(p));
2768         }
2769
2770         r.in.datatype           = NULL;
2771         r.in.devmode_ctr.devmode= NULL;
2772         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2773         r.in.level              = 1;
2774         r.in.userlevel.level1   = &userlevel1;
2775         r.out.handle = handle;
2776
2777         userlevel1.size = 1234;
2778         userlevel1.client = "hello";
2779         userlevel1.user = "spottyfoot!";
2780         userlevel1.build = 1;
2781         userlevel1.major = 2;
2782         userlevel1.minor = 3;
2783         userlevel1.processor = 4;
2784
2785         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2786
2787         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2788
2789         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2790
2791         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2792
2793         return true;
2794 }
2795
2796 static bool test_OpenPrinterEx(struct torture_context *tctx,
2797                                struct dcerpc_pipe *p,
2798                                const char *name)
2799 {
2800         struct policy_handle handle;
2801         bool ret = true;
2802
2803         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2804                 return false;
2805         }
2806
2807         if (!test_GetPrinter(tctx, p, &handle)) {
2808                 ret = false;
2809         }
2810
2811         if (!test_EnumForms(tctx, p, &handle, false)) {
2812                 ret = false;
2813         }
2814
2815         if (!test_AddForm(tctx, p, &handle, false)) {
2816                 ret = false;
2817         }
2818
2819         if (!test_EnumPrinterData(tctx, p, &handle)) {
2820                 ret = false;
2821         }
2822
2823         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2824                 ret = false;
2825         }
2826
2827         if (!test_printer_keys(tctx, p, &handle)) {
2828                 ret = false;
2829         }
2830
2831         if (!test_PausePrinter(tctx, p, &handle)) {
2832                 ret = false;
2833         }
2834
2835         if (!test_DoPrintTest(tctx, p, &handle)) {
2836                 ret = false;
2837         }
2838
2839         if (!test_ResumePrinter(tctx, p, &handle)) {
2840                 ret = false;
2841         }
2842
2843         if (!test_SetPrinterData(tctx, p, &handle)) {
2844                 ret = false;
2845         }
2846
2847         if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2848                 ret = false;
2849         }
2850
2851         if (!torture_setting_bool(tctx, "samba3", false)) {
2852                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2853                         ret = false;
2854                 }
2855         }
2856
2857         if (!test_ClosePrinter(tctx, p, &handle)) {
2858                 ret = false;
2859         }
2860
2861         return ret;
2862 }
2863
2864 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2865 {
2866         struct spoolss_EnumPrinters r;
2867         NTSTATUS status;
2868         uint16_t levels[] = {1, 2, 4, 5};
2869         int i;
2870         bool ret = true;
2871
2872         for (i=0;i<ARRAY_SIZE(levels);i++) {
2873                 union spoolss_PrinterInfo *info;
2874                 int j;
2875                 uint32_t needed;
2876                 uint32_t count;
2877
2878                 r.in.flags      = PRINTER_ENUM_LOCAL;
2879                 r.in.server     = "";
2880                 r.in.level      = levels[i];
2881                 r.in.buffer     = NULL;
2882                 r.in.offered    = 0;
2883                 r.out.needed    = &needed;
2884                 r.out.count     = &count;
2885                 r.out.info      = &info;
2886
2887                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2888
2889                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2890                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2891
2892                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2893                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2894                         data_blob_clear(&blob);
2895                         r.in.buffer = &blob;
2896                         r.in.offered = needed;
2897                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2898                 }
2899
2900                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2901
2902                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2903
2904                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2905
2906                 if (!info) {
2907                         torture_comment(tctx, "No printers returned\n");
2908                         return true;
2909                 }
2910
2911                 for (j=0;j<count;j++) {
2912                         if (r.in.level == 1) {
2913                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
2914                                 char *slash, *name;
2915                                 name = unc;
2916                                 if (unc[0] == '\\' && unc[1] == '\\') {
2917                                         unc +=2;
2918                                 }
2919                                 slash = strchr(unc, '\\');
2920                                 if (slash) {
2921                                         slash++;
2922                                         name = slash;
2923                                 }
2924                                 if (!test_OpenPrinter(tctx, p, name)) {
2925                                         ret = false;
2926                                 }
2927                                 if (!test_OpenPrinterEx(tctx, p, name)) {
2928                                         ret = false;
2929                                 }
2930                         }
2931                 }
2932         }
2933
2934         return ret;
2935 }
2936
2937 static bool test_GetPrinterDriver(struct torture_context *tctx,
2938                                   struct dcerpc_pipe *p,
2939                                   struct policy_handle *handle,
2940                                   const char *driver_name)
2941 {
2942         struct spoolss_GetPrinterDriver r;
2943         uint32_t needed;
2944
2945         r.in.handle = handle;
2946         r.in.architecture = "W32X86";
2947         r.in.level = 1;
2948         r.in.buffer = NULL;
2949         r.in.offered = 0;
2950         r.out.needed = &needed;
2951
2952         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2953
2954         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2955                 "failed to call GetPrinterDriver");
2956         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2957                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2958                 data_blob_clear(&blob);
2959                 r.in.buffer = &blob;
2960                 r.in.offered = needed;
2961                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2962                         "failed to call GetPrinterDriver");
2963         }
2964
2965         torture_assert_werr_ok(tctx, r.out.result,
2966                 "failed to call GetPrinterDriver");
2967
2968         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2969
2970         return true;
2971 }
2972
2973 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2974                                    struct dcerpc_pipe *p,
2975                                    struct policy_handle *handle,
2976                                    const char *driver_name)
2977 {
2978         struct spoolss_GetPrinterDriver2 r;
2979         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
2980         uint32_t needed;
2981         uint32_t server_major_version;
2982         uint32_t server_minor_version;
2983         int i;
2984
2985         r.in.handle = handle;
2986         r.in.architecture = SPOOLSS_ARCHITECTURE_NT_X86;
2987         r.in.client_major_version = 3;
2988         r.in.client_minor_version = 0;
2989         r.out.needed = &needed;
2990         r.out.server_major_version = &server_major_version;
2991         r.out.server_minor_version = &server_minor_version;
2992
2993         for (i=0;i<ARRAY_SIZE(levels);i++) {
2994
2995                 r.in.buffer = NULL;
2996                 r.in.offered = 0;
2997                 r.in.level = levels[i];
2998
2999                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3000                         driver_name, r.in.level);
3001
3002                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3003                         "failed to call GetPrinterDriver2");
3004                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3005                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3006                         data_blob_clear(&blob);
3007                         r.in.buffer = &blob;
3008                         r.in.offered = needed;
3009                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3010                                 "failed to call GetPrinterDriver2");
3011                 }
3012
3013                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3014                         switch (r.in.level) {
3015                         case 101:
3016                         case 8:
3017                                 continue;
3018                         default:
3019                                 break;
3020                         }
3021                 }
3022
3023                 torture_assert_werr_ok(tctx, r.out.result,
3024                         "failed to call GetPrinterDriver2");
3025
3026                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3027         }
3028
3029         return true;
3030 }
3031
3032 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3033                                         struct dcerpc_pipe *p)
3034 {
3035         struct spoolss_EnumPrinterDrivers r;
3036         NTSTATUS status;
3037         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3038         int i;
3039
3040         for (i=0;i<ARRAY_SIZE(levels);i++) {
3041
3042                 uint32_t needed;
3043                 uint32_t count;
3044                 union spoolss_DriverInfo *info;
3045
3046                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3047                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3048                 r.in.level = levels[i];
3049                 r.in.buffer = NULL;
3050                 r.in.offered = 0;
3051                 r.out.needed = &needed;
3052                 r.out.count = &count;
3053                 r.out.info = &info;
3054
3055                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3056
3057                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3058
3059                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3060
3061                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3062                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3063                         data_blob_clear(&blob);
3064                         r.in.buffer = &blob;
3065                         r.in.offered = needed;
3066                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3067                 }
3068
3069                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3070
3071                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3072
3073                 if (!info) {
3074                         torture_comment(tctx, "No printer drivers returned\n");
3075                         break;
3076                 }
3077
3078                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3079         }
3080
3081         return true;
3082 }
3083
3084 static bool test_DeletePrinter(struct torture_context *tctx,
3085                                struct dcerpc_pipe *p,
3086                                struct policy_handle *handle)
3087 {
3088         struct spoolss_DeletePrinter r;
3089
3090         torture_comment(tctx, "Testing DeletePrinter\n");
3091
3092         r.in.handle = handle;
3093
3094         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3095                 "failed to delete printer");
3096         torture_assert_werr_ok(tctx, r.out.result,
3097                 "failed to delete printer");
3098
3099         return true;
3100 }
3101
3102 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3103                                        struct dcerpc_pipe *p,
3104                                        uint32_t flags,
3105                                        uint32_t level,
3106                                        const char *name,
3107                                        bool *found)
3108 {
3109         struct spoolss_EnumPrinters e;
3110         uint32_t count;
3111         union spoolss_PrinterInfo *info;
3112         uint32_t needed;
3113         int i;
3114
3115         *found = false;
3116
3117         e.in.flags = flags;
3118         e.in.server = NULL;
3119         e.in.level = level;
3120         e.in.buffer = NULL;
3121         e.in.offered = 0;
3122         e.out.count = &count;
3123         e.out.info = &info;
3124         e.out.needed = &needed;
3125
3126         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3127                 "failed to enum printers");
3128
3129         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3130                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3131                 data_blob_clear(&blob);
3132                 e.in.buffer = &blob;
3133                 e.in.offered = needed;
3134
3135                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3136                         "failed to enum printers");
3137         }
3138
3139         torture_assert_werr_ok(tctx, e.out.result,
3140                 "failed to enum printers");
3141
3142         for (i=0; i < count; i++) {
3143
3144                 const char *current = NULL;
3145
3146                 switch (level) {
3147                 case 1:
3148                         current = info[i].info1.name;
3149                         break;
3150                 }
3151
3152                 if (strequal(current, name)) {
3153                         *found = true;
3154                         break;
3155                 }
3156         }
3157
3158         return true;
3159 }
3160
3161 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3162                                       struct dcerpc_pipe *p,
3163                                       const char *printername,
3164                                       bool ex)
3165 {
3166         WERROR result;
3167         struct spoolss_AddPrinter r;
3168         struct spoolss_AddPrinterEx rex;
3169         struct spoolss_SetPrinterInfoCtr info_ctr;
3170         struct spoolss_SetPrinterInfo1 info1;
3171         struct spoolss_DevmodeContainer devmode_ctr;
3172         struct sec_desc_buf secdesc_ctr;
3173         struct spoolss_UserLevelCtr userlevel_ctr;
3174         struct policy_handle handle;
3175         bool found = false;
3176
3177         ZERO_STRUCT(devmode_ctr);
3178         ZERO_STRUCT(secdesc_ctr);
3179         ZERO_STRUCT(userlevel_ctr);
3180         ZERO_STRUCT(info1);
3181
3182         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3183
3184         /* try to add printer to wellknown printer list (level 1) */
3185
3186         userlevel_ctr.level = 1;
3187
3188         info_ctr.info.info1 = &info1;
3189         info_ctr.level = 1;
3190
3191         rex.in.server = NULL;
3192         rex.in.info_ctr = &info_ctr;
3193         rex.in.devmode_ctr = &devmode_ctr;
3194         rex.in.secdesc_ctr = &secdesc_ctr;
3195         rex.in.userlevel_ctr = &userlevel_ctr;
3196         rex.out.handle = &handle;
3197
3198         r.in.server = NULL;
3199         r.in.info_ctr = &info_ctr;
3200         r.in.devmode_ctr = &devmode_ctr;
3201         r.in.secdesc_ctr = &secdesc_ctr;
3202         r.out.handle = &handle;
3203
3204         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3205                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3206                 "failed to add printer");
3207         result = ex ? rex.out.result : r.out.result;
3208         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3209                 "unexpected result code");
3210
3211         info1.name = printername;
3212         info1.flags = PRINTER_ATTRIBUTE_SHARED;
3213
3214         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3215                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3216                 "failed to add printer");
3217         result = ex ? rex.out.result : r.out.result;
3218         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3219                 "unexpected result code");
3220
3221         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3222            better do a real check to see the printer is really there */
3223
3224         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3225                                                         PRINTER_ENUM_NETWORK, 1,
3226                                                         printername,
3227                                                         &found),
3228                         "failed to enum printers");
3229
3230         torture_assert(tctx, found, "failed to find newly added printer");
3231
3232         info1.flags = 0;
3233
3234         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3235                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3236                 "failed to add printer");
3237         result = ex ? rex.out.result : r.out.result;
3238         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3239                 "unexpected result code");
3240
3241         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3242            better do a real check to see the printer has really been removed
3243            from the well known printer list */
3244
3245         found = false;
3246
3247         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3248                                                         PRINTER_ENUM_NETWORK, 1,
3249                                                         printername,
3250                                                         &found),
3251                         "failed to enum printers");
3252 #if 0
3253         torture_assert(tctx, !found, "printer still in well known printer list");
3254 #endif
3255         return true;
3256 }
3257
3258 static bool test_AddPrinter_normal(struct torture_context *tctx,
3259                                    struct dcerpc_pipe *p,
3260                                    struct policy_handle *handle_p,
3261                                    const char *printername,
3262                                    const char *drivername,
3263                                    const char *portname,
3264                                    bool ex)
3265 {
3266         WERROR result;
3267         struct spoolss_AddPrinter r;
3268         struct spoolss_AddPrinterEx rex;
3269         struct spoolss_SetPrinterInfoCtr info_ctr;
3270         struct spoolss_SetPrinterInfo2 info2;
3271         struct spoolss_DevmodeContainer devmode_ctr;
3272         struct sec_desc_buf secdesc_ctr;
3273         struct spoolss_UserLevelCtr userlevel_ctr;
3274         struct policy_handle handle;
3275         bool found = false;
3276
3277         ZERO_STRUCT(devmode_ctr);
3278         ZERO_STRUCT(secdesc_ctr);
3279         ZERO_STRUCT(userlevel_ctr);
3280
3281         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3282
3283         userlevel_ctr.level = 1;
3284
3285         rex.in.server = NULL;
3286         rex.in.info_ctr = &info_ctr;
3287         rex.in.devmode_ctr = &devmode_ctr;
3288         rex.in.secdesc_ctr = &secdesc_ctr;
3289         rex.in.userlevel_ctr = &userlevel_ctr;
3290         rex.out.handle = &handle;
3291
3292         r.in.server = NULL;
3293         r.in.info_ctr = &info_ctr;
3294         r.in.devmode_ctr = &devmode_ctr;
3295         r.in.secdesc_ctr = &secdesc_ctr;
3296         r.out.handle = &handle;
3297
3298  again:
3299
3300         /* try to add printer to printer list (level 2) */
3301
3302         ZERO_STRUCT(info2);
3303
3304         info_ctr.info.info2 = &info2;
3305         info_ctr.level = 2;
3306
3307         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3308                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3309                 "failed to add printer");
3310         result = ex ? rex.out.result : r.out.result;
3311         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3312                 "unexpected result code");
3313
3314         info2.printername = printername;
3315
3316         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3317                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3318                 "failed to add printer");
3319         result = ex ? rex.out.result : r.out.result;
3320
3321         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3322                 struct policy_handle printer_handle;
3323
3324                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3325                         "failed to open printer handle");
3326
3327                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3328                         "failed to delete printer");
3329
3330                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3331                         "failed to close server handle");
3332
3333                 goto again;
3334         }
3335
3336         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3337                 "unexpected result code");
3338
3339         info2.portname = portname;
3340
3341         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3342                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3343                 "failed to add printer");
3344         result = ex ? rex.out.result : r.out.result;
3345         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3346                 "unexpected result code");
3347
3348         info2.drivername = drivername;
3349
3350         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3351                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3352                 "failed to add printer");
3353         result = ex ? rex.out.result : r.out.result;
3354         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3355                 "unexpected result code");
3356
3357         info2.printprocessor = "winprint";
3358
3359         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3360                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3361                 "failed to add printer");
3362         result = ex ? rex.out.result : r.out.result;
3363         torture_assert_werr_ok(tctx, result,
3364                 "failed to add printer");
3365
3366         *handle_p = handle;
3367
3368         /* we are paranoid, really check if the printer is there now */
3369
3370         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3371                                                         PRINTER_ENUM_LOCAL, 1,
3372                                                         printername,
3373                                                         &found),
3374                         "failed to enum printers");
3375         torture_assert(tctx, found, "failed to find newly added printer");
3376
3377         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3378                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3379                 "failed to add printer");
3380         result = ex ? rex.out.result : r.out.result;
3381         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3382                 "unexpected result code");
3383
3384         return true;
3385 }
3386
3387 static bool test_AddPrinterEx(struct torture_context *tctx,
3388                               struct dcerpc_pipe *p,
3389                               struct policy_handle *handle_p,
3390                               const char *printername,
3391                               const char *drivername,
3392                               const char *portname)
3393 {
3394         bool ret = true;
3395
3396         if (!torture_setting_bool(tctx, "samba3", false)) {
3397                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3398                         torture_comment(tctx, "failed to add printer to well known list\n");
3399                         ret = false;
3400                 }
3401         }
3402
3403         if (!test_AddPrinter_normal(tctx, p, handle_p,
3404                                     printername, drivername, portname,
3405                                     true)) {
3406                 torture_comment(tctx, "failed to add printer to printer list\n");
3407                 ret = false;
3408         }
3409
3410         return ret;
3411 }
3412
3413 static bool test_AddPrinter(struct torture_context *tctx,
3414                             struct dcerpc_pipe *p,
3415                             struct policy_handle *handle_p,
3416                             const char *printername,
3417                             const char *drivername,
3418                             const char *portname)
3419 {
3420         bool ret = true;
3421
3422         if (!torture_setting_bool(tctx, "samba3", false)) {
3423                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3424                         torture_comment(tctx, "failed to add printer to well known list\n");
3425                         ret = false;
3426                 }
3427         }
3428
3429         if (!test_AddPrinter_normal(tctx, p, handle_p,
3430                                     printername, drivername, portname,
3431                                     false)) {
3432                 torture_comment(tctx, "failed to add printer to printer list\n");
3433                 ret = false;
3434         }
3435
3436         return ret;
3437 }
3438
3439 static bool test_printer_info(struct torture_context *tctx,
3440                               struct dcerpc_pipe *p,
3441                               struct policy_handle *handle)
3442 {
3443         bool ret = true;
3444
3445         if (!test_PrinterInfo(tctx, p, handle)) {
3446                 ret = false;
3447         }
3448
3449         if (!test_SetPrinter_errors(tctx, p, handle)) {
3450                 ret = false;
3451         }
3452
3453         return ret;
3454 }
3455
3456 static bool test_EnumPrinterKey(struct torture_context *tctx,
3457                                 struct dcerpc_pipe *p,
3458                                 struct policy_handle *handle,
3459                                 const char *key_name,
3460                                 const char ***array)
3461 {
3462         struct spoolss_EnumPrinterKey r;
3463         uint32_t needed = 0;
3464         union spoolss_KeyNames key_buffer;
3465         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
3466         uint32_t _ndr_size;
3467         int i;
3468
3469         r.in.handle = handle;
3470         r.in.key_name = key_name;
3471         r.out.key_buffer = &key_buffer;
3472         r.out.needed = &needed;
3473         r.out._ndr_size = &_ndr_size;
3474
3475         for (i=0; i < ARRAY_SIZE(offered); i++) {
3476
3477                 if (offered[i] < 0 && needed) {
3478                         if (needed <= 4) {
3479                                 continue;
3480                         }
3481                         r.in.offered = needed + offered[i];
3482                 } else {
3483                         r.in.offered = offered[i];
3484                 }
3485
3486                 ZERO_STRUCT(key_buffer);
3487
3488                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
3489
3490                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3491                         "failed to call EnumPrinterKey");
3492                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3493
3494                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
3495                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3496                                         _ndr_size, r.in.offered/2));
3497
3498                         r.in.offered = needed;
3499                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3500                                 "failed to call EnumPrinterKey");
3501                 }
3502
3503                 if (offered[i] > 0) {
3504                         torture_assert_werr_ok(tctx, r.out.result,
3505                                 "failed to call EnumPrinterKey");
3506                 }
3507
3508                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
3509                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3510                                 _ndr_size, r.in.offered/2));
3511
3512                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
3513                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
3514
3515                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
3516                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
3517
3518                 if (key_buffer.string_array) {
3519                         uint32_t calc_needed = 0;
3520                         int s;
3521                         for (s=0; key_buffer.string_array[s]; s++) {
3522                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
3523                         }
3524                         if (!key_buffer.string_array[0]) {
3525                                 calc_needed += 2;
3526                         }
3527                         calc_needed += 2;
3528
3529                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
3530                                 "EnumPrinterKey unexpected size");
3531                 }
3532         }
3533
3534         if (array) {
3535                 *array = key_buffer.string_array;
3536         }
3537
3538         return true;
3539 }
3540
3541 bool test_printer_keys(struct torture_context *tctx,
3542                        struct dcerpc_pipe *p,
3543                        struct policy_handle *handle)
3544 {
3545         const char **key_array = NULL;
3546         int i;
3547
3548         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3549                 "failed to call test_EnumPrinterKey");
3550
3551         for (i=0; key_array && key_array[i]; i++) {
3552                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3553                         "failed to call test_EnumPrinterKey");
3554         }
3555         for (i=0; key_array && key_array[i]; i++) {
3556                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3557                         "failed to call test_EnumPrinterDataEx");
3558         }
3559
3560         return true;
3561 }
3562
3563 static bool test_printer(struct torture_context *tctx,
3564                          struct dcerpc_pipe *p)
3565 {
3566         bool ret = true;
3567         struct policy_handle handle[2];
3568         bool found = false;
3569         const char *drivername = "Microsoft XPS Document Writer";
3570         const char *portname = "LPT1:";
3571
3572         /* test printer created via AddPrinter */
3573
3574         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3575                 return false;
3576         }
3577
3578         if (!test_printer_info(tctx, p, &handle[0])) {
3579                 ret = false;
3580         }
3581
3582         if (!test_printer_keys(tctx, p, &handle[0])) {
3583                 ret = false;
3584         }
3585
3586         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3587                 ret = false;
3588         }
3589
3590         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3591                                         TORTURE_PRINTER, &found)) {
3592                 ret = false;
3593         }
3594
3595         torture_assert(tctx, !found, "deleted printer still there");
3596
3597         /* test printer created via AddPrinterEx */
3598
3599         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3600                 return false;
3601         }
3602
3603         if (!test_printer_info(tctx, p, &handle[1])) {
3604                 ret = false;
3605         }
3606
3607         if (!test_printer_keys(tctx, p, &handle[1])) {
3608                 ret = false;
3609         }
3610
3611         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3612                 ret = false;
3613         }
3614
3615         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3616                                         TORTURE_PRINTER_EX, &found)) {
3617                 ret = false;
3618         }
3619
3620         torture_assert(tctx, !found, "deleted printer still there");
3621
3622         return ret;
3623 }
3624
3625 bool torture_rpc_spoolss(struct torture_context *torture)
3626 {
3627         NTSTATUS status;
3628         struct dcerpc_pipe *p;
3629         bool ret = true;
3630         struct test_spoolss_context *ctx;
3631
3632         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3633         if (!NT_STATUS_IS_OK(status)) {
3634                 return false;
3635         }
3636
3637         ctx = talloc_zero(torture, struct test_spoolss_context);
3638
3639         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3640         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3641         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3642         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3643         ret &= test_EnumPorts(torture, p, ctx);
3644         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3645         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3646         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3647         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3648         ret &= test_EnumMonitors(torture, p, ctx);
3649         ret &= test_EnumPrintProcessors(torture, p, ctx);
3650         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3651         ret &= test_EnumPrinters(torture, p, ctx);
3652         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3653         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3654         ret &= test_OpenPrinter_badname(torture, p, "");
3655         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3656         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3657         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3658         ret &= test_OpenPrinter_badname(torture, p,
3659                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3660
3661
3662         ret &= test_AddPort(torture, p);
3663         ret &= test_EnumPorts_old(torture, p);
3664         ret &= test_EnumPrinters_old(torture, p);
3665         ret &= test_EnumPrinterDrivers_old(torture, p);
3666
3667         return ret;
3668 }
3669
3670 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3671 {
3672         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3673
3674         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3675                                                         "printer", &ndr_table_spoolss);
3676
3677         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3678
3679         return suite;
3680 }