ddc14f33a2c347c6079e770354238150b25e3f76
[abartlet/samba.git/.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009
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 static bool test_GetPrinterDriver(struct torture_context *tctx,
2541                                   struct dcerpc_pipe *p,
2542                                   struct policy_handle *handle,
2543                                   const char *driver_name)
2544 {
2545         struct spoolss_GetPrinterDriver r;
2546         uint32_t needed;
2547
2548         r.in.handle = handle;
2549         r.in.architecture = "W32X86";
2550         r.in.level = 1;
2551         r.in.buffer = NULL;
2552         r.in.offered = 0;
2553         r.out.needed = &needed;
2554
2555         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2556
2557         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2558                 "failed to call GetPrinterDriver");
2559         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2560                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2561                 data_blob_clear(&blob);
2562                 r.in.buffer = &blob;
2563                 r.in.offered = needed;
2564                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2565                         "failed to call GetPrinterDriver");
2566         }
2567
2568         torture_assert_werr_ok(tctx, r.out.result,
2569                 "failed to call GetPrinterDriver");
2570
2571         return true;
2572 }
2573
2574 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2575                                    struct dcerpc_pipe *p,
2576                                    struct policy_handle *handle,
2577                                    const char *driver_name)
2578 {
2579         struct spoolss_GetPrinterDriver2 r;
2580         uint32_t needed;
2581         uint32_t server_major_version;
2582         uint32_t server_minor_version;
2583
2584         r.in.handle = handle;
2585         r.in.architecture = "W32X86";
2586         r.in.level = 1;
2587         r.in.buffer = NULL;
2588         r.in.offered = 0;
2589         r.in.client_major_version = 0;
2590         r.in.client_minor_version = 0;
2591         r.out.needed = &needed;
2592         r.out.server_major_version = &server_major_version;
2593         r.out.server_minor_version = &server_minor_version;
2594
2595         torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2596
2597         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2598                 "failed to call GetPrinterDriver2");
2599         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2600                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2601                 data_blob_clear(&blob);
2602                 r.in.buffer = &blob;
2603                 r.in.offered = needed;
2604                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2605                         "failed to call GetPrinterDriver2");
2606         }
2607
2608         torture_assert_werr_ok(tctx, r.out.result,
2609                 "failed to call GetPrinterDriver2");
2610
2611         return true;
2612 }
2613
2614 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2615                                         struct dcerpc_pipe *p)
2616 {
2617         struct spoolss_EnumPrinterDrivers r;
2618         NTSTATUS status;
2619         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2620         int i;
2621
2622         for (i=0;i<ARRAY_SIZE(levels);i++) {
2623
2624                 uint32_t needed;
2625                 uint32_t count;
2626                 union spoolss_DriverInfo *info;
2627
2628                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2629                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2630                 r.in.level = levels[i];
2631                 r.in.buffer = NULL;
2632                 r.in.offered = 0;
2633                 r.out.needed = &needed;
2634                 r.out.count = &count;
2635                 r.out.info = &info;
2636
2637                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2638
2639                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2640
2641                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2642
2643                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2644                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2645                         data_blob_clear(&blob);
2646                         r.in.buffer = &blob;
2647                         r.in.offered = needed;
2648                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2649                 }
2650
2651                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2652
2653                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2654
2655                 if (!info) {
2656                         torture_comment(tctx, "No printer drivers returned\n");
2657                         break;
2658                 }
2659         }
2660
2661         return true;
2662 }
2663
2664 static bool test_DeletePrinter(struct torture_context *tctx,
2665                                struct dcerpc_pipe *p,
2666                                struct policy_handle *handle)
2667 {
2668         struct spoolss_DeletePrinter r;
2669
2670         torture_comment(tctx, "Testing DeletePrinter\n");
2671
2672         r.in.handle = handle;
2673
2674         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2675                 "failed to delete printer");
2676         torture_assert_werr_ok(tctx, r.out.result,
2677                 "failed to delete printer");
2678
2679         return true;
2680 }
2681
2682 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2683                                        struct dcerpc_pipe *p,
2684                                        uint32_t flags,
2685                                        uint32_t level,
2686                                        const char *name,
2687                                        bool *found)
2688 {
2689         struct spoolss_EnumPrinters e;
2690         uint32_t count;
2691         union spoolss_PrinterInfo *info;
2692         uint32_t needed;
2693         int i;
2694
2695         *found = false;
2696
2697         e.in.flags = flags;
2698         e.in.server = NULL;
2699         e.in.level = level;
2700         e.in.buffer = NULL;
2701         e.in.offered = 0;
2702         e.out.count = &count;
2703         e.out.info = &info;
2704         e.out.needed = &needed;
2705
2706         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2707                 "failed to enum printers");
2708
2709         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2710                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2711                 data_blob_clear(&blob);
2712                 e.in.buffer = &blob;
2713                 e.in.offered = needed;
2714
2715                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2716                         "failed to enum printers");
2717         }
2718
2719         torture_assert_werr_ok(tctx, e.out.result,
2720                 "failed to enum printers");
2721
2722         for (i=0; i < count; i++) {
2723
2724                 const char *current = NULL;
2725
2726                 switch (level) {
2727                 case 1:
2728                         current = info[i].info1.name;
2729                         break;
2730                 }
2731
2732                 if (strequal(current, name)) {
2733                         *found = true;
2734                         break;
2735                 }
2736         }
2737
2738         return true;
2739 }
2740
2741 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2742                                       struct dcerpc_pipe *p,
2743                                       const char *printername,
2744                                       bool ex)
2745 {
2746         WERROR result;
2747         struct spoolss_AddPrinter r;
2748         struct spoolss_AddPrinterEx rex;
2749         struct spoolss_SetPrinterInfoCtr info_ctr;
2750         struct spoolss_SetPrinterInfo1 info1;
2751         struct spoolss_DevmodeContainer devmode_ctr;
2752         struct sec_desc_buf secdesc_ctr;
2753         struct spoolss_UserLevelCtr userlevel_ctr;
2754         struct policy_handle handle;
2755         bool found = false;
2756
2757         ZERO_STRUCT(devmode_ctr);
2758         ZERO_STRUCT(secdesc_ctr);
2759         ZERO_STRUCT(userlevel_ctr);
2760         ZERO_STRUCT(info1);
2761
2762         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2763
2764         /* try to add printer to wellknown printer list (level 1) */
2765
2766         userlevel_ctr.level = 1;
2767
2768         info_ctr.info.info1 = &info1;
2769         info_ctr.level = 1;
2770
2771         rex.in.server = NULL;
2772         rex.in.info_ctr = &info_ctr;
2773         rex.in.devmode_ctr = &devmode_ctr;
2774         rex.in.secdesc_ctr = &secdesc_ctr;
2775         rex.in.userlevel_ctr = &userlevel_ctr;
2776         rex.out.handle = &handle;
2777
2778         r.in.server = NULL;
2779         r.in.info_ctr = &info_ctr;
2780         r.in.devmode_ctr = &devmode_ctr;
2781         r.in.secdesc_ctr = &secdesc_ctr;
2782         r.out.handle = &handle;
2783
2784         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2785                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2786                 "failed to add printer");
2787         result = ex ? rex.out.result : r.out.result;
2788         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2789                 "unexpected result code");
2790
2791         info1.name = printername;
2792         info1.flags = PRINTER_ATTRIBUTE_SHARED;
2793
2794         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2795                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2796                 "failed to add printer");
2797         result = ex ? rex.out.result : r.out.result;
2798         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2799                 "unexpected result code");
2800
2801         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2802            better do a real check to see the printer is really there */
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
2810         torture_assert(tctx, found, "failed to find newly added printer");
2811
2812         info1.flags = 0;
2813
2814         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2815                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2816                 "failed to add printer");
2817         result = ex ? rex.out.result : r.out.result;
2818         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2819                 "unexpected result code");
2820
2821         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2822            better do a real check to see the printer has really been removed
2823            from the well known printer list */
2824
2825         found = false;
2826
2827         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2828                                                         PRINTER_ENUM_NETWORK, 1,
2829                                                         printername,
2830                                                         &found),
2831                         "failed to enum printers");
2832 #if 0
2833         torture_assert(tctx, !found, "printer still in well known printer list");
2834 #endif
2835         return true;
2836 }
2837
2838 static bool test_AddPrinter_normal(struct torture_context *tctx,
2839                                    struct dcerpc_pipe *p,
2840                                    struct policy_handle *handle_p,
2841                                    const char *printername,
2842                                    const char *drivername,
2843                                    const char *portname,
2844                                    bool ex)
2845 {
2846         WERROR result;
2847         struct spoolss_AddPrinter r;
2848         struct spoolss_AddPrinterEx rex;
2849         struct spoolss_SetPrinterInfoCtr info_ctr;
2850         struct spoolss_SetPrinterInfo2 info2;
2851         struct spoolss_DevmodeContainer devmode_ctr;
2852         struct sec_desc_buf secdesc_ctr;
2853         struct spoolss_UserLevelCtr userlevel_ctr;
2854         struct policy_handle handle;
2855         bool found = false;
2856
2857         ZERO_STRUCT(devmode_ctr);
2858         ZERO_STRUCT(secdesc_ctr);
2859         ZERO_STRUCT(userlevel_ctr);
2860
2861         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
2862
2863         userlevel_ctr.level = 1;
2864
2865         rex.in.server = NULL;
2866         rex.in.info_ctr = &info_ctr;
2867         rex.in.devmode_ctr = &devmode_ctr;
2868         rex.in.secdesc_ctr = &secdesc_ctr;
2869         rex.in.userlevel_ctr = &userlevel_ctr;
2870         rex.out.handle = &handle;
2871
2872         r.in.server = NULL;
2873         r.in.info_ctr = &info_ctr;
2874         r.in.devmode_ctr = &devmode_ctr;
2875         r.in.secdesc_ctr = &secdesc_ctr;
2876         r.out.handle = &handle;
2877
2878  again:
2879
2880         /* try to add printer to printer list (level 2) */
2881
2882         ZERO_STRUCT(info2);
2883
2884         info_ctr.info.info2 = &info2;
2885         info_ctr.level = 2;
2886
2887         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2888                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2889                 "failed to add printer");
2890         result = ex ? rex.out.result : r.out.result;
2891         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2892                 "unexpected result code");
2893
2894         info2.printername = printername;
2895
2896         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2897                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2898                 "failed to add printer");
2899         result = ex ? rex.out.result : r.out.result;
2900
2901         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
2902                 struct policy_handle printer_handle;
2903
2904                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
2905                         "failed to open printer handle");
2906
2907                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
2908                         "failed to delete printer");
2909
2910                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
2911                         "failed to close server handle");
2912
2913                 goto again;
2914         }
2915
2916         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
2917                 "unexpected result code");
2918
2919         info2.portname = portname;
2920
2921         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2922                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2923                 "failed to add printer");
2924         result = ex ? rex.out.result : r.out.result;
2925         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
2926                 "unexpected result code");
2927
2928         info2.drivername = drivername;
2929
2930         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2931                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2932                 "failed to add printer");
2933         result = ex ? rex.out.result : r.out.result;
2934         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
2935                 "unexpected result code");
2936
2937         info2.printprocessor = "winprint";
2938
2939         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2940                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2941                 "failed to add printer");
2942         result = ex ? rex.out.result : r.out.result;
2943         torture_assert_werr_ok(tctx, result,
2944                 "failed to add printer");
2945
2946         *handle_p = handle;
2947
2948         /* we are paranoid, really check if the printer is there now */
2949
2950         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2951                                                         PRINTER_ENUM_LOCAL, 1,
2952                                                         printername,
2953                                                         &found),
2954                         "failed to enum printers");
2955         torture_assert(tctx, found, "failed to find newly added printer");
2956
2957         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2958                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2959                 "failed to add printer");
2960         result = ex ? rex.out.result : r.out.result;
2961         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2962                 "unexpected result code");
2963
2964         return true;
2965 }
2966
2967 static bool test_AddPrinterEx(struct torture_context *tctx,
2968                               struct dcerpc_pipe *p,
2969                               struct policy_handle *handle_p,
2970                               const char *printername,
2971                               const char *drivername,
2972                               const char *portname)
2973 {
2974         bool ret = true;
2975
2976         if (!torture_setting_bool(tctx, "samba3", false)) {
2977                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
2978                         torture_comment(tctx, "failed to add printer to well known list\n");
2979                         ret = false;
2980                 }
2981         }
2982
2983         if (!test_AddPrinter_normal(tctx, p, handle_p,
2984                                     printername, drivername, portname,
2985                                     true)) {
2986                 torture_comment(tctx, "failed to add printer to printer list\n");
2987                 ret = false;
2988         }
2989
2990         return ret;
2991 }
2992
2993 static bool test_AddPrinter(struct torture_context *tctx,
2994                             struct dcerpc_pipe *p,
2995                             struct policy_handle *handle_p,
2996                             const char *printername,
2997                             const char *drivername,
2998                             const char *portname)
2999 {
3000         bool ret = true;
3001
3002         if (!torture_setting_bool(tctx, "samba3", false)) {
3003                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3004                         torture_comment(tctx, "failed to add printer to well known list\n");
3005                         ret = false;
3006                 }
3007         }
3008
3009         if (!test_AddPrinter_normal(tctx, p, handle_p,
3010                                     printername, drivername, portname,
3011                                     false)) {
3012                 torture_comment(tctx, "failed to add printer to printer list\n");
3013                 ret = false;
3014         }
3015
3016         return ret;
3017 }
3018
3019 static bool test_printer_info(struct torture_context *tctx,
3020                               struct dcerpc_pipe *p,
3021                               struct policy_handle *handle)
3022 {
3023         bool ret = true;
3024
3025         if (!test_PrinterInfo(tctx, p, handle)) {
3026                 ret = false;
3027         }
3028
3029         if (!test_SetPrinter_errors(tctx, p, handle)) {
3030                 ret = false;
3031         }
3032
3033         return ret;
3034 }
3035
3036 static bool test_printer(struct torture_context *tctx,
3037                          struct dcerpc_pipe *p)
3038 {
3039         bool ret = true;
3040         struct policy_handle handle[2];
3041         bool found = false;
3042         const char *drivername = "Microsoft XPS Document Writer";
3043         const char *portname = "LPT1:";
3044
3045         /* test printer created via AddPrinter */
3046
3047         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3048                 return false;
3049         }
3050
3051         if (!test_printer_info(tctx, p, &handle[0])) {
3052                 ret = false;
3053         }
3054
3055         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3056                 ret = false;
3057         }
3058
3059         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3060                                         TORTURE_PRINTER, &found)) {
3061                 ret = false;
3062         }
3063
3064         torture_assert(tctx, !found, "deleted printer still there");
3065
3066         /* test printer created via AddPrinterEx */
3067
3068         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3069                 return false;
3070         }
3071
3072         if (!test_printer_info(tctx, p, &handle[1])) {
3073                 ret = false;
3074         }
3075
3076         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3077                 ret = false;
3078         }
3079
3080         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3081                                         TORTURE_PRINTER_EX, &found)) {
3082                 ret = false;
3083         }
3084
3085         torture_assert(tctx, !found, "deleted printer still there");
3086
3087         return ret;
3088 }
3089
3090 bool torture_rpc_spoolss(struct torture_context *torture)
3091 {
3092         NTSTATUS status;
3093         struct dcerpc_pipe *p;
3094         bool ret = true;
3095         struct test_spoolss_context *ctx;
3096
3097         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3098         if (!NT_STATUS_IS_OK(status)) {
3099                 return false;
3100         }
3101
3102         ctx = talloc_zero(torture, struct test_spoolss_context);
3103
3104         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3105
3106         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3107         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3108         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3109         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3110         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3111         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3112         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3113         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3114         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3115         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
3116         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
3117         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
3118         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
3119         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3120         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3121         ret &= test_EnumPorts(torture, p, ctx);
3122         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3123         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3124         ret &= test_EnumPrinterDrivers(torture, p, ctx);
3125         ret &= test_EnumMonitors(torture, p, ctx);
3126         ret &= test_EnumPrintProcessors(torture, p, ctx);
3127         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3128         ret &= test_EnumPrinters(torture, p, ctx);
3129         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3130         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3131         ret &= test_OpenPrinter_badname(torture, p, "");
3132         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3133         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3134         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3135         ret &= test_OpenPrinter_badname(torture, p,
3136                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3137
3138
3139         ret &= test_AddPort(torture, p);
3140         ret &= test_EnumPorts_old(torture, p);
3141         ret &= test_EnumPrinters_old(torture, p);
3142         ret &= test_EnumPrinterDrivers_old(torture, p);
3143
3144         return ret;
3145 }
3146
3147 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3148 {
3149         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3150
3151         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3152                                                         "printer", &ndr_table_spoolss);
3153
3154         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3155
3156         return suite;
3157 }