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