6810bf068f88bcec53c9f788c3bf23c4b37a59bd
[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                                 enum winreg_Type *type_p,
2018                                 union spoolss_PrinterData *data_p)
2019 {
2020         NTSTATUS status;
2021         struct spoolss_GetPrinterData r;
2022         uint32_t needed;
2023         enum winreg_Type type;
2024         union spoolss_PrinterData data;
2025
2026         r.in.handle = handle;
2027         r.in.value_name = value_name;
2028         r.in.offered = 0;
2029         r.out.needed = &needed;
2030         r.out.type = &type;
2031         r.out.data = &data;
2032
2033         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2034
2035         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2036         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2037
2038         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2039                 r.in.offered = needed;
2040
2041                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2042                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2043                 /* do not move below WERR_MORE_DATA check, as this test is used
2044                  * for a lot of well known printer server values */
2045                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2046         }
2047
2048         if (type_p) {
2049                 *type_p = type;
2050         }
2051
2052         if (data_p) {
2053                 *data_p = data;
2054         }
2055
2056         return true;
2057 }
2058
2059 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2060                                   struct dcerpc_pipe *p,
2061                                   struct policy_handle *handle,
2062                                   const char *key_name,
2063                                   const char *value_name,
2064                                   enum winreg_Type *type_p,
2065                                   DATA_BLOB *buffer_p)
2066 {
2067         NTSTATUS status;
2068         struct spoolss_GetPrinterDataEx r;
2069         enum winreg_Type type;
2070         uint32_t needed;
2071         uint8_t *buffer;
2072
2073         buffer = talloc_array(tctx, uint8_t, 0);
2074
2075         r.in.handle = handle;
2076         r.in.key_name = key_name;
2077         r.in.value_name = value_name;
2078         r.in.offered = 0;
2079         r.out.type = &type;
2080         r.out.needed = &needed;
2081         r.out.buffer = buffer;
2082
2083         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2084                 r.in.key_name, r.in.value_name);
2085
2086         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2087         if (!NT_STATUS_IS_OK(status)) {
2088                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2089                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2090                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2091                 }
2092                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2093         }
2094
2095         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2096                 r.in.offered = needed;
2097                 buffer = talloc_array(tctx, uint8_t, needed);
2098                 r.out.buffer = buffer;
2099
2100                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2101                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2102         }
2103
2104         torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
2105
2106         if (type_p) {
2107                 *type_p = type;
2108         }
2109
2110         if (buffer_p) {
2111                 *buffer_p = data_blob(buffer, needed);
2112         }
2113
2114         return true;
2115 }
2116
2117 static bool test_GetPrinterData_list(struct torture_context *tctx,
2118                                      struct dcerpc_pipe *p,
2119                                      struct policy_handle *handle)
2120 {
2121         bool ret = true;
2122         const char *list[] = {
2123                 "W3SvcInstalled",
2124                 "BeepEnabled",
2125                 "EventLog",
2126                 "NetPopup",
2127                 "NetPopupToComputer",
2128                 "MajorVersion",
2129                 "MinorVersion",
2130                 "DefaultSpoolDirectory",
2131                 "Architecture",
2132                 "DsPresent",
2133                 "OSVersion",
2134                 "OSVersionEx",
2135                 "DNSMachineName"
2136         };
2137         int i;
2138
2139         for (i=0; i < ARRAY_SIZE(list); i++) {
2140                 ret &= test_GetPrinterData(tctx, p, handle, list[i], NULL, NULL);
2141         }
2142
2143         return ret;
2144 }
2145
2146 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2147                                  struct policy_handle *handle)
2148 {
2149         NTSTATUS status;
2150         struct spoolss_EnumPrinterData r;
2151
2152         ZERO_STRUCT(r);
2153         r.in.handle = handle;
2154         r.in.enum_index = 0;
2155
2156         do {
2157                 uint32_t value_size = 0;
2158                 uint32_t data_size = 0;
2159                 enum winreg_Type type = 0;
2160
2161                 r.in.value_offered = value_size;
2162                 r.out.value_needed = &value_size;
2163                 r.in.data_offered = data_size;
2164                 r.out.data_needed = &data_size;
2165
2166                 r.out.type = &type;
2167                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2168
2169                 torture_comment(tctx, "Testing EnumPrinterData\n");
2170
2171                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2172
2173                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2174                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2175                         break;
2176                 }
2177                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2178
2179                 r.in.value_offered = value_size;
2180                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2181                 r.in.data_offered = data_size;
2182                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2183
2184                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2185
2186                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2187                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2188                         break;
2189                 }
2190
2191                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2192
2193                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2194                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2195
2196                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2197                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2198
2199                 r.in.enum_index++;
2200
2201         } while (W_ERROR_IS_OK(r.out.result));
2202
2203         return true;
2204 }
2205
2206 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2207                                    struct dcerpc_pipe *p,
2208                                    struct policy_handle *handle,
2209                                    const char *key_name)
2210 {
2211         struct spoolss_EnumPrinterDataEx r;
2212         struct spoolss_PrinterEnumValues *info;
2213         uint32_t needed;
2214         uint32_t count;
2215
2216         r.in.handle = handle;
2217         r.in.key_name = key_name;
2218         r.in.offered = 0;
2219         r.out.needed = &needed;
2220         r.out.count = &count;
2221         r.out.info = &info;
2222
2223         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2224
2225         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2226                 "EnumPrinterDataEx failed");
2227         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2228                 r.in.offered = needed;
2229                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2230                         "EnumPrinterDataEx failed");
2231         }
2232
2233         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2234
2235         return true;
2236 }
2237
2238
2239 static bool test_DeletePrinterData(struct torture_context *tctx,
2240                                    struct dcerpc_pipe *p,
2241                                    struct policy_handle *handle,
2242                                    const char *value_name)
2243 {
2244         NTSTATUS status;
2245         struct spoolss_DeletePrinterData r;
2246
2247         r.in.handle = handle;
2248         r.in.value_name = value_name;
2249
2250         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2251                 r.in.value_name);
2252
2253         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2254
2255         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2256         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2257
2258         return true;
2259 }
2260
2261 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2262                                      struct dcerpc_pipe *p,
2263                                      struct policy_handle *handle,
2264                                      const char *key_name,
2265                                      const char *value_name)
2266 {
2267         struct spoolss_DeletePrinterDataEx r;
2268
2269         r.in.handle = handle;
2270         r.in.key_name = key_name;
2271         r.in.value_name = value_name;
2272
2273         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2274                 r.in.key_name, r.in.value_name);
2275
2276         torture_assert_ntstatus_ok(tctx,
2277                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2278                 "DeletePrinterDataEx failed");
2279         torture_assert_werr_ok(tctx, r.out.result,
2280                 "DeletePrinterDataEx failed");
2281
2282         return true;
2283 }
2284
2285 static bool test_DeletePrinterKey(struct torture_context *tctx,
2286                                   struct dcerpc_pipe *p,
2287                                   struct policy_handle *handle,
2288                                   const char *key_name)
2289 {
2290         struct spoolss_DeletePrinterKey r;
2291
2292         r.in.handle = handle;
2293         r.in.key_name = key_name;
2294
2295         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2296
2297         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2298                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2299                 return true;
2300         }
2301
2302         torture_assert_ntstatus_ok(tctx,
2303                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2304                 "DeletePrinterKey failed");
2305         torture_assert_werr_ok(tctx, r.out.result,
2306                 "DeletePrinterKey failed");
2307
2308         return true;
2309 }
2310
2311 static bool test_SetPrinterData(struct torture_context *tctx,
2312                                 struct dcerpc_pipe *p,
2313                                 struct policy_handle *handle)
2314 {
2315         NTSTATUS status;
2316         struct spoolss_SetPrinterData r;
2317         const char *values[] = {
2318                 "spootyfoot",
2319                 "spooty\\foot",
2320                 "spooty,foot",
2321                 "spooty foot"
2322         };
2323         int i;
2324
2325         for (i=0; i < ARRAY_SIZE(values); i++) {
2326
2327                 enum winreg_Type type;
2328                 union spoolss_PrinterData data;
2329
2330                 r.in.handle = handle;
2331                 r.in.value_name = values[i];
2332                 r.in.type = REG_SZ;
2333                 r.in.data.string = "dog";
2334
2335                 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2336                         r.in.value_name);
2337
2338                 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2339
2340                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2341                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2342
2343                 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2344                         return false;
2345                 }
2346
2347                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2348                 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2349
2350                 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2351                         return false;
2352                 }
2353         }
2354
2355         return true;
2356 }
2357
2358 static bool test_EnumPrinterKey(struct torture_context *tctx,
2359                                 struct dcerpc_pipe *p,
2360                                 struct policy_handle *handle,
2361                                 const char *key_name,
2362                                 const char ***array);
2363
2364 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2365                                   struct dcerpc_pipe *p,
2366                                   struct policy_handle *handle)
2367 {
2368         NTSTATUS status;
2369         struct spoolss_SetPrinterDataEx r;
2370         const char *value_name = "dog";
2371         const char *keys[] = {
2372                 "torturedataex",
2373                 "what a wurst",
2374                 "torturedataex_with_subkey\\subkey",
2375                 "torturedataex_with_subkey\\subkey:0",
2376                 "torturedataex_with_subkey\\subkey:1",
2377                 "torturedataex_with_subkey\\subkey\\subsubkey",
2378                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2379                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2380                 "torture,data,ex"
2381         };
2382         int i;
2383         DATA_BLOB blob = data_blob_string_const("catfoobar");
2384
2385
2386         for (i=0; i < ARRAY_SIZE(keys); i++) {
2387
2388                 char *c;
2389                 const char *key;
2390                 enum winreg_Type type;
2391                 DATA_BLOB buffer;
2392                 const char **subkeys;
2393
2394                 r.in.handle = handle;
2395                 r.in.key_name = keys[i];
2396                 r.in.value_name = value_name;
2397                 r.in.type = REG_BINARY;
2398                 r.in.offered = blob.length;
2399                 r.in.buffer = blob.data;
2400
2401                 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2402
2403                 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2404
2405                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2406                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2407
2408                 key = talloc_strdup(tctx, r.in.key_name);
2409
2410                 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &buffer)) {
2411                         return false;
2412                 }
2413
2414                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2415                 torture_assert_data_blob_equal(tctx, blob, buffer, "data mismatch");
2416
2417                 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2418                         return false;
2419                 }
2420
2421                 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2422                         return false;
2423                 }
2424
2425                 c = strchr(key, '\\');
2426                 if (c) {
2427                         int i;
2428
2429                         /* we have subkeys */
2430
2431                         *c = 0;
2432
2433                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2434                                 return false;
2435                         }
2436
2437                         for (i=0; subkeys && subkeys[i]; i++) {
2438
2439                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2440
2441                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2442                                         return false;
2443                                 }
2444                         }
2445
2446                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2447                                 return false;
2448                         }
2449
2450                 } else {
2451                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2452                                 return false;
2453                         }
2454                 }
2455         }
2456
2457         return true;
2458 }
2459
2460
2461 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2462                                        struct dcerpc_pipe *p,
2463                                        struct policy_handle *handle)
2464 {
2465         NTSTATUS status;
2466         struct dcerpc_binding *b;
2467         struct dcerpc_pipe *p2;
2468         struct spoolss_ClosePrinter cp;
2469
2470         /* only makes sense on SMB */
2471         if (p->conn->transport.transport != NCACN_NP) {
2472                 return true;
2473         }
2474
2475         torture_comment(tctx, "testing close on secondary pipe\n");
2476
2477         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2478         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2479
2480         status = dcerpc_secondary_connection(p, &p2, b);
2481         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2482
2483         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2484         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2485
2486         cp.in.handle = handle;
2487         cp.out.handle = handle;
2488
2489         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2490         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2491                         "ERROR: Allowed close on secondary connection");
2492
2493         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2494                                  "Unexpected fault code");
2495
2496         talloc_free(p2);
2497
2498         return true;
2499 }
2500
2501 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2502                                      struct dcerpc_pipe *p, const char *name)
2503 {
2504         NTSTATUS status;
2505         struct spoolss_OpenPrinter op;
2506         struct spoolss_OpenPrinterEx opEx;
2507         struct policy_handle handle;
2508         bool ret = true;
2509
2510         op.in.printername       = name;
2511         op.in.datatype          = NULL;
2512         op.in.devmode_ctr.devmode= NULL;
2513         op.in.access_mask       = 0;
2514         op.out.handle           = &handle;
2515
2516         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2517
2518         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2519         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2520         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2521                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2522                         name, win_errstr(op.out.result));
2523         }
2524
2525         if (W_ERROR_IS_OK(op.out.result)) {
2526                 ret &=test_ClosePrinter(tctx, p, &handle);
2527         }
2528
2529         opEx.in.printername             = name;
2530         opEx.in.datatype                = NULL;
2531         opEx.in.devmode_ctr.devmode     = NULL;
2532         opEx.in.access_mask             = 0;
2533         opEx.in.level                   = 1;
2534         opEx.in.userlevel.level1        = NULL;
2535         opEx.out.handle                 = &handle;
2536
2537         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2538
2539         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2540         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2541         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2542                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2543                         name, win_errstr(opEx.out.result));
2544         }
2545
2546         if (W_ERROR_IS_OK(opEx.out.result)) {
2547                 ret &=test_ClosePrinter(tctx, p, &handle);
2548         }
2549
2550         return ret;
2551 }
2552
2553 static bool test_OpenPrinter(struct torture_context *tctx,
2554                              struct dcerpc_pipe *p,
2555                              const char *name)
2556 {
2557         NTSTATUS status;
2558         struct spoolss_OpenPrinter r;
2559         struct policy_handle handle;
2560         bool ret = true;
2561
2562         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2563         r.in.datatype           = NULL;
2564         r.in.devmode_ctr.devmode= NULL;
2565         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2566         r.out.handle            = &handle;
2567
2568         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2569
2570         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2571
2572         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2573
2574         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2575
2576         if (!test_GetPrinter(tctx, p, &handle)) {
2577                 ret = false;
2578         }
2579
2580         if (!torture_setting_bool(tctx, "samba3", false)) {
2581                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2582                         ret = false;
2583                 }
2584         }
2585
2586         if (!test_ClosePrinter(tctx, p, &handle)) {
2587                 ret = false;
2588         }
2589
2590         return ret;
2591 }
2592
2593 static bool call_OpenPrinterEx(struct torture_context *tctx,
2594                                struct dcerpc_pipe *p,
2595                                const char *name, struct policy_handle *handle)
2596 {
2597         struct spoolss_OpenPrinterEx r;
2598         struct spoolss_UserLevel1 userlevel1;
2599         NTSTATUS status;
2600
2601         if (name && name[0]) {
2602                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2603                                                    dcerpc_server_name(p), name);
2604         } else {
2605                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2606                                                    dcerpc_server_name(p));
2607         }
2608
2609         r.in.datatype           = NULL;
2610         r.in.devmode_ctr.devmode= NULL;
2611         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2612         r.in.level              = 1;
2613         r.in.userlevel.level1   = &userlevel1;
2614         r.out.handle = handle;
2615
2616         userlevel1.size = 1234;
2617         userlevel1.client = "hello";
2618         userlevel1.user = "spottyfoot!";
2619         userlevel1.build = 1;
2620         userlevel1.major = 2;
2621         userlevel1.minor = 3;
2622         userlevel1.processor = 4;
2623
2624         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2625
2626         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2627
2628         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2629
2630         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2631
2632         return true;
2633 }
2634
2635 static bool test_OpenPrinterEx(struct torture_context *tctx,
2636                                struct dcerpc_pipe *p,
2637                                const char *name)
2638 {
2639         struct policy_handle handle;
2640         bool ret = true;
2641
2642         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2643                 return false;
2644         }
2645
2646         if (!test_GetPrinter(tctx, p, &handle)) {
2647                 ret = false;
2648         }
2649
2650         if (!test_EnumForms(tctx, p, &handle, false)) {
2651                 ret = false;
2652         }
2653
2654         if (!test_AddForm(tctx, p, &handle, false)) {
2655                 ret = false;
2656         }
2657
2658         if (!test_EnumPrinterData(tctx, p, &handle)) {
2659                 ret = false;
2660         }
2661
2662         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2663                 ret = false;
2664         }
2665
2666         if (!test_printer_keys(tctx, p, &handle)) {
2667                 ret = false;
2668         }
2669
2670         if (!test_PausePrinter(tctx, p, &handle)) {
2671                 ret = false;
2672         }
2673
2674         if (!test_DoPrintTest(tctx, p, &handle)) {
2675                 ret = false;
2676         }
2677
2678         if (!test_ResumePrinter(tctx, p, &handle)) {
2679                 ret = false;
2680         }
2681
2682         if (!test_SetPrinterData(tctx, p, &handle)) {
2683                 ret = false;
2684         }
2685
2686         if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2687                 ret = false;
2688         }
2689
2690         if (!torture_setting_bool(tctx, "samba3", false)) {
2691                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2692                         ret = false;
2693                 }
2694         }
2695
2696         if (!test_ClosePrinter(tctx, p, &handle)) {
2697                 ret = false;
2698         }
2699
2700         return ret;
2701 }
2702
2703 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2704 {
2705         struct spoolss_EnumPrinters r;
2706         NTSTATUS status;
2707         uint16_t levels[] = {1, 2, 4, 5};
2708         int i;
2709         bool ret = true;
2710
2711         for (i=0;i<ARRAY_SIZE(levels);i++) {
2712                 union spoolss_PrinterInfo *info;
2713                 int j;
2714                 uint32_t needed;
2715                 uint32_t count;
2716
2717                 r.in.flags      = PRINTER_ENUM_LOCAL;
2718                 r.in.server     = "";
2719                 r.in.level      = levels[i];
2720                 r.in.buffer     = NULL;
2721                 r.in.offered    = 0;
2722                 r.out.needed    = &needed;
2723                 r.out.count     = &count;
2724                 r.out.info      = &info;
2725
2726                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2727
2728                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2729                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2730
2731                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2732                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2733                         data_blob_clear(&blob);
2734                         r.in.buffer = &blob;
2735                         r.in.offered = needed;
2736                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2737                 }
2738
2739                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2740
2741                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2742
2743                 if (!info) {
2744                         torture_comment(tctx, "No printers returned\n");
2745                         return true;
2746                 }
2747
2748                 for (j=0;j<count;j++) {
2749                         if (r.in.level == 1) {
2750                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
2751                                 char *slash, *name;
2752                                 name = unc;
2753                                 if (unc[0] == '\\' && unc[1] == '\\') {
2754                                         unc +=2;
2755                                 }
2756                                 slash = strchr(unc, '\\');
2757                                 if (slash) {
2758                                         slash++;
2759                                         name = slash;
2760                                 }
2761                                 if (!test_OpenPrinter(tctx, p, name)) {
2762                                         ret = false;
2763                                 }
2764                                 if (!test_OpenPrinterEx(tctx, p, name)) {
2765                                         ret = false;
2766                                 }
2767                         }
2768                 }
2769         }
2770
2771         return ret;
2772 }
2773
2774 static bool test_GetPrinterDriver(struct torture_context *tctx,
2775                                   struct dcerpc_pipe *p,
2776                                   struct policy_handle *handle,
2777                                   const char *driver_name)
2778 {
2779         struct spoolss_GetPrinterDriver r;
2780         uint32_t needed;
2781
2782         r.in.handle = handle;
2783         r.in.architecture = "W32X86";
2784         r.in.level = 1;
2785         r.in.buffer = NULL;
2786         r.in.offered = 0;
2787         r.out.needed = &needed;
2788
2789         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2790
2791         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2792                 "failed to call GetPrinterDriver");
2793         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2794                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2795                 data_blob_clear(&blob);
2796                 r.in.buffer = &blob;
2797                 r.in.offered = needed;
2798                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2799                         "failed to call GetPrinterDriver");
2800         }
2801
2802         torture_assert_werr_ok(tctx, r.out.result,
2803                 "failed to call GetPrinterDriver");
2804
2805         return true;
2806 }
2807
2808 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2809                                    struct dcerpc_pipe *p,
2810                                    struct policy_handle *handle,
2811                                    const char *driver_name)
2812 {
2813         struct spoolss_GetPrinterDriver2 r;
2814         uint32_t needed;
2815         uint32_t server_major_version;
2816         uint32_t server_minor_version;
2817
2818         r.in.handle = handle;
2819         r.in.architecture = "W32X86";
2820         r.in.level = 1;
2821         r.in.buffer = NULL;
2822         r.in.offered = 0;
2823         r.in.client_major_version = 0;
2824         r.in.client_minor_version = 0;
2825         r.out.needed = &needed;
2826         r.out.server_major_version = &server_major_version;
2827         r.out.server_minor_version = &server_minor_version;
2828
2829         torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2830
2831         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2832                 "failed to call GetPrinterDriver2");
2833         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2834                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2835                 data_blob_clear(&blob);
2836                 r.in.buffer = &blob;
2837                 r.in.offered = needed;
2838                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2839                         "failed to call GetPrinterDriver2");
2840         }
2841
2842         torture_assert_werr_ok(tctx, r.out.result,
2843                 "failed to call GetPrinterDriver2");
2844
2845         return true;
2846 }
2847
2848 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2849                                         struct dcerpc_pipe *p)
2850 {
2851         struct spoolss_EnumPrinterDrivers r;
2852         NTSTATUS status;
2853         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2854         int i;
2855
2856         for (i=0;i<ARRAY_SIZE(levels);i++) {
2857
2858                 uint32_t needed;
2859                 uint32_t count;
2860                 union spoolss_DriverInfo *info;
2861
2862                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2863                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2864                 r.in.level = levels[i];
2865                 r.in.buffer = NULL;
2866                 r.in.offered = 0;
2867                 r.out.needed = &needed;
2868                 r.out.count = &count;
2869                 r.out.info = &info;
2870
2871                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2872
2873                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2874
2875                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2876
2877                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2878                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2879                         data_blob_clear(&blob);
2880                         r.in.buffer = &blob;
2881                         r.in.offered = needed;
2882                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2883                 }
2884
2885                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2886
2887                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2888
2889                 if (!info) {
2890                         torture_comment(tctx, "No printer drivers returned\n");
2891                         break;
2892                 }
2893         }
2894
2895         return true;
2896 }
2897
2898 static bool test_DeletePrinter(struct torture_context *tctx,
2899                                struct dcerpc_pipe *p,
2900                                struct policy_handle *handle)
2901 {
2902         struct spoolss_DeletePrinter r;
2903
2904         torture_comment(tctx, "Testing DeletePrinter\n");
2905
2906         r.in.handle = handle;
2907
2908         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2909                 "failed to delete printer");
2910         torture_assert_werr_ok(tctx, r.out.result,
2911                 "failed to delete printer");
2912
2913         return true;
2914 }
2915
2916 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2917                                        struct dcerpc_pipe *p,
2918                                        uint32_t flags,
2919                                        uint32_t level,
2920                                        const char *name,
2921                                        bool *found)
2922 {
2923         struct spoolss_EnumPrinters e;
2924         uint32_t count;
2925         union spoolss_PrinterInfo *info;
2926         uint32_t needed;
2927         int i;
2928
2929         *found = false;
2930
2931         e.in.flags = flags;
2932         e.in.server = NULL;
2933         e.in.level = level;
2934         e.in.buffer = NULL;
2935         e.in.offered = 0;
2936         e.out.count = &count;
2937         e.out.info = &info;
2938         e.out.needed = &needed;
2939
2940         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2941                 "failed to enum printers");
2942
2943         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2944                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2945                 data_blob_clear(&blob);
2946                 e.in.buffer = &blob;
2947                 e.in.offered = needed;
2948
2949                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2950                         "failed to enum printers");
2951         }
2952
2953         torture_assert_werr_ok(tctx, e.out.result,
2954                 "failed to enum printers");
2955
2956         for (i=0; i < count; i++) {
2957
2958                 const char *current = NULL;
2959
2960                 switch (level) {
2961                 case 1:
2962                         current = info[i].info1.name;
2963                         break;
2964                 }
2965
2966                 if (strequal(current, name)) {
2967                         *found = true;
2968                         break;
2969                 }
2970         }
2971
2972         return true;
2973 }
2974
2975 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2976                                       struct dcerpc_pipe *p,
2977                                       const char *printername,
2978                                       bool ex)
2979 {
2980         WERROR result;
2981         struct spoolss_AddPrinter r;
2982         struct spoolss_AddPrinterEx rex;
2983         struct spoolss_SetPrinterInfoCtr info_ctr;
2984         struct spoolss_SetPrinterInfo1 info1;
2985         struct spoolss_DevmodeContainer devmode_ctr;
2986         struct sec_desc_buf secdesc_ctr;
2987         struct spoolss_UserLevelCtr userlevel_ctr;
2988         struct policy_handle handle;
2989         bool found = false;
2990
2991         ZERO_STRUCT(devmode_ctr);
2992         ZERO_STRUCT(secdesc_ctr);
2993         ZERO_STRUCT(userlevel_ctr);
2994         ZERO_STRUCT(info1);
2995
2996         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2997
2998         /* try to add printer to wellknown printer list (level 1) */
2999
3000         userlevel_ctr.level = 1;
3001
3002         info_ctr.info.info1 = &info1;
3003         info_ctr.level = 1;
3004
3005         rex.in.server = NULL;
3006         rex.in.info_ctr = &info_ctr;
3007         rex.in.devmode_ctr = &devmode_ctr;
3008         rex.in.secdesc_ctr = &secdesc_ctr;
3009         rex.in.userlevel_ctr = &userlevel_ctr;
3010         rex.out.handle = &handle;
3011
3012         r.in.server = NULL;
3013         r.in.info_ctr = &info_ctr;
3014         r.in.devmode_ctr = &devmode_ctr;
3015         r.in.secdesc_ctr = &secdesc_ctr;
3016         r.out.handle = &handle;
3017
3018         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3019                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3020                 "failed to add printer");
3021         result = ex ? rex.out.result : r.out.result;
3022         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3023                 "unexpected result code");
3024
3025         info1.name = printername;
3026         info1.flags = PRINTER_ATTRIBUTE_SHARED;
3027
3028         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3029                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3030                 "failed to add printer");
3031         result = ex ? rex.out.result : r.out.result;
3032         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3033                 "unexpected result code");
3034
3035         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3036            better do a real check to see the printer is really there */
3037
3038         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3039                                                         PRINTER_ENUM_NETWORK, 1,
3040                                                         printername,
3041                                                         &found),
3042                         "failed to enum printers");
3043
3044         torture_assert(tctx, found, "failed to find newly added printer");
3045
3046         info1.flags = 0;
3047
3048         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3049                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3050                 "failed to add printer");
3051         result = ex ? rex.out.result : r.out.result;
3052         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3053                 "unexpected result code");
3054
3055         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3056            better do a real check to see the printer has really been removed
3057            from the well known printer list */
3058
3059         found = false;
3060
3061         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3062                                                         PRINTER_ENUM_NETWORK, 1,
3063                                                         printername,
3064                                                         &found),
3065                         "failed to enum printers");
3066 #if 0
3067         torture_assert(tctx, !found, "printer still in well known printer list");
3068 #endif
3069         return true;
3070 }
3071
3072 static bool test_AddPrinter_normal(struct torture_context *tctx,
3073                                    struct dcerpc_pipe *p,
3074                                    struct policy_handle *handle_p,
3075                                    const char *printername,
3076                                    const char *drivername,
3077                                    const char *portname,
3078                                    bool ex)
3079 {
3080         WERROR result;
3081         struct spoolss_AddPrinter r;
3082         struct spoolss_AddPrinterEx rex;
3083         struct spoolss_SetPrinterInfoCtr info_ctr;
3084         struct spoolss_SetPrinterInfo2 info2;
3085         struct spoolss_DevmodeContainer devmode_ctr;
3086         struct sec_desc_buf secdesc_ctr;
3087         struct spoolss_UserLevelCtr userlevel_ctr;
3088         struct policy_handle handle;
3089         bool found = false;
3090
3091         ZERO_STRUCT(devmode_ctr);
3092         ZERO_STRUCT(secdesc_ctr);
3093         ZERO_STRUCT(userlevel_ctr);
3094
3095         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3096
3097         userlevel_ctr.level = 1;
3098
3099         rex.in.server = NULL;
3100         rex.in.info_ctr = &info_ctr;
3101         rex.in.devmode_ctr = &devmode_ctr;
3102         rex.in.secdesc_ctr = &secdesc_ctr;
3103         rex.in.userlevel_ctr = &userlevel_ctr;
3104         rex.out.handle = &handle;
3105
3106         r.in.server = NULL;
3107         r.in.info_ctr = &info_ctr;
3108         r.in.devmode_ctr = &devmode_ctr;
3109         r.in.secdesc_ctr = &secdesc_ctr;
3110         r.out.handle = &handle;
3111
3112  again:
3113
3114         /* try to add printer to printer list (level 2) */
3115
3116         ZERO_STRUCT(info2);
3117
3118         info_ctr.info.info2 = &info2;
3119         info_ctr.level = 2;
3120
3121         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3122                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3123                 "failed to add printer");
3124         result = ex ? rex.out.result : r.out.result;
3125         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3126                 "unexpected result code");
3127
3128         info2.printername = printername;
3129
3130         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3131                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3132                 "failed to add printer");
3133         result = ex ? rex.out.result : r.out.result;
3134
3135         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3136                 struct policy_handle printer_handle;
3137
3138                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3139                         "failed to open printer handle");
3140
3141                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3142                         "failed to delete printer");
3143
3144                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3145                         "failed to close server handle");
3146
3147                 goto again;
3148         }
3149
3150         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3151                 "unexpected result code");
3152
3153         info2.portname = portname;
3154
3155         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3156                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3157                 "failed to add printer");
3158         result = ex ? rex.out.result : r.out.result;
3159         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3160                 "unexpected result code");
3161
3162         info2.drivername = drivername;
3163
3164         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3165                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3166                 "failed to add printer");
3167         result = ex ? rex.out.result : r.out.result;
3168         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3169                 "unexpected result code");
3170
3171         info2.printprocessor = "winprint";
3172
3173         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3174                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3175                 "failed to add printer");
3176         result = ex ? rex.out.result : r.out.result;
3177         torture_assert_werr_ok(tctx, result,
3178                 "failed to add printer");
3179
3180         *handle_p = handle;
3181
3182         /* we are paranoid, really check if the printer is there now */
3183
3184         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3185                                                         PRINTER_ENUM_LOCAL, 1,
3186                                                         printername,
3187                                                         &found),
3188                         "failed to enum printers");
3189         torture_assert(tctx, found, "failed to find newly added printer");
3190
3191         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3192                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3193                 "failed to add printer");
3194         result = ex ? rex.out.result : r.out.result;
3195         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3196                 "unexpected result code");
3197
3198         return true;
3199 }
3200
3201 static bool test_AddPrinterEx(struct torture_context *tctx,
3202                               struct dcerpc_pipe *p,
3203                               struct policy_handle *handle_p,
3204                               const char *printername,
3205                               const char *drivername,
3206                               const char *portname)
3207 {
3208         bool ret = true;
3209
3210         if (!torture_setting_bool(tctx, "samba3", false)) {
3211                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3212                         torture_comment(tctx, "failed to add printer to well known list\n");
3213                         ret = false;
3214                 }
3215         }
3216
3217         if (!test_AddPrinter_normal(tctx, p, handle_p,
3218                                     printername, drivername, portname,
3219                                     true)) {
3220                 torture_comment(tctx, "failed to add printer to printer list\n");
3221                 ret = false;
3222         }
3223
3224         return ret;
3225 }
3226
3227 static bool test_AddPrinter(struct torture_context *tctx,
3228                             struct dcerpc_pipe *p,
3229                             struct policy_handle *handle_p,
3230                             const char *printername,
3231                             const char *drivername,
3232                             const char *portname)
3233 {
3234         bool ret = true;
3235
3236         if (!torture_setting_bool(tctx, "samba3", false)) {
3237                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3238                         torture_comment(tctx, "failed to add printer to well known list\n");
3239                         ret = false;
3240                 }
3241         }
3242
3243         if (!test_AddPrinter_normal(tctx, p, handle_p,
3244                                     printername, drivername, portname,
3245                                     false)) {
3246                 torture_comment(tctx, "failed to add printer to printer list\n");
3247                 ret = false;
3248         }
3249
3250         return ret;
3251 }
3252
3253 static bool test_printer_info(struct torture_context *tctx,
3254                               struct dcerpc_pipe *p,
3255                               struct policy_handle *handle)
3256 {
3257         bool ret = true;
3258
3259         if (!test_PrinterInfo(tctx, p, handle)) {
3260                 ret = false;
3261         }
3262
3263         if (!test_SetPrinter_errors(tctx, p, handle)) {
3264                 ret = false;
3265         }
3266
3267         return ret;
3268 }
3269
3270 static bool test_EnumPrinterKey(struct torture_context *tctx,
3271                                 struct dcerpc_pipe *p,
3272                                 struct policy_handle *handle,
3273                                 const char *key_name,
3274                                 const char ***array)
3275 {
3276         struct spoolss_EnumPrinterKey r;
3277         uint32_t needed;
3278         struct spoolss_StringArray2 key_buffer;
3279
3280         r.in.handle = handle;
3281         r.in.key_name = key_name;
3282         r.in.offered = 0;
3283         r.out.key_buffer = &key_buffer;
3284         r.out.needed = &needed;
3285
3286         torture_comment(tctx, "Testing EnumPrinterKey(%s)\n", r.in.key_name);
3287
3288         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3289                 "failed to call EnumPrinterKey");
3290         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3291                 torture_assert(tctx, (key_buffer._ndr_size == 0),
3292                         talloc_asprintf(tctx, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer._ndr_size));
3293                 r.in.offered = needed;
3294                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3295                         "failed to call EnumPrinterKey");
3296         }
3297         torture_assert_werr_ok(tctx, r.out.result,
3298                 "failed to call EnumPrinterKey");
3299
3300         torture_assert(tctx, (key_buffer._ndr_size * 2 == needed),
3301                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3302                 key_buffer._ndr_size, needed/2));
3303
3304         if (array) {
3305                 *array = key_buffer.string;
3306         }
3307
3308         return true;
3309 }
3310
3311 bool test_printer_keys(struct torture_context *tctx,
3312                        struct dcerpc_pipe *p,
3313                        struct policy_handle *handle)
3314 {
3315         const char **key_array = NULL;
3316         int i;
3317
3318         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3319                 "failed to call test_EnumPrinterKey");
3320
3321         for (i=0; key_array && key_array[i]; i++) {
3322                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3323                         "failed to call test_EnumPrinterKey");
3324         }
3325         for (i=0; key_array && key_array[i]; i++) {
3326                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3327                         "failed to call test_EnumPrinterDataEx");
3328         }
3329
3330         return true;
3331 }
3332
3333 static bool test_printer(struct torture_context *tctx,
3334                          struct dcerpc_pipe *p)
3335 {
3336         bool ret = true;
3337         struct policy_handle handle[2];
3338         bool found = false;
3339         const char *drivername = "Microsoft XPS Document Writer";
3340         const char *portname = "LPT1:";
3341
3342         /* test printer created via AddPrinter */
3343
3344         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3345                 return false;
3346         }
3347
3348         if (!test_printer_info(tctx, p, &handle[0])) {
3349                 ret = false;
3350         }
3351
3352         if (!test_printer_keys(tctx, p, &handle[0])) {
3353                 ret = false;
3354         }
3355
3356         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3357                 ret = false;
3358         }
3359
3360         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3361                                         TORTURE_PRINTER, &found)) {
3362                 ret = false;
3363         }
3364
3365         torture_assert(tctx, !found, "deleted printer still there");
3366
3367         /* test printer created via AddPrinterEx */
3368
3369         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3370                 return false;
3371         }
3372
3373         if (!test_printer_info(tctx, p, &handle[1])) {
3374                 ret = false;
3375         }
3376
3377         if (!test_printer_keys(tctx, p, &handle[1])) {
3378                 ret = false;
3379         }
3380
3381         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3382                 ret = false;
3383         }
3384
3385         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3386                                         TORTURE_PRINTER_EX, &found)) {
3387                 ret = false;
3388         }
3389
3390         torture_assert(tctx, !found, "deleted printer still there");
3391
3392         return ret;
3393 }
3394
3395 bool torture_rpc_spoolss(struct torture_context *torture)
3396 {
3397         NTSTATUS status;
3398         struct dcerpc_pipe *p;
3399         bool ret = true;
3400         struct test_spoolss_context *ctx;
3401
3402         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3403         if (!NT_STATUS_IS_OK(status)) {
3404                 return false;
3405         }
3406
3407         ctx = talloc_zero(torture, struct test_spoolss_context);
3408
3409         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3410         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3411         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3412         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3413         ret &= test_EnumPorts(torture, p, ctx);
3414         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3415         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3416         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3417         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3418         ret &= test_EnumMonitors(torture, p, ctx);
3419         ret &= test_EnumPrintProcessors(torture, p, ctx);
3420         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3421         ret &= test_EnumPrinters(torture, p, ctx);
3422         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3423         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3424         ret &= test_OpenPrinter_badname(torture, p, "");
3425         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3426         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3427         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3428         ret &= test_OpenPrinter_badname(torture, p,
3429                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3430
3431
3432         ret &= test_AddPort(torture, p);
3433         ret &= test_EnumPorts_old(torture, p);
3434         ret &= test_EnumPrinters_old(torture, p);
3435         ret &= test_EnumPrinterDrivers_old(torture, p);
3436
3437         return ret;
3438 }
3439
3440 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3441 {
3442         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3443
3444         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3445                                                         "printer", &ndr_table_spoolss);
3446
3447         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3448
3449         return suite;
3450 }