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