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