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