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