f0ecb65785bf80ab449210099364322202e5c332
[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                                     const char *architecture)
314 {
315         NTSTATUS status;
316         struct spoolss_EnumPrinterDrivers r;
317         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
318         int i, j;
319
320         for (i=0;i<ARRAY_SIZE(levels);i++) {
321                 int level = levels[i];
322                 DATA_BLOB blob;
323                 uint32_t needed;
324                 uint32_t count;
325                 union spoolss_DriverInfo *info;
326
327                 /* FIXME: gd, come back and fix "" as server, and handle
328                  * priority of returned error codes in torture test and samba 3
329                  * server */
330
331                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
332                 r.in.environment        = architecture;
333                 r.in.level              = level;
334                 r.in.buffer             = NULL;
335                 r.in.offered            = 0;
336                 r.out.needed            = &needed;
337                 r.out.count             = &count;
338                 r.out.info              = &info;
339
340                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
341
342                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
343                 torture_assert_ntstatus_ok(tctx, status,
344                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
345                 if (W_ERROR_IS_OK(r.out.result)) {
346                         /* TODO: do some more checks here */
347                         continue;
348                 }
349                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
350                         blob = data_blob_talloc(ctx, NULL, needed);
351                         data_blob_clear(&blob);
352                         r.in.buffer = &blob;
353                         r.in.offered = needed;
354
355                         status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
356                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
357                 }
358
359                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
360
361                 ctx->driver_count[level]        = count;
362                 ctx->drivers[level]             = info;
363         }
364
365         for (i=1;i<ARRAY_SIZE(levels);i++) {
366                 int level = levels[i];
367                 int old_level = levels[i-1];
368
369                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
370                         "EnumPrinterDrivers invalid value");
371         }
372
373         for (i=0;i<ARRAY_SIZE(levels);i++) {
374                 int level = levels[i];
375
376                 for (j=0;j<ctx->driver_count[level];j++) {
377                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
378                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
379                         switch (level) {
380                         case 1:
381                                 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
382                                 break;
383                         case 2:
384                                 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
385                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
386                                 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
387                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
388                                 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
389                                 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
390                                 break;
391                         case 3:
392                                 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
393                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
394                                 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
395                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
396                                 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
397                                 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
398                                 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
399                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
400                                 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
401                                 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
402                                 break;
403                         case 4:
404                                 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
405                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
406                                 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
407                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
408                                 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
409                                 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
410                                 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
411                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
412                                 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
413                                 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
414                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
415                                 break;
416                         case 5:
417                                 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
418                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
419                                 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
420                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
421                                 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
422                                 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
423                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
424                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
425                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
426                                 break;
427                         case 6:
428                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
429                                 break;
430                         }
431                 }
432         }
433
434         return true;
435 }
436
437 static bool test_EnumMonitors(struct torture_context *tctx,
438                               struct dcerpc_pipe *p,
439                               struct test_spoolss_context *ctx)
440 {
441         NTSTATUS status;
442         struct spoolss_EnumMonitors r;
443         uint16_t levels[] = { 1, 2 };
444         int i, j;
445
446         for (i=0;i<ARRAY_SIZE(levels);i++) {
447                 int level = levels[i];
448                 DATA_BLOB blob;
449                 uint32_t needed;
450                 uint32_t count;
451                 union spoolss_MonitorInfo *info;
452
453                 r.in.servername = "";
454                 r.in.level = level;
455                 r.in.buffer = NULL;
456                 r.in.offered = 0;
457                 r.out.needed = &needed;
458                 r.out.count = &count;
459                 r.out.info = &info;
460
461                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
462
463                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
464                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
465                 if (W_ERROR_IS_OK(r.out.result)) {
466                         /* TODO: do some more checks here */
467                         continue;
468                 }
469                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
470                         "EnumMonitors failed");
471
472                 blob = data_blob_talloc(ctx, NULL, needed);
473                 data_blob_clear(&blob);
474                 r.in.buffer = &blob;
475                 r.in.offered = needed;
476
477                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
478                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
479
480                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
481
482                 ctx->monitor_count[level]       = count;
483                 ctx->monitors[level]            = info;
484         }
485
486         for (i=1;i<ARRAY_SIZE(levels);i++) {
487                 int level = levels[i];
488                 int old_level = levels[i-1];
489                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
490                                          "EnumMonitors invalid value");
491         }
492
493         for (i=0;i<ARRAY_SIZE(levels);i++) {
494                 int level = levels[i];
495                 for (j=0;j<ctx->monitor_count[level];j++) {
496                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
497                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
498                         switch (level) {
499                         case 1:
500                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
501                                 break;
502                         case 2:
503                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
504                                 break;
505                         }
506                 }
507         }
508
509         return true;
510 }
511
512 static bool test_EnumPrintProcessors(struct torture_context *tctx,
513                                      struct dcerpc_pipe *p,
514                                      struct test_spoolss_context *ctx)
515 {
516         NTSTATUS status;
517         struct spoolss_EnumPrintProcessors r;
518         uint16_t levels[] = { 1 };
519         int i, j;
520
521         for (i=0;i<ARRAY_SIZE(levels);i++) {
522                 int level = levels[i];
523                 DATA_BLOB blob;
524                 uint32_t needed;
525                 uint32_t count;
526                 union spoolss_PrintProcessorInfo *info;
527
528                 r.in.servername = "";
529                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
530                 r.in.level = level;
531                 r.in.buffer = NULL;
532                 r.in.offered = 0;
533                 r.out.needed = &needed;
534                 r.out.count = &count;
535                 r.out.info = &info;
536
537                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
538
539                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
540                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
541                 if (W_ERROR_IS_OK(r.out.result)) {
542                         /* TODO: do some more checks here */
543                         continue;
544                 }
545                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
546                         "EnumPrintProcessors unexpected return code");
547
548                 blob = data_blob_talloc(ctx, NULL, needed);
549                 data_blob_clear(&blob);
550                 r.in.buffer = &blob;
551                 r.in.offered = needed;
552
553                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
554                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
555
556                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
557
558                 ctx->print_processor_count[level]       = count;
559                 ctx->print_processors[level]            = info;
560         }
561
562         for (i=1;i<ARRAY_SIZE(levels);i++) {
563                 int level = levels[i];
564                 int old_level = levels[i-1];
565                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
566                         "EnumPrintProcessors failed");
567         }
568
569         for (i=0;i<ARRAY_SIZE(levels);i++) {
570                 int level = levels[i];
571                 for (j=0;j<ctx->print_processor_count[level];j++) {
572 #if 0
573                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
574                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
575 #endif
576                         switch (level) {
577                         case 1:
578                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
579                                 break;
580                         }
581                 }
582         }
583
584         return true;
585 }
586
587 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
588                                         struct dcerpc_pipe *p,
589                                         struct test_spoolss_context *ctx)
590 {
591         NTSTATUS status;
592         struct spoolss_EnumPrintProcDataTypes r;
593         uint16_t levels[] = { 1 };
594         int i;
595
596         for (i=0;i<ARRAY_SIZE(levels);i++) {
597                 int level = levels[i];
598                 DATA_BLOB blob;
599                 uint32_t needed;
600                 uint32_t count;
601                 union spoolss_PrintProcDataTypesInfo *info;
602
603                 r.in.servername = "";
604                 r.in.print_processor_name = "winprint";
605                 r.in.level = level;
606                 r.in.buffer = NULL;
607                 r.in.offered = 0;
608                 r.out.needed = &needed;
609                 r.out.count = &count;
610                 r.out.info = &info;
611
612                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
613
614                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
615                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
616                 if (W_ERROR_IS_OK(r.out.result)) {
617                         /* TODO: do some more checks here */
618                         continue;
619                 }
620                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
621                         "EnumPrintProcDataTypes unexpected return code");
622
623                 blob = data_blob_talloc(ctx, NULL, needed);
624                 data_blob_clear(&blob);
625                 r.in.buffer = &blob;
626                 r.in.offered = needed;
627
628                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
629                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
630
631                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
632         }
633
634         return true;
635 }
636
637
638 static bool test_EnumPrinters(struct torture_context *tctx,
639                               struct dcerpc_pipe *p,
640                               struct test_spoolss_context *ctx)
641 {
642         struct spoolss_EnumPrinters r;
643         NTSTATUS status;
644         uint16_t levels[] = { 0, 1, 2, 4, 5 };
645         int i, j;
646
647         for (i=0;i<ARRAY_SIZE(levels);i++) {
648                 int level = levels[i];
649                 DATA_BLOB blob;
650                 uint32_t needed;
651                 uint32_t count;
652                 union spoolss_PrinterInfo *info;
653
654                 r.in.flags      = PRINTER_ENUM_LOCAL;
655                 r.in.server     = "";
656                 r.in.level      = level;
657                 r.in.buffer     = NULL;
658                 r.in.offered    = 0;
659                 r.out.needed    = &needed;
660                 r.out.count     = &count;
661                 r.out.info      = &info;
662
663                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
664
665                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
666                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
667                 if (W_ERROR_IS_OK(r.out.result)) {
668                         /* TODO: do some more checks here */
669                         continue;
670                 }
671                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
672                         "EnumPrinters unexpected return code");
673
674                 blob = data_blob_talloc(ctx, NULL, needed);
675                 data_blob_clear(&blob);
676                 r.in.buffer = &blob;
677                 r.in.offered = needed;
678
679                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
680                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
681
682                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
683
684                 ctx->printer_count[level]       = count;
685                 ctx->printers[level]            = info;
686         }
687
688         for (i=1;i<ARRAY_SIZE(levels);i++) {
689                 int level = levels[i];
690                 int old_level = levels[i-1];
691                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
692                                          "EnumPrinters invalid value");
693         }
694
695         for (i=0;i<ARRAY_SIZE(levels);i++) {
696                 int level = levels[i];
697                 for (j=0;j<ctx->printer_count[level];j++) {
698                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
699                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
700                         switch (level) {
701                         case 0:
702                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
703                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
704                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
705                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
706                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
707                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
708                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
709                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
710                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
711                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
712                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
713                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
714                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
715                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
716                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
717                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
718                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
719                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
720                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
721                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
722                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
723                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
724                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
725                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
726                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
727                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
728                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
729                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
730                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
731                                 break;
732                         case 1:
733                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
734                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
735                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
736                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
737                                 break;
738                         case 2:
739                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
740                                 break;
741                         case 4:
742                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
743                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
744                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
745                                 break;
746                         case 5:
747                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
748                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
749                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
750                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
751                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
752                                 break;
753                         }
754                 }
755         }
756
757         /* TODO:
758          *      - verify that the port of a printer was in the list returned by EnumPorts
759          */
760
761         return true;
762 }
763
764 static bool test_GetPrinter(struct torture_context *tctx,
765                             struct dcerpc_pipe *p,
766                      struct policy_handle *handle)
767 {
768         NTSTATUS status;
769         struct spoolss_GetPrinter r;
770         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
771         int i;
772         uint32_t needed;
773
774         for (i=0;i<ARRAY_SIZE(levels);i++) {
775                 r.in.handle = handle;
776                 r.in.level = levels[i];
777                 r.in.buffer = NULL;
778                 r.in.offered = 0;
779                 r.out.needed = &needed;
780
781                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
782
783                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
784                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
785
786                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
787                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
788                         data_blob_clear(&blob);
789                         r.in.buffer = &blob;
790                         r.in.offered = needed;
791                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
792                 }
793
794                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
795
796                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
797         }
798
799         return true;
800 }
801
802 static bool test_SetPrinter_errors(struct torture_context *tctx,
803                                    struct dcerpc_pipe *p,
804                                    struct policy_handle *handle)
805 {
806         struct spoolss_SetPrinter r;
807         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
808         int i;
809
810         struct spoolss_SetPrinterInfoCtr info_ctr;
811         struct spoolss_DevmodeContainer devmode_ctr;
812         struct sec_desc_buf secdesc_ctr;
813
814         info_ctr.level = 0;
815         info_ctr.info.info0 = NULL;
816
817         ZERO_STRUCT(devmode_ctr);
818         ZERO_STRUCT(secdesc_ctr);
819
820         r.in.handle = handle;
821         r.in.info_ctr = &info_ctr;
822         r.in.devmode_ctr = &devmode_ctr;
823         r.in.secdesc_ctr = &secdesc_ctr;
824         r.in.command = 0;
825
826         torture_comment(tctx, "Testing SetPrinter all zero\n");
827
828         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
829                 "failed to call SetPrinter");
830         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
831                 "failed to call SetPrinter");
832
833  again:
834         for (i=0; i < ARRAY_SIZE(levels); i++) {
835
836                 struct spoolss_SetPrinterInfo0 info0;
837                 struct spoolss_SetPrinterInfo1 info1;
838                 struct spoolss_SetPrinterInfo2 info2;
839                 struct spoolss_SetPrinterInfo3 info3;
840                 struct spoolss_SetPrinterInfo4 info4;
841                 struct spoolss_SetPrinterInfo5 info5;
842                 struct spoolss_SetPrinterInfo6 info6;
843                 struct spoolss_SetPrinterInfo7 info7;
844                 struct spoolss_DeviceModeInfo info8;
845                 struct spoolss_DeviceModeInfo info9;
846
847
848                 info_ctr.level = levels[i];
849                 switch (levels[i]) {
850                 case 0:
851                         ZERO_STRUCT(info0);
852                         info_ctr.info.info0 = &info0;
853                         break;
854                 case 1:
855                         ZERO_STRUCT(info1);
856                         info_ctr.info.info1 = &info1;
857                         break;
858                 case 2:
859                         ZERO_STRUCT(info2);
860                         info_ctr.info.info2 = &info2;
861                         break;
862                 case 3:
863                         ZERO_STRUCT(info3);
864                         info_ctr.info.info3 = &info3;
865                         break;
866                 case 4:
867                         ZERO_STRUCT(info4);
868                         info_ctr.info.info4 = &info4;
869                         break;
870                 case 5:
871                         ZERO_STRUCT(info5);
872                         info_ctr.info.info5 = &info5;
873                         break;
874                 case 6:
875                         ZERO_STRUCT(info6);
876                         info_ctr.info.info6 = &info6;
877                         break;
878                 case 7:
879                         ZERO_STRUCT(info7);
880                         info_ctr.info.info7 = &info7;
881                         break;
882                 case 8:
883                         ZERO_STRUCT(info8);
884                         info_ctr.info.info8 = &info8;
885                         break;
886                 case 9:
887                         ZERO_STRUCT(info9);
888                         info_ctr.info.info9 = &info9;
889                         break;
890                 }
891
892                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
893                         info_ctr.level, r.in.command);
894
895                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
896                         "failed to call SetPrinter");
897
898                 switch (r.in.command) {
899                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
900                         /* is ignored for all levels other then 0 */
901                         if (info_ctr.level > 0) {
902                                 /* ignored then */
903                                 break;
904                         }
905                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
906                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
907                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
908                         if (info_ctr.level > 0) {
909                                 /* is invalid for all levels other then 0 */
910                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
911                                         "unexpected error code returned");
912                                 continue;
913                         } else {
914                                 torture_assert_werr_ok(tctx, r.out.result,
915                                         "failed to call SetPrinter with non 0 command");
916                                 continue;
917                         }
918                         break;
919
920                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
921                         /* FIXME: gd needs further investigation */
922                 default:
923                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
924                                 "unexpected error code returned");
925                         continue;
926                 }
927
928                 switch (info_ctr.level) {
929                 case 1:
930                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
931                                 "unexpected error code returned");
932                         break;
933                 case 2:
934                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
935                                 "unexpected error code returned");
936                         break;
937                 case 3:
938                 case 4:
939                 case 5:
940                 case 7:
941                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
942                                 "unexpected error code returned");
943                         break;
944                 case 9:
945                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
946                                 "unexpected error code returned");
947                         break;
948                 default:
949                         torture_assert_werr_ok(tctx, r.out.result,
950                                 "failed to call SetPrinter");
951                         break;
952                 }
953         }
954
955         if (r.in.command < 5) {
956                 r.in.command++;
957                 goto again;
958         }
959
960         return true;
961 }
962
963 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
964 {
965         if ((r->level == 2) && (r->info.info2)) {
966                 r->info.info2->secdesc = NULL;
967                 r->info.info2->devmode = NULL;
968         }
969 }
970
971 static bool test_PrinterInfo(struct torture_context *tctx,
972                              struct dcerpc_pipe *p,
973                              struct policy_handle *handle)
974 {
975         NTSTATUS status;
976         struct spoolss_SetPrinter s;
977         struct spoolss_GetPrinter q;
978         struct spoolss_GetPrinter q0;
979         struct spoolss_SetPrinterInfoCtr info_ctr;
980         union spoolss_PrinterInfo info;
981         struct spoolss_DevmodeContainer devmode_ctr;
982         struct sec_desc_buf secdesc_ctr;
983         uint32_t needed;
984         bool ret = true;
985         int i;
986
987         uint32_t status_list[] = {
988                 /* these do not stick
989                 PRINTER_STATUS_PAUSED,
990                 PRINTER_STATUS_ERROR,
991                 PRINTER_STATUS_PENDING_DELETION, */
992                 PRINTER_STATUS_PAPER_JAM,
993                 PRINTER_STATUS_PAPER_OUT,
994                 PRINTER_STATUS_MANUAL_FEED,
995                 PRINTER_STATUS_PAPER_PROBLEM,
996                 PRINTER_STATUS_OFFLINE,
997                 PRINTER_STATUS_IO_ACTIVE,
998                 PRINTER_STATUS_BUSY,
999                 PRINTER_STATUS_PRINTING,
1000                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1001                 PRINTER_STATUS_NOT_AVAILABLE,
1002                 PRINTER_STATUS_WAITING,
1003                 PRINTER_STATUS_PROCESSING,
1004                 PRINTER_STATUS_INITIALIZING,
1005                 PRINTER_STATUS_WARMING_UP,
1006                 PRINTER_STATUS_TONER_LOW,
1007                 PRINTER_STATUS_NO_TONER,
1008                 PRINTER_STATUS_PAGE_PUNT,
1009                 PRINTER_STATUS_USER_INTERVENTION,
1010                 PRINTER_STATUS_OUT_OF_MEMORY,
1011                 PRINTER_STATUS_DOOR_OPEN,
1012                 PRINTER_STATUS_SERVER_UNKNOWN,
1013                 PRINTER_STATUS_POWER_SAVE,
1014                 /* these do not stick
1015                 0x02000000,
1016                 0x04000000,
1017                 0x08000000,
1018                 0x10000000,
1019                 0x20000000,
1020                 0x40000000,
1021                 0x80000000 */
1022         };
1023         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1024         uint32_t attribute_list[] = {
1025                 PRINTER_ATTRIBUTE_QUEUED,
1026                 /* fails with WERR_INVALID_DATATYPE:
1027                 PRINTER_ATTRIBUTE_DIRECT, */
1028                 /* does not stick
1029                 PRINTER_ATTRIBUTE_DEFAULT, */
1030                 PRINTER_ATTRIBUTE_SHARED,
1031                 /* does not stick
1032                 PRINTER_ATTRIBUTE_NETWORK, */
1033                 PRINTER_ATTRIBUTE_HIDDEN,
1034                 PRINTER_ATTRIBUTE_LOCAL,
1035                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1036                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1037                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1038                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1039                 /* does not stick
1040                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1041                 /* fails with WERR_INVALID_DATATYPE:
1042                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1043                 /* these do not stick
1044                 PRINTER_ATTRIBUTE_PUBLISHED,
1045                 PRINTER_ATTRIBUTE_FAX,
1046                 PRINTER_ATTRIBUTE_TS,
1047                 0x00010000,
1048                 0x00020000,
1049                 0x00040000,
1050                 0x00080000,
1051                 0x00100000,
1052                 0x00200000,
1053                 0x00400000,
1054                 0x00800000,
1055                 0x01000000,
1056                 0x02000000,
1057                 0x04000000,
1058                 0x08000000,
1059                 0x10000000,
1060                 0x20000000,
1061                 0x40000000,
1062                 0x80000000 */
1063         };
1064
1065         ZERO_STRUCT(devmode_ctr);
1066         ZERO_STRUCT(secdesc_ctr);
1067
1068         s.in.handle = handle;
1069         s.in.command = 0;
1070         s.in.info_ctr = &info_ctr;
1071         s.in.devmode_ctr = &devmode_ctr;
1072         s.in.secdesc_ctr = &secdesc_ctr;
1073
1074         q.in.handle = handle;
1075         q.out.info = &info;
1076         q0 = q;
1077
1078 #define TESTGETCALL(call, r) \
1079                 r.in.buffer = NULL; \
1080                 r.in.offered = 0;\
1081                 r.out.needed = &needed; \
1082                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1083                 if (!NT_STATUS_IS_OK(status)) { \
1084                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1085                                r.in.level, nt_errstr(status), __location__); \
1086                         ret = false; \
1087                         break; \
1088                 }\
1089                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1090                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1091                         data_blob_clear(&blob); \
1092                         r.in.buffer = &blob; \
1093                         r.in.offered = needed; \
1094                 }\
1095                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1096                 if (!NT_STATUS_IS_OK(status)) { \
1097                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1098                                r.in.level, nt_errstr(status), __location__); \
1099                         ret = false; \
1100                         break; \
1101                 } \
1102                 if (!W_ERROR_IS_OK(r.out.result)) { \
1103                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1104                                r.in.level, win_errstr(r.out.result), __location__); \
1105                         ret = false; \
1106                         break; \
1107                 }
1108
1109
1110 #define TESTSETCALL_EXP(call, r, err) \
1111                 clear_info2(&info_ctr);\
1112                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1113                 if (!NT_STATUS_IS_OK(status)) { \
1114                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1115                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1116                         ret = false; \
1117                         break; \
1118                 } \
1119                 if (!W_ERROR_IS_OK(err)) { \
1120                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1121                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1122                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1123                                 ret = false; \
1124                         } \
1125                         break; \
1126                 } \
1127                 if (!W_ERROR_IS_OK(r.out.result)) { \
1128                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1129                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1130                         ret = false; \
1131                         break; \
1132                 }
1133
1134 #define TESTSETCALL(call, r) \
1135         TESTSETCALL_EXP(call, r, WERR_OK)
1136
1137 #define STRING_EQUAL(s1, s2, field) \
1138                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1139                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1140                                #field, s2, __location__); \
1141                         ret = false; \
1142                         break; \
1143                 }
1144
1145 #define MEM_EQUAL(s1, s2, length, field) \
1146                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1147                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1148                                #field, (const char *)s2, __location__); \
1149                         ret = false; \
1150                         break; \
1151                 }
1152
1153 #define INT_EQUAL(i1, i2, field) \
1154                 if (i1 != i2) { \
1155                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1156                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1157                         ret = false; \
1158                         break; \
1159                 }
1160
1161 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1162                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1163                 q.in.level = lvl1; \
1164                 TESTGETCALL(GetPrinter, q) \
1165                 info_ctr.level = lvl1; \
1166                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1167                 info_ctr.info.info ## lvl1->field1 = value;\
1168                 TESTSETCALL_EXP(SetPrinter, s, err) \
1169                 info_ctr.info.info ## lvl1->field1 = ""; \
1170                 TESTGETCALL(GetPrinter, q) \
1171                 info_ctr.info.info ## lvl1->field1 = value; \
1172                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1173                 q.in.level = lvl2; \
1174                 TESTGETCALL(GetPrinter, q) \
1175                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1176                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1177         } while (0)
1178
1179 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1180         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1181         } while (0);
1182
1183 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1184                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1185                 q.in.level = lvl1; \
1186                 TESTGETCALL(GetPrinter, q) \
1187                 info_ctr.level = lvl1; \
1188                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1189                 info_ctr.info.info ## lvl1->field1 = value; \
1190                 TESTSETCALL(SetPrinter, s) \
1191                 info_ctr.info.info ## lvl1->field1 = 0; \
1192                 TESTGETCALL(GetPrinter, q) \
1193                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1194                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1195                 q.in.level = lvl2; \
1196                 TESTGETCALL(GetPrinter, q) \
1197                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1198                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1199         } while (0)
1200
1201 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1202         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1203         } while (0)
1204
1205         q0.in.level = 0;
1206         do { TESTGETCALL(GetPrinter, q0) } while (0);
1207
1208         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1209         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1210
1211         /* level 0 printername does not stick */
1212 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1213         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1214         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1215         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1216         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1217 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1218         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1219         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1220         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1221         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1222 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1223         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1224         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1225         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1226         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1227
1228         /* servername can be set but does not stick
1229         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1230         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1231         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1232         */
1233
1234         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1235         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1236         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1237         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1238         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1239
1240         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1241         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1242         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1243         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1244         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1245         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1246         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1247         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1248         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1249         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1250
1251         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1252 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1253                         attribute_list[i],
1254                         (attribute_list[i] | default_attribute)
1255                         ); */
1256                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1257                         attribute_list[i],
1258                         (attribute_list[i] | default_attribute)
1259                         );
1260                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1261                         attribute_list[i],
1262                         (attribute_list[i] | default_attribute)
1263                         );
1264                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1265                         attribute_list[i],
1266                         (attribute_list[i] | default_attribute)
1267                         );
1268 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1269                         attribute_list[i],
1270                         (attribute_list[i] | default_attribute)
1271                         ); */
1272                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1273                         attribute_list[i],
1274                         (attribute_list[i] | default_attribute)
1275                         );
1276                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1277                         attribute_list[i],
1278                         (attribute_list[i] | default_attribute)
1279                         );
1280                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1281                         attribute_list[i],
1282                         (attribute_list[i] | default_attribute)
1283                         );
1284 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1285                         attribute_list[i],
1286                         (attribute_list[i] | default_attribute)
1287                         ); */
1288                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1289                         attribute_list[i],
1290                         (attribute_list[i] | default_attribute)
1291                         );
1292                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1293                         attribute_list[i],
1294                         (attribute_list[i] | default_attribute)
1295                         );
1296                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1297                         attribute_list[i],
1298                         (attribute_list[i] | default_attribute)
1299                         );
1300         }
1301
1302         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1303                 /* level 2 sets do not stick
1304                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1305                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1306                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1307                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1308                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1309                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1310         }
1311
1312         /* priorities need to be between 0 and 99
1313            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1314         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1315         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1316         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1317         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1318         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1319         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1320         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1321         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1322
1323         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1324         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1325
1326         /* does not stick
1327         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1328         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1329
1330         /* does not stick
1331         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1332         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1333
1334         /* FIXME: gd also test devmode and secdesc behavior */
1335
1336         {
1337                 /* verify composition of level 1 description field */
1338                 const char *description;
1339                 const char *tmp;
1340
1341                 q0.in.level = 1;
1342                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1343
1344                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1345
1346                 q0.in.level = 2;
1347                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1348
1349                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1350                         q0.out.info->info2.printername,
1351                         q0.out.info->info2.drivername,
1352                         q0.out.info->info2.location);
1353
1354                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1355         }
1356
1357         return ret;
1358 }
1359
1360
1361 static bool test_ClosePrinter(struct torture_context *tctx,
1362                               struct dcerpc_pipe *p,
1363                               struct policy_handle *handle)
1364 {
1365         NTSTATUS status;
1366         struct spoolss_ClosePrinter r;
1367
1368         r.in.handle = handle;
1369         r.out.handle = handle;
1370
1371         torture_comment(tctx, "Testing ClosePrinter\n");
1372
1373         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1374         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1375         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1376
1377         return true;
1378 }
1379
1380 static bool test_GetForm(struct torture_context *tctx,
1381                          struct dcerpc_pipe *p,
1382                          struct policy_handle *handle,
1383                          const char *form_name,
1384                          uint32_t level)
1385 {
1386         NTSTATUS status;
1387         struct spoolss_GetForm r;
1388         uint32_t needed;
1389
1390         r.in.handle = handle;
1391         r.in.form_name = form_name;
1392         r.in.level = level;
1393         r.in.buffer = NULL;
1394         r.in.offered = 0;
1395         r.out.needed = &needed;
1396
1397         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1398
1399         status = dcerpc_spoolss_GetForm(p, tctx, &r);
1400         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1401
1402         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1403                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1404                 data_blob_clear(&blob);
1405                 r.in.buffer = &blob;
1406                 r.in.offered = needed;
1407                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1408                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1409
1410                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1411
1412                 torture_assert(tctx, r.out.info, "No form info returned");
1413         }
1414
1415         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1416
1417         return true;
1418 }
1419
1420 static bool test_EnumForms(struct torture_context *tctx,
1421                            struct dcerpc_pipe *p,
1422                            struct policy_handle *handle, bool print_server)
1423 {
1424         NTSTATUS status;
1425         struct spoolss_EnumForms r;
1426         bool ret = true;
1427         uint32_t needed;
1428         uint32_t count;
1429         uint32_t levels[] = { 1, 2 };
1430         int i;
1431
1432         for (i=0; i<ARRAY_SIZE(levels); i++) {
1433
1434                 union spoolss_FormInfo *info;
1435
1436                 r.in.handle = handle;
1437                 r.in.level = levels[i];
1438                 r.in.buffer = NULL;
1439                 r.in.offered = 0;
1440                 r.out.needed = &needed;
1441                 r.out.count = &count;
1442                 r.out.info = &info;
1443
1444                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1445
1446                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1447                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1448
1449                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1450                         break;
1451                 }
1452
1453                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1454                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1455
1456                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1457                         int j;
1458                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1459                         data_blob_clear(&blob);
1460                         r.in.buffer = &blob;
1461                         r.in.offered = needed;
1462
1463                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1464
1465                         torture_assert(tctx, info, "No forms returned");
1466
1467                         for (j = 0; j < count; j++) {
1468                                 if (!print_server)
1469                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1470                         }
1471                 }
1472
1473                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1474
1475                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1476         }
1477
1478         return true;
1479 }
1480
1481 static bool test_DeleteForm(struct torture_context *tctx,
1482                             struct dcerpc_pipe *p,
1483                             struct policy_handle *handle,
1484                             const char *form_name)
1485 {
1486         NTSTATUS status;
1487         struct spoolss_DeleteForm r;
1488
1489         r.in.handle = handle;
1490         r.in.form_name = form_name;
1491
1492         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1493
1494         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1495
1496         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1497
1498         return true;
1499 }
1500
1501 static bool test_AddForm(struct torture_context *tctx,
1502                          struct dcerpc_pipe *p,
1503                          struct policy_handle *handle, bool print_server)
1504 {
1505         struct spoolss_AddForm r;
1506         struct spoolss_AddFormInfo1 addform;
1507         const char *form_name = "testform3";
1508         NTSTATUS status;
1509         bool ret = true;
1510
1511         r.in.handle     = handle;
1512         r.in.level      = 1;
1513         r.in.info.info1 = &addform;
1514         addform.flags           = SPOOLSS_FORM_USER;
1515         addform.form_name       = form_name;
1516         addform.size.width      = 50;
1517         addform.size.height     = 25;
1518         addform.area.left       = 5;
1519         addform.area.top        = 10;
1520         addform.area.right      = 45;
1521         addform.area.bottom     = 15;
1522
1523         status = dcerpc_spoolss_AddForm(p, tctx, &r);
1524
1525         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1526
1527         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1528
1529         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1530
1531         {
1532                 struct spoolss_SetForm sf;
1533                 struct spoolss_AddFormInfo1 setform;
1534
1535                 sf.in.handle    = handle;
1536                 sf.in.form_name = form_name;
1537                 sf.in.level     = 1;
1538                 sf.in.info.info1= &setform;
1539                 setform.flags           = addform.flags;
1540                 setform.form_name       = addform.form_name;
1541                 setform.size            = addform.size;
1542                 setform.area            = addform.area;
1543
1544                 setform.size.width      = 1234;
1545
1546                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1547
1548                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1549
1550                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1551         }
1552
1553         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1554
1555         {
1556                 struct spoolss_EnumForms e;
1557                 union spoolss_FormInfo *info;
1558                 uint32_t needed;
1559                 uint32_t count;
1560                 bool found = false;
1561
1562                 e.in.handle = handle;
1563                 e.in.level = 1;
1564                 e.in.buffer = NULL;
1565                 e.in.offered = 0;
1566                 e.out.needed = &needed;
1567                 e.out.count = &count;
1568                 e.out.info = &info;
1569
1570                 torture_comment(tctx, "Testing EnumForms level 1\n");
1571
1572                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1573                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1574
1575                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1576                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1577
1578                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1579                         int j;
1580                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1581                         data_blob_clear(&blob);
1582                         e.in.buffer = &blob;
1583                         e.in.offered = needed;
1584
1585                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1586
1587                         torture_assert(tctx, info, "No forms returned");
1588
1589                         for (j = 0; j < count; j++) {
1590                                 if (strequal(form_name, info[j].info1.form_name)) {
1591                                         found = true;
1592                                         break;
1593                                 }
1594                         }
1595                 }
1596                 torture_assert(tctx, found, "Newly added form not found in enum call");
1597         }
1598
1599         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1600                 ret = false;
1601         }
1602
1603         return ret;
1604 }
1605
1606 static bool test_EnumPorts_old(struct torture_context *tctx,
1607                                struct dcerpc_pipe *p)
1608 {
1609         NTSTATUS status;
1610         struct spoolss_EnumPorts r;
1611         uint32_t needed;
1612         uint32_t count;
1613         union spoolss_PortInfo *info;
1614
1615         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1616                                           dcerpc_server_name(p));
1617         r.in.level = 2;
1618         r.in.buffer = NULL;
1619         r.in.offered = 0;
1620         r.out.needed = &needed;
1621         r.out.count = &count;
1622         r.out.info = &info;
1623
1624         torture_comment(tctx, "Testing EnumPorts\n");
1625
1626         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1627
1628         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1629
1630         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1631                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1632                 data_blob_clear(&blob);
1633                 r.in.buffer = &blob;
1634                 r.in.offered = needed;
1635
1636                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1637                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1638                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1639
1640                 torture_assert(tctx, info, "No ports returned");
1641         }
1642
1643         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1644
1645         return true;
1646 }
1647
1648 static bool test_AddPort(struct torture_context *tctx,
1649                          struct dcerpc_pipe *p)
1650 {
1651         NTSTATUS status;
1652         struct spoolss_AddPort r;
1653
1654         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1655                                            dcerpc_server_name(p));
1656         r.in.unknown = 0;
1657         r.in.monitor_name = "foo";
1658
1659         torture_comment(tctx, "Testing AddPort\n");
1660
1661         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1662
1663         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1664
1665         /* win2k3 returns WERR_NOT_SUPPORTED */
1666
1667 #if 0
1668
1669         if (!W_ERROR_IS_OK(r.out.result)) {
1670                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1671                 return false;
1672         }
1673
1674 #endif
1675
1676         return true;
1677 }
1678
1679 static bool test_GetJob(struct torture_context *tctx,
1680                         struct dcerpc_pipe *p,
1681                         struct policy_handle *handle, uint32_t job_id)
1682 {
1683         NTSTATUS status;
1684         struct spoolss_GetJob r;
1685         union spoolss_JobInfo info;
1686         uint32_t needed;
1687         uint32_t levels[] = {1, 2 /* 3, 4 */};
1688         uint32_t i;
1689
1690         r.in.handle = handle;
1691         r.in.job_id = job_id;
1692         r.in.level = 0;
1693         r.in.buffer = NULL;
1694         r.in.offered = 0;
1695         r.out.needed = &needed;
1696         r.out.info = &info;
1697
1698         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1699
1700         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1701         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1702
1703         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1704
1705                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1706
1707                 needed = 0;
1708
1709                 r.in.level = levels[i];
1710                 r.in.offered = 0;
1711                 r.in.buffer = NULL;
1712
1713                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1714                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1715
1716                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1717                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1718                         data_blob_clear(&blob);
1719                         r.in.buffer = &blob;
1720                         r.in.offered = needed;
1721
1722                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1723                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1724
1725                 }
1726                 torture_assert(tctx, r.out.info, "No job info returned");
1727                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1728         }
1729
1730         return true;
1731 }
1732
1733 static bool test_SetJob(struct torture_context *tctx,
1734                         struct dcerpc_pipe *p,
1735                         struct policy_handle *handle, uint32_t job_id,
1736                         enum spoolss_JobControl command)
1737 {
1738         NTSTATUS status;
1739         struct spoolss_SetJob r;
1740
1741         r.in.handle     = handle;
1742         r.in.job_id     = job_id;
1743         r.in.ctr        = NULL;
1744         r.in.command    = command;
1745
1746         switch (command) {
1747         case SPOOLSS_JOB_CONTROL_PAUSE:
1748                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1749                 break;
1750         case SPOOLSS_JOB_CONTROL_RESUME:
1751                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1752                 break;
1753         case SPOOLSS_JOB_CONTROL_CANCEL:
1754                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1755                 break;
1756         case SPOOLSS_JOB_CONTROL_RESTART:
1757                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1758                 break;
1759         case SPOOLSS_JOB_CONTROL_DELETE:
1760                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1761                 break;
1762         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1763                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1764                 break;
1765         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1766                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1767                 break;
1768         case SPOOLSS_JOB_CONTROL_RETAIN:
1769                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1770                 break;
1771         case SPOOLSS_JOB_CONTROL_RELEASE:
1772                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1773                 break;
1774         default:
1775                 torture_comment(tctx, "Testing SetJob\n");
1776                 break;
1777         }
1778
1779         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1780         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1781         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1782
1783         return true;
1784 }
1785
1786 static bool test_AddJob(struct torture_context *tctx,
1787                         struct dcerpc_pipe *p,
1788                         struct policy_handle *handle)
1789 {
1790         NTSTATUS status;
1791         struct spoolss_AddJob r;
1792         uint32_t needed;
1793
1794         r.in.level = 0;
1795         r.in.handle = handle;
1796         r.in.offered = 0;
1797         r.out.needed = &needed;
1798         r.in.buffer = r.out.buffer = NULL;
1799
1800         torture_comment(tctx, "Testing AddJob\n");
1801
1802         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1803         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1804
1805         r.in.level = 1;
1806
1807         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1808         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1809
1810         return true;
1811 }
1812
1813
1814 static bool test_EnumJobs(struct torture_context *tctx,
1815                           struct dcerpc_pipe *p,
1816                           struct policy_handle *handle)
1817 {
1818         NTSTATUS status;
1819         struct spoolss_EnumJobs r;
1820         uint32_t needed;
1821         uint32_t count;
1822         union spoolss_JobInfo *info;
1823
1824         r.in.handle = handle;
1825         r.in.firstjob = 0;
1826         r.in.numjobs = 0xffffffff;
1827         r.in.level = 1;
1828         r.in.buffer = NULL;
1829         r.in.offered = 0;
1830         r.out.needed = &needed;
1831         r.out.count = &count;
1832         r.out.info = &info;
1833
1834         torture_comment(tctx, "Testing EnumJobs\n");
1835
1836         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1837
1838         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1839
1840         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1841                 int j;
1842                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1843                 data_blob_clear(&blob);
1844                 r.in.buffer = &blob;
1845                 r.in.offered = needed;
1846
1847                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1848
1849                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1850                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1851                 torture_assert(tctx, info, "No jobs returned");
1852
1853                 for (j = 0; j < count; j++) {
1854
1855                         torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
1856                                 "failed to call test_GetJob");
1857
1858                         /* FIXME - gd */
1859                         if (!torture_setting_bool(tctx, "samba3", false)) {
1860                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1861                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1862                         }
1863                 }
1864
1865         } else {
1866                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1867         }
1868
1869         return true;
1870 }
1871
1872 static bool test_DoPrintTest(struct torture_context *tctx,
1873                              struct dcerpc_pipe *p,
1874                              struct policy_handle *handle)
1875 {
1876         bool ret = true;
1877         NTSTATUS status;
1878         struct spoolss_StartDocPrinter s;
1879         struct spoolss_DocumentInfo1 info1;
1880         struct spoolss_StartPagePrinter sp;
1881         struct spoolss_WritePrinter w;
1882         struct spoolss_EndPagePrinter ep;
1883         struct spoolss_EndDocPrinter e;
1884         int i;
1885         uint32_t job_id;
1886         uint32_t num_written;
1887
1888         torture_comment(tctx, "Testing StartDocPrinter\n");
1889
1890         s.in.handle             = handle;
1891         s.in.level              = 1;
1892         s.in.info.info1         = &info1;
1893         s.out.job_id            = &job_id;
1894         info1.document_name     = "TorturePrintJob";
1895         info1.output_file       = NULL;
1896         info1.datatype          = "RAW";
1897
1898         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1899         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1900         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1901
1902         for (i=1; i < 4; i++) {
1903                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1904
1905                 sp.in.handle            = handle;
1906
1907                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1908                 torture_assert_ntstatus_ok(tctx, status,
1909                                            "dcerpc_spoolss_StartPagePrinter failed");
1910                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1911
1912                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1913
1914                 w.in.handle             = handle;
1915                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1916                 w.out.num_written       = &num_written;
1917
1918                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1919                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1920                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1921
1922                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1923
1924                 ep.in.handle            = handle;
1925
1926                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1927                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1928                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1929         }
1930
1931         torture_comment(tctx, "Testing EndDocPrinter\n");
1932
1933         e.in.handle = handle;
1934
1935         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1936         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1937         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1938
1939         ret &= test_AddJob(tctx, p, handle);
1940         ret &= test_EnumJobs(tctx, p, handle);
1941
1942         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1943
1944         return ret;
1945 }
1946
1947 static bool test_PausePrinter(struct torture_context *tctx,
1948                               struct dcerpc_pipe *p,
1949                               struct policy_handle *handle)
1950 {
1951         NTSTATUS status;
1952         struct spoolss_SetPrinter r;
1953         struct spoolss_SetPrinterInfoCtr info_ctr;
1954         struct spoolss_DevmodeContainer devmode_ctr;
1955         struct sec_desc_buf secdesc_ctr;
1956
1957         info_ctr.level = 0;
1958         info_ctr.info.info0 = NULL;
1959
1960         ZERO_STRUCT(devmode_ctr);
1961         ZERO_STRUCT(secdesc_ctr);
1962
1963         r.in.handle             = handle;
1964         r.in.info_ctr           = &info_ctr;
1965         r.in.devmode_ctr        = &devmode_ctr;
1966         r.in.secdesc_ctr        = &secdesc_ctr;
1967         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1968
1969         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1970
1971         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1972
1973         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1974
1975         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1976
1977         return true;
1978 }
1979
1980 static bool test_ResumePrinter(struct torture_context *tctx,
1981                                struct dcerpc_pipe *p,
1982                                struct policy_handle *handle)
1983 {
1984         NTSTATUS status;
1985         struct spoolss_SetPrinter r;
1986         struct spoolss_SetPrinterInfoCtr info_ctr;
1987         struct spoolss_DevmodeContainer devmode_ctr;
1988         struct sec_desc_buf secdesc_ctr;
1989
1990         info_ctr.level = 0;
1991         info_ctr.info.info0 = NULL;
1992
1993         ZERO_STRUCT(devmode_ctr);
1994         ZERO_STRUCT(secdesc_ctr);
1995
1996         r.in.handle             = handle;
1997         r.in.info_ctr           = &info_ctr;
1998         r.in.devmode_ctr        = &devmode_ctr;
1999         r.in.secdesc_ctr        = &secdesc_ctr;
2000         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
2001
2002         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2003
2004         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2005
2006         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2007
2008         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2009
2010         return true;
2011 }
2012
2013 static bool test_GetPrinterData(struct torture_context *tctx,
2014                                 struct dcerpc_pipe *p,
2015                                 struct policy_handle *handle,
2016                                 const char *value_name)
2017 {
2018         NTSTATUS status;
2019         struct spoolss_GetPrinterData r;
2020         uint32_t needed;
2021         enum winreg_Type type;
2022         union spoolss_PrinterData data;
2023
2024         r.in.handle = handle;
2025         r.in.value_name = value_name;
2026         r.in.offered = 0;
2027         r.out.needed = &needed;
2028         r.out.type = &type;
2029         r.out.data = &data;
2030
2031         torture_comment(tctx, "Testing GetPrinterData\n");
2032
2033         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2034         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2035
2036         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2037                 r.in.offered = needed;
2038
2039                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2040                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2041
2042                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2043         }
2044
2045         return true;
2046 }
2047
2048 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2049                                   struct dcerpc_pipe *p,
2050                                   struct policy_handle *handle,
2051                                   const char *key_name,
2052                                   const char *value_name)
2053 {
2054         NTSTATUS status;
2055         struct spoolss_GetPrinterDataEx r;
2056         enum winreg_Type type;
2057         uint32_t needed;
2058
2059         r.in.handle = handle;
2060         r.in.key_name = key_name;
2061         r.in.value_name = value_name;
2062         r.in.offered = 0;
2063         r.out.type = &type;
2064         r.out.needed = &needed;
2065         r.out.buffer = NULL;
2066
2067         torture_comment(tctx, "Testing GetPrinterDataEx\n");
2068
2069         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2072                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2073                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2074                 }
2075                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2076         }
2077
2078         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2079                 r.in.offered = needed;
2080                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2081
2082                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2083                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2084
2085                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
2086         }
2087
2088         return true;
2089 }
2090
2091 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2092                                  struct policy_handle *handle)
2093 {
2094         NTSTATUS status;
2095         struct spoolss_EnumPrinterData r;
2096
2097         ZERO_STRUCT(r);
2098         r.in.handle = handle;
2099         r.in.enum_index = 0;
2100
2101         do {
2102                 uint32_t value_size = 0;
2103                 uint32_t data_size = 0;
2104                 enum winreg_Type type = 0;
2105
2106                 r.in.value_offered = value_size;
2107                 r.out.value_needed = &value_size;
2108                 r.in.data_offered = data_size;
2109                 r.out.data_needed = &data_size;
2110
2111                 r.out.type = &type;
2112                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2113
2114                 torture_comment(tctx, "Testing EnumPrinterData\n");
2115
2116                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2117
2118                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2119                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2120                         break;
2121                 }
2122                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2123
2124                 r.in.value_offered = value_size;
2125                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2126                 r.in.data_offered = data_size;
2127                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2128
2129                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2130
2131                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2132                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2133                         break;
2134                 }
2135
2136                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2137
2138                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name),
2139                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2140
2141                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name),
2142                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2143
2144                 r.in.enum_index++;
2145
2146         } while (W_ERROR_IS_OK(r.out.result));
2147
2148         return true;
2149 }
2150
2151 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2152                                    struct dcerpc_pipe *p,
2153                                    struct policy_handle *handle,
2154                                    const char *key_name)
2155 {
2156         NTSTATUS status;
2157         struct spoolss_EnumPrinterDataEx r;
2158         struct spoolss_PrinterEnumValues *info;
2159         uint32_t needed;
2160         uint32_t count;
2161
2162         r.in.handle = handle;
2163         r.in.key_name = key_name;
2164         r.in.offered = 0;
2165         r.out.needed = &needed;
2166         r.out.count = &count;
2167         r.out.info = &info;
2168
2169         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2170
2171         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2172                 "EnumPrinterDataEx failed");
2173         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2174                 r.in.offered = needed;
2175                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2176                         "EnumPrinterDataEx failed");
2177         }
2178
2179         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2180
2181         return true;
2182 }
2183
2184
2185 static bool test_DeletePrinterData(struct torture_context *tctx,
2186                                    struct dcerpc_pipe *p,
2187                                    struct policy_handle *handle,
2188                                    const char *value_name)
2189 {
2190         NTSTATUS status;
2191         struct spoolss_DeletePrinterData r;
2192
2193         r.in.handle = handle;
2194         r.in.value_name = value_name;
2195
2196         torture_comment(tctx, "Testing DeletePrinterData\n");
2197
2198         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2199
2200         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2201         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2202
2203         return true;
2204 }
2205
2206 static bool test_SetPrinterData(struct torture_context *tctx,
2207                                 struct dcerpc_pipe *p,
2208                                 struct policy_handle *handle)
2209 {
2210         NTSTATUS status;
2211         struct spoolss_SetPrinterData r;
2212         const char *value_name = "spottyfoot";
2213
2214         r.in.handle = handle;
2215         r.in.value_name = value_name;
2216         r.in.type = REG_SZ;
2217         r.in.data.string = "dog";
2218
2219         torture_comment(tctx, "Testing SetPrinterData(%s)\n", value_name);
2220
2221         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2222
2223         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2224         torture_assert_werr_ok(tctx, r.out.result, "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, "PrinterDriverData")) {
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                         torture_assert(tctx, (key_buffer._ndr_size == 0),
3064                                 talloc_asprintf(tctx, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer._ndr_size));
3065
3066                         r.in.offered = needed;
3067                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3068                                 "failed to call EnumPrinterKey");
3069                 }
3070                 torture_assert_werr_ok(tctx, r.out.result,
3071                         "failed to call EnumPrinterKey");
3072
3073                 torture_assert(tctx, (key_buffer._ndr_size * 2 == needed),
3074                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3075                         key_buffer._ndr_size, needed/2));
3076
3077                 key_array = key_buffer.string;
3078         }
3079
3080         for (i=0; key_array && key_array[i]; i++) {
3081                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3082                         "failed to call test_EnumPrinterDataEx");
3083         }
3084
3085         return true;
3086 }
3087
3088 static bool test_printer(struct torture_context *tctx,
3089                          struct dcerpc_pipe *p)
3090 {
3091         bool ret = true;
3092         struct policy_handle handle[2];
3093         bool found = false;
3094         const char *drivername = "Microsoft XPS Document Writer";
3095         const char *portname = "LPT1:";
3096
3097         /* test printer created via AddPrinter */
3098
3099         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3100                 return false;
3101         }
3102
3103         if (!test_printer_info(tctx, p, &handle[0])) {
3104                 ret = false;
3105         }
3106
3107         if (!test_printer_keys(tctx, p, &handle[0])) {
3108                 ret = false;
3109         }
3110
3111         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3112                 ret = false;
3113         }
3114
3115         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3116                                         TORTURE_PRINTER, &found)) {
3117                 ret = false;
3118         }
3119
3120         torture_assert(tctx, !found, "deleted printer still there");
3121
3122         /* test printer created via AddPrinterEx */
3123
3124         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3125                 return false;
3126         }
3127
3128         if (!test_printer_info(tctx, p, &handle[1])) {
3129                 ret = false;
3130         }
3131
3132         if (!test_printer_keys(tctx, p, &handle[1])) {
3133                 ret = false;
3134         }
3135
3136         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3137                 ret = false;
3138         }
3139
3140         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3141                                         TORTURE_PRINTER_EX, &found)) {
3142                 ret = false;
3143         }
3144
3145         torture_assert(tctx, !found, "deleted printer still there");
3146
3147         return ret;
3148 }
3149
3150 bool torture_rpc_spoolss(struct torture_context *torture)
3151 {
3152         NTSTATUS status;
3153         struct dcerpc_pipe *p;
3154         bool ret = true;
3155         struct test_spoolss_context *ctx;
3156
3157         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3158         if (!NT_STATUS_IS_OK(status)) {
3159                 return false;
3160         }
3161
3162         ctx = talloc_zero(torture, struct test_spoolss_context);
3163
3164         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3165
3166         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3167         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3168         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3169         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3170         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3171         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3172         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3173         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3174         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3175         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
3176         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
3177         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
3178         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
3179         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3180         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3181         ret &= test_EnumPorts(torture, p, ctx);
3182         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3183         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3184         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3185         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3186         ret &= test_EnumMonitors(torture, p, ctx);
3187         ret &= test_EnumPrintProcessors(torture, p, ctx);
3188         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3189         ret &= test_EnumPrinters(torture, p, ctx);
3190         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3191         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3192         ret &= test_OpenPrinter_badname(torture, p, "");
3193         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3194         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3195         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3196         ret &= test_OpenPrinter_badname(torture, p,
3197                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3198
3199
3200         ret &= test_AddPort(torture, p);
3201         ret &= test_EnumPorts_old(torture, p);
3202         ret &= test_EnumPrinters_old(torture, p);
3203         ret &= test_EnumPrinterDrivers_old(torture, p);
3204
3205         return ret;
3206 }
3207
3208 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3209 {
3210         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3211
3212         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3213                                                         "printer", &ndr_table_spoolss);
3214
3215         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3216
3217         return suite;
3218 }